Wednesday, June 9, 2010

Liefray: Using JSONObject for Ajax in Plugin Portlet...

Many times we face situations when we need to use Ajax call from JSP pages. Using jQuery, its very easy to call any JSP through AJAX. You can just call the JSP and show its response from callback into some DOM element.

 $.ajax({  
      type: 'POST',  
      url: getUrl(),  
      data: {},                                   
      success: function(returnData) {  
          $('#someElementId').html(returnData);  
      }  
     });  

But this is useful when you want some big data OR some complex UI layout which is hard to generate using callback javascript function. Simple we call the JSP in which we have already designed the layout properly so we don't need to bother about manipulating the returnData in javascript.

Now think if you only need some small amount of data from server side, how will go? Making a new JSP for such a small task is not worhty i think. One technology is there for our help,JSON. JSON is a simple string notation of any object, which represents key-value pair like hashmap but uses its own structure to define objects.

Liferay provides com.liferay.portal.struts.JSONAction class which is a struts Action class. But to use this one in portlet we need to configure the portlet as a com.liferay.portlet. But there is one more way to use JSON with plugin portlet, using overriding serveResource method from GenericPortlet class into your portlet class.

 protected void getSomeDataAsJson(ResourceRequest request, ResourceResponse response)  
 throws PortletException, IOException {  
     String myParam = ParamUtil.getString(request, "myParam","");  
     // Some service call using params from request...  
     Obj obj = getDataFromSomeService(myParam);  
     JSONObject jsonObj = JSONFactoryUtil.createJSONObject();  
     // obj can be anything... Integer,Boolean,String or some custom POJO...  
     jsonObj.put("testData", obj);  
     OutputStream os = response.getPortletOutputStream();  
     try {  
         os.write(jsonObj.toString().getBytes());  
     }  
     finally {  
         os.close();  
     }  
 }  
 @Override  
 public void serveResource(ResourceRequest request, ResourceResponse response)  
         throws PortletException, IOException {  
     String cmd = ParamUtil.getString(request,Constants.CMD);  
     if ("getSomeDataAsJson".equals(cmd)) {  
         getSomeDataAsJson(request, response);  
     }  
 }  

The above method will provide the JSON object as a result in javascript callback function. Check the Ajax call,

 $("input:button[@name='<portlet:namespace />SomeThing']").click (function() {  
     $('#<portlet:namespace />myDiv').text("");  
     //URL which goes to your portlet...  
     var url = "<portlet:resourceURL><portlet:param name='<%=Constants.CMD %>' value='getSomeDataAsJson' /></portlet:resourceURL>";      
     //Append your hidden input fields in the resourceURL...   
     url +="&"+$('input:hidden').serialize();   
     $.ajax({  
             url: url,  
             data: {},  
             dataType: 'json',  
             success: function(message) {  
                     $('#<portlet:namespace />myDiv').text(message.testData);  
                     }  
             }  
         );      
     });  

This way we don't need to create JSPs for small data fetching. Show other ways also using simple AJAX calling (Like DWR supports, direct calling JAVA class method from JS and returns data in JS callback).

2 Comments:

ArrayLust said...

Just what I was looking for. Thanks for sharing.

Anonymous said...

thanx