Portlet specification defines various phases of portlet like render, action, serve-resource, event etc. Passing information from one phase to another(e.g passing information from action to render) is common scenario. When portlet completes the action phase, portal container will call its render phase (along with render phase of all portlet on same page).
Many a times, you need to pass some information from action to render phase. For example, you are adding student details in DB.
To achieve this you need to create html form (with student details like name, standard DOB etc) with action URL. When user submit the form, these data (student information) will be available in action method where you perform CRUD operation to add student.
As per portlet specification, soon after action phase completes, portal container will trigger its render phase(by calling render method).
Assume that you want to show success message like “<<NAME OF STUDENT>> is added successfully” in portlet JSP (view.jsp).
For this student name should be available in render method. But you are getting student name (along with other information) in action method. So you need to pass student name from action method to render method.
I will be showing how to pass data from action to render phase by creating Liferay MVC Portlet. I took plugin project name as action-to-render and -portlet will be appended by Liferay IDE while creating plugin project.
I gave portlet class as com.opensource.techblog.portlet.ActionToRenderPortlet. After this the project structure looks like below screenshot.
Add following code in the view.jsp
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %> <portlet:defineObjects /> <portlet:actionURL name="sampleActionMethod1" var="sampleActionURL"> </portlet:actionURL> <form action="${sampleActionURL}" method="post"> Student Information <br> Name:<input type="text" name="<portlet:namespace/>name"> Standard:<input type="text" name="<portlet:namespace/>std"> <input type="submit" name="Add Student"> </form>
Explanation
- To understand how and from where to pass the information from action to render, I mimic the code to add students here.
- So in this JSP, I have created one HTML form with action URL. In this HTML form, I am taking student name and standard.
- When a user submits this form, this information (name and standard) will be sent to the action method to add student information in DB.
Now add following code in ActionToRenderPortlet class
package com.opensource.techblog.portlet; import java.io.IOException; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.PortletException; import javax.portlet.ProcessAction; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.util.bridges.mvc.MVCPortlet; public class ActionToRenderPortlet extends MVCPortlet { private static Log _log = LogFactoryUtil.getLog(ActionToRenderPortlet.class.getName()); @Override public void render(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException { String studentName = ParamUtil.get(renderRequest, "studentName", ""); _log.info("studentName in render is ==>"+studentName); renderRequest.setAttribute("studentName", studentName); super.render(renderRequest, renderResponse); } @ProcessAction(name="sampleActionMethod1") public void sampleActionMethod1(ActionRequest actionRequest, ActionResponse actionResponse) throws PortletException, IOException { String studentName = ParamUtil.get(actionRequest, "name", ""); String standard = ParamUtil.get(actionRequest, "std", ""); /** * code to add Student here..... */ } }
Explanation
- I have added an action method which will be called when the user submits the form (triggered through action URL bind to that form)
- In this action method, I am reading request parameter name (student name) and standard. (I used ParamUtil class to read the request parameters)
- The comment – “code to add student here” would be actual code to save student detail in DB. To make it simple, I haven’t put actual code. Our main goal is to see how to pass information from the render to the action phase.
- In the render method, I am reading studentName parameter and storing it in the request attribute so that I can use it in view.jsp (through EL – expression language) to show a success message with the student name.
- Portal will call render phase (method) after completion of action phase(method). I am reading name(student name) parameter in action method which will not be available to render method by default. (at this point try yourself reading name(student name) request param in render method and you will get null /empty value).
- In Liferay we can pass information from action to render by different approaches / mechanisms.
Various mechanisms to pass information from Action to Render Phase
There are many ways to pass information from action to render phase. In this article, we will see each of them.
Approach:-1 By setting render parameter in actionResponse object
In this approach, you can pass information from action to render by setting it in render parameter in action method. Let’s do it practically. Add following code at the end of action method (after the comment)
//Setting student name in ActionResponse so that it will be available in render method. actionResponse.setRenderParameter("studentName", studentName);
Explanation
- What we are doing is passing the value of the parameter (which we already read from ActionRequest object and stored in variable studentName) into ActionResponse object by calling it’s setRenderParameter method.
- This method is overloaded and it has following variants.
- actionResponse.setRenderParameter(key, value) :- will be used to pass key and its value.
- actionResponse.setRenderParameter(key, values[]) :- will be used to pass key and multiple values
- actionResponse.setRenderParameters(Map<Key,values[]>) :- will be used to pass map of keys with its multiple values.
- Here all parameters type would be of String
- Note: You can access this parameter in the render method by the same key name that you passed in the action method.
- Pros
- It’s very easy to use
- Cons
- For each separate parameter that you want to pass from action to render phase, you have to make separate actionResponse.setRenderParameter method call.
- Since it’s a parameter, you only can pass an object of type String from render to action phase
Approach:-2 By setting init parameter ‘copy-request-parameters’ in portlet.xml file.
This approach talks about sending information from action to render by just doing configuration change. Add following init parameter in portlet.xml file
<init-param> <name>copy-request-parameters</name> <value>true</value> </init-param>
Explanation
- What does this mean? We are instructing the portal to pass all parameters from action to render phase for that portlet. In other words, by default all render parameters would be available to the render method as well for that portlet.
- Try yourself by first removing all actionResponse.setRenderParameter and then put the above code in portlet.xml. You will observe that all parameters that are available in the action method are also available in the render method and you no need to do any extra things.
- Pros
- You do not need to make a separate actionResponse.setRenderParameter call for each parameter.
- Cons
- Since it’s a parameter, you only can pass an object of type String from render to action phase
- You need to pay special attention while using this approach.
- When you set copy-request-parameters to true for any portlet, then the portal will remember all such parameters of that portlet for any further execution.
- What does this mean ? Let’s understand this by example. Assume that there are 2 portlets placed on page. Out of them, one we have already seen above, I am calling it portlet-1. Assume that second portlet has just one link (render URL). When a user clicks on this link, the portal will call the render method of the second portlet along with the render method of the first portlet (portlet 1) as well.
- But for portlet 1 (just we seen above to add student details), the portal will remember the parameter which was added in action method of portlet 1 so it will print a success message every time a user clicks on the link on the second portlet (portlet-2)
- When a user manually refreshes the page or do any direct interaction with portlet-1 then only it will remove those render parameter.
- So in case if you don’t wish to retain such render parameters in the render method while interacting with other portlets, then you need to manually call actionResponse.setRenderPamater method for each such parameter instead of setting copy-request-parameters value in portlet.xml file.
Approach:-3 passing information by setting it in the request attribute.
In this approach, you need to simply add your information in the request scope to pass it from action to render phase. For example, add following code in action method.
actionRequest.setAttribute("standard", standard);
Explanation:
- we can set the information in request attribute by calling actionRequest.setAttribute(KEY,VALUE).
- As stated in this blog, the portal will call the render method just after it completes the execution of the action method. So if you wish to access your information, you need to simply call renderRequest.getAttribute(KEY). You need to pass the same KEY which you used while adding it in the request attribute in the action method.
- to understand it properly, I am passing the standard in the request attribute. If you wish to read it in the render method, you need to call renderRequest.getAttribute(“standard”).
- Pros
- You can pass any object (not only String) from action to render method.
- It’s very simple to use. Any parameter which is stored in the request parameter will be available in JSP as well. so you can directly access them by EL (Expression Language)
- Cons
- For each object you wish to pass from action to render, you need to make a separate call for actionRequest.setAttribute method.
Summing UP
- Passing information across the portlet phase is a common scenario. As per portlet specification, the portal will call the render method soon after the execution of the action method completes.
- You can pass information from action to render method by
- adding parameter by calling actionResponse.setRenderParameter
- setting init parameter copy-request-parameters to true in portlet.xml file
- setting information in request attribute by calling actionRequest.setAttribute method.
- You can refer to this link for more information.
Download Source – Liferay 6.2