Tuesday, September 7, 2010

Liferay Struts Portlet: Usage of SessionErrors class...

This is very common issues we come across when we want to change portal code with extension environment. Mostly we do is, copying the code from portal to ext and making new struts portlet.

And for sending errors to pages, we use SessionErrors.add(...) method, which will eventually forward to default error.jsp file. So you will never find what is happening. Simple thing, to make this working fine, is...

- Make new empty page named error.jsp in your portlet.
- Make new Struts-config and tiles-def entry of your new JSP in ext.
- From your render method, forward to the new file when you have SessionErrors filled with errors like,

 if (!SessionErrors.isEmpty(req)) {
  return mapping.findForward("portlet.portlet_name.error");
 }
 

See this link to understand the detailed problem...

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).

Thursday, May 1, 2008

Using Struts tags - <logic:iterate>,<logic:equal>,<bean:write>

I was wondering what should i write about now.And suddenly i got this to do.
I have a small change in the jsp which is made using struts framework.In struts, there are many tags which are easy to use and generate output fast.easy to write.

In struts, we have ActionServlet,Action classes and ActionForms.

ActionServlet will transfer the request to ActionServlet with ActionForms containing all the HTML form data.so you can access any data of the of ActionForm from Servlet request.

See the below code.then we will talk regarding it.

<select name="sel1" id="selTestStruts" style="width:90px;">
<option value="0" selected="selected">Please Select
<logic:iterate id="myBean" name="someForm" property="someFormProp1">
<logic:equal value="test" property="someStrPropOfMyBean" name="myBean">
<option value='<bean:write name="myBean" property="someStrPropOfMyBean"/>'><bean:write name="myBean" property="someNamePropOfMyBean"/></option>
</logic:equal>
</logic:iterate>
</select>


here we are trying to fill HTML select box using struts' <logic:iterate>, <logic:equal><bean:write> tags.

<logic:iterate> will iterate on 'someFormProp1' of 'someForm' which is in the http request.it will make 'myBean' from property 'someFormProp1' which is a List of some data.

You can simply write any property from that 'myBean' we made above.But i also shown here how you can put logic to seperate things on some property value so you don't need to put logic in the SP or generate another property for it.

<logic:equal> checks the value of property named 'someStrPropOfMyBean' with the string given in 'value="test"' attribute (means with 'test' here). If the value matches then only it will make new <option> for <select> box.

same thing you can do with not including some specific value match using <logic:notEqual>

<bean:write> tag will simply write property 'someStrPropOfMyBean' of 'myBean' which is a object of some Value Object class from the List property 'someFormProp1' of 'someForm'.

Though this is very simple thing but i write because may be this can be helpful to some newbies.