<img height="1" width="1" style="display:none;" alt="" src="https://px.ads.linkedin.com/collect/?pid=299788&amp;fmt=gif">

Portlet Basics: Passing Objects

Software Development, Portal, Software Solutions

HOW TO PASS OBJECTS FROM ACTION TO RENDER LIFECYCLES

Hello and welcome to another short portlet lesson. This one is aimed at beginning portlet developers! I will concentrate on one of the basics of portlet development: passing objects from the action to the render lifecycle. I will show you how to set these objects in the action phase and how to pull them off during the render phase in the portlet and its included JSP. Seems fairly simple and straightforward, so why write this up?

MOTIVATION

The reason I've written this blog is to help portlet developers who may not have absorbed this information. These developers often stuff their object values into parameter and attribute set methods, and whatever else they can find in the code in hope of pulling them off in their doView render methods and JSPs. When I first started out, it took me awhile to absorb this information as it's a topic that's often spread around in most portlet documentation. It's my hope that putting these all in one place will help you easily digest what options are available for passing information forward.

WHAT ARE THE ACTION AND RENDER LIFECYCLES?

For those of you JEE web developers that haven't used portlets, the action and render lifecycles (phases) are two of four lifecycles used in a portlet application (others consist of event and resource cycles). The way the action and render lifecycles work is in the style of the Post/Redirect/Get web development pattern. A simple example of this would be submitting a form POST that would be processed in the action lifecycle on the portal. It is followed by a redirect getting a view result, which is repeatable from the render phase to display to the user. By repeatable, I mean a browser refresh can execute the render phase again, building the page with all parameters still available.
As you can see, these two lifecycles have a clear separation of duties. Even so, updates are generally reflected on that view. Thus, information will often need to be passed from action to render (i.e. when a database update is performed in the action phase which then needs to display a confirmation message to the user in the render phase).
Below are the proper methods for setting and retrieving objects, each with their own benefits and drawbacks.

RENDER PARAMETERS

This is the staple method for passing values from action to render. These are known as private render parameters if they are only used within the portlet, or public render parameters if they are shared with other portlets (though additional setup is required in the portlet.xml file for public). Even though the only object type allowed to be set in render parameters is String and String arrays, it is often all that is needed in order to generate the objects used during the render phase.
A nice benefit of render parameters is they're automatically encoded within a portlet resourceURL tag declaration (for AJAX calls and resource downloads) in a JSP to avoid duplication of effort. The same behavior can be achieved in renderURL and actionURL tags by setting the 'copyCurrentRenderParameters' parameter to 'true' inside the tag. This allows you to avoid re-coding all the parameters that need to be sent back to the portal during one of these requests.
These render parameters are cleared out when new render and action requests, as well as event updates, are made to the portal. So, if your render view code depends on them, make sure they're set and available.
All code examples below follow the same pattern. It shows how to set the objects in the action phase and how to pull them in during the render phase, both inside the doView method and JSPs. The JSP examples assume use of JSTL.

Action phase:

[java]
@ProcessAction(name="myAction")
public void processMyAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException {
// render param for single String
String paramString = "a String";
response.setRenderParameter("stringParam", paramString);
// render param for String Array
String[] paramArray = {"String 1", "String 2"};
response.setRenderParameter("arrayParam", paramArray);
// render params for Map of String param keys to String Array values
// NOTE: this will remove render parameters already placed in previously
Map<String,String[]> paramMap = new HashMap<String,String[]>();
paramMap.put("mapParam1", new String[]{"String 1", "String 2"});
paramMap.put("mapParam2", new String[]{"String 3", "String 4"});
response.setRenderParameters(paramMap);
}
[/java]

Render phase:

[java]
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
String paramString = request.getParameter("stringParam");
String[] paramArray = request.getParameterValues("arrayParam");
Map<String,String[]> paramMap = request.getParameterMap();
}
[/java]

Render phase (JSP):

