The actionScopedRequestAttributes container runtime option

One common issue in working with standard compliant portlet is how do i pass data from action phase(processAction()) to render phase (render()). In order to take advantage of portlet life cycle normally we should execute the business logic to get data from back end in the processAction() method and then pass the complex object from processAction() to render() method but the problem is the we cannot pass complex object we can only pass string parameters by calling PortletResponse.setRenderParameter() method, only alternative is to use the PortletSession

The Portlet Specification introduced concept of container run time options that allows us to modify/ tune behavior of the portlet container. It introduced a javax.portlet.actionScopedRequestAttributes which is set to false by default, but if you set its value to true then you can set request attribute in the processAction() method and you should be able to access those request attributes in the render() method. These request attributes will be preserved until the next action or event request. One drawback of this approach is the request attributes are stored in PortletSession under the hood and it has performance implications of storing data in portlet session, but positive side this approach is better than storing and removing objects in session by yourself.


I wanted to try this feature so I did create ActionScopeRequestAttributePortelt portlet.

This is how my portlet.xml file looks like

<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
id="com.webspherenotes.jsr286.ActionScopeRequestAttributePortlet.78dbf213e2">
<portlet>
<portlet-name>ActionScopeRequestAttribute</portlet-name>
<display-name xml:lang="en">ActionScopeRequestAttribute</display-name>
<display-name>ActionScopeRequestAttribute</display-name>
<portlet-class>com.webspherenotes.jsr286.ActionScopeRequestAttributePortlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<portlet-info>
<title>ActionScopeRequestAttribute</title>
<short-title>ActionScopeRequestAttribute</short-title>
<keywords>ActionScopeRequestAttribute</keywords>
</portlet-info>
</portlet>
<default-namespace>http://ActionScopeRequestAttribute/</default-namespace>
<container-runtime-option>
<name>javax.portlet.actionScopedRequestAttributes</name>
<value>true</value>
<value>numberOfCachedScopes</value>
<value>10</value>
</container-runtime-option>
</portlet-app>


As you can see the value of actionScopedRequestAttributes is set to true. THis is how the portlet code looks like

package com.webspherenotes.jsr286;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class ActionScopeRequestAttributePortlet extends javax.portlet.GenericPortlet {
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
System.out.println("doView(), Exiting Value of request attribute"
+ request.getAttribute("userName"));

PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher("/action.jsp");
rd.include(request,response);

}
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, java.io.IOException {
System.out.println("processAction(), Exiting Value of request attribute"
+ request.getAttribute("userName"));
System.out.println("Setting request attribute userName to "
+ request.getParameter("userName"));
request.setAttribute("userName", request.getParameter("userName"));
}

}


In the processAction() method i am storing the value of userName submitted by the user as request attribute and then in the .jsp i am just reading the values from renderRequest and display it to user like this


<%@page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" session="false"%>
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
<portlet:defineObjects />
<portlet:actionURL var="actionUrl">
<portlet:param name="action" value="submit" />
</portlet:actionURL>
<form method="post" action="<%=actionUrl %>">
<table>
<tr>
<td>Value stored in request attribute</td>
<td colspan="2">
<%=renderRequest.getAttribute("userName") %>
</td>
</tr>
<tr>
<td>User Name</td>
<td><input type="text" name="userName" /></td>
<td><input type="submit" name="submit" value="Submit" /></td>
</tr>

</table>
</form>


I tried this code in WPS 7.0 and it worked, so i used the How to inspect the values stored in the Portlet Session to check the PortletSession and i can see the com.ibm.ws.portletcontainer.core.action_scope_cache attribute in the PORTLET_SCOPE

5 comments:

  1. One aspect to take in consideration, is that changing the container runtime option to true is not advised by IBM.

    It the following article it identifies to "use this feature only if you cannot avoid it, as it will probably cause some performance degradation".

    http://www.ibm.com/developerworks/websphere/library/techarticles/0803_hepper/0803_hepper.html

    However, I'm not sure if this is still applicable in WPS7, as it does identify this logic is dependent on the portal container and is an old article.

    If you find any additional feedback on this, will be much appreciated.

    Cheers,
    Gab

    ReplyDelete
  2. This feature doesn't seem to working in Websphere portal 7. I tried using container runtime option in both the portlet level and application level. Still there is no effect. Is there anyother configuration that I am missing?

    ReplyDelete
  3. It doesn't work for me too. WPS7

    ReplyDelete