Liferay GWT portlet - replacing GWT-RPC with JSON
This is a continuation of my previous post Liferay GWT portlet - how to make it "instanceable" and use GWT RPC. The approach described there uses Liferay specific functionality called PortalDelegateServlet. This way one can easily use GWT RPC which somewhat simplifies client-server communication. However if you need to develop a JSR 286 portlet you need a more standard compatible way of doing AJAX calls. For this reason JSR 286 defines serverResource method and this post will show how to refactor the code to replace GWT RPC calls with exchanging JSON messages using serverResource method.
Let GWT know the prtlet URLs
First thing to do is to tell GWT what are the proper URLs to call the portlet. Therefore creating a Chatroom instance based on portlet id only, is no longer enough. To overcome this you need to provide a JavaScript object holding portlet URLs. I, for example, have called it ChatroomPortlet and it's defined in chatrooms.js file.
Then, in view.jsp, create and store that object instead of portlet id. Of course for the purpose of this example only resourceURL is needed but in a real world scenario you'll probably also need renderURL and actionURL. To map this JavaScript object to GWT class create JSNI class ChatroomJsObject
Next you need to modify Chatroom's constructor to accept ChatroomJsObject instead of String representing portlet id. Of course this reflects how GWTEntryPoint creates Chatroom instances.
Have a look at my commit to see what has changed.
Create the JSR 286 portlet
Now you need to write a portlet and implement serveResource method. Basically the method contains the same logic that used to be in ChatroomServiceImpl. The only difference is that now it gets its input form JSON object and responds with JSON object. The portlet code is available here. Of course don't forget to replace the default MVCPortlet with your own in portlet.xml
Again there is commit which does above modifications, so you can check what has changed.
Update GWT client-server calls
Having the portlet ready, it's time to change the GWT code to send and receive JSON to resourceURL instead of using GWT RPC. For this to work you need to add 2 GWT modules to Chatrooms.gwt.xml:
<inherits name="com.google.gwt.http.HTTP" />
<inherits name="com.google.gwt.json.JSON" />
To be able to convert JSON response to GWT class you'll have to provide another JSNI class ChatroomMessageJsObject. Finally the Chatroom class itself needs to be updated:
- replace the body of sendMessageToServer method to create JSON object and send it to the portlet bu using RequestBuilder
- replace the body of getMessages method to covert JSON object from response to list of ChatroomMessageJsObject to be displayed.
- convert lastMessageTime form Date to long as there are some issues with passing dates in JSON
As usual you can refer to my commit to get an idea what and how has changed.
That's it. You are ready. Optionally you can do some cleanup by removing unused classes like I did.