[xml]
String: ${param.stringParam}<br/>
Alternate Notation: ${param['stringParam']}<br/>
Array (alternate notation is also applicable):
<c:forEach var="aValue" items="${paramValues.arrayParam}">
${aValue}
</c:forEach>
[/xml]
As you see, it's pretty straightforward. In the action method, variations of the 'setRenderParameter' method are used to set either string, string array or a map of string arrays on the ActionResponse object. These are pulled into the doView method from the RenderRequest object's 'getParameter' methods. The JSPs use the implicit 'param' object for retrieval of values.

ACTION SCOPED REQUEST ATTRIBUTES

A new method for passing objects was introduced in Portlet 2.0 (JSR 286) – action scoped request attributes. This technique allows full objects to be set in the action request and pulled off in the render request. Behind the scenes, it automatically stores this object in the session on a temporary basis until the next action request is received, so it's important to make sure that object is Serializable. Please note that in the JSPs, the attributes can be pulled off the scope (portletRequestScope) directly or without use of the scope, which will search the scopes for your object reference (my preferred way).
In order to use this feature, make sure your portal server supports it. Even though it is a required feature in the portlet spec, some portals don't handle it or have alternative ways of handling it.
Add the container runtime option in portlet.xml (at bottom of <portlet> or <portlet-app> declaration).  To note 'numberOfCachedScopes' is to address how many are cached in case the back button is used.
[xml]
<container-runtime-option>
<name>javax.portlet.actionScopedRequestAttributes</name>
<value>true</value>
<value>numberOfCachedScopes</value>
<value>10</value>
</container-runtime-option>
[/xml]

Action phase:

[java]
@ProcessAction(name="myAction")
public void processMyAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException {
Foo foo = new Foo(); // has method getFooValue()
request.setAttribute("objAttribute", foo);
}
[/java]

Render phase:

[java]
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
Foo foo = (Foo)request.getAttribute("objAttribute");
foo.getFooValue();
}
[/java]

Render phase (JSP):

[xml]
Object: ${objAttribute.fooValue}<br/>
Object: ${portletRequestScope.objAttribute.fooValue}<br/>
[/xml]
As you see, the action scope request attributes are a bit different in use than the render parameters, requiring the setup of the container runtime options on the portlet.xml file on a portal server that supports it. Then, in the action method, the 'setAttribute' method is used to set objects on the ActionRequest object. The doView method calls the corresponding 'getAttribute' method on the RenderRequest object to get the values. The values are pulled in the JSPs using either the direct or indirect method.

Storing on Session

Storing objects on the session provides another means of passing information from action to render, although not the most efficient. It is more appropriate for user actions spanning multiple requests. Even so, it is possible to lose context if the user enjoys the back button. Further drawbacks to using a session include the additional code required to remove objects out of the session as needed and using additional memory.

Action phase:

[java]
@ProcessAction(name="myAction")
public void processMyAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException {
Foo anyObject = new Foo(); // has method getFooValue()
PortletSession session = request.getPortletSession();
session.setAttribute("objAttribute", anyObject);
}
[/java]

Render phase:

[java]
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
PortletSession session = request.getPortletSession();
Foo object = (Foo)session.getAttribute("objAttribute");
}
[/java]

Render phase (JSP):

[xml]
Object: ${objAttribute.fooValue}<br/>
Object: ${portletSessionScope.objAttribute.fooValue}<br/>
[/xml]
The session method of passing objects pretty much mirrors the action scope request attributes in the use of their methods. In general, I try to use the session scope as little as possible in order to avoid bloat in both use of memory and extra code to maintain it.
I hope this has helped some portlet beginners out there get a clearer picture of how to pass information in portlets. There are other mechanisms that can be used in frameworks like the Spring Portlet MVC that supplement these, but I'll have to save that for later.  End of lesson!

TAGS: Software Development, Portal, Software Solutions

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Subscribe to Our Newsletter

Recent Blog Posts