Oracle9iAS Portal Developer Kit
Adding Session Storage

In previous articles, you learned how to use the PDK-Java Framework to render portlet content in various render modes and how to implement features such as customization. This article shows you how to implement session storage for your portlet. A session object is used to maintain state between requests from the Oracle9iAS Portal to the Provider. Without the session concept, it would be no mechanism to associate one communication with another. PDK-Java maintains sessions based on the ProviderUser abstraction.

In this article, you will use session storage to count the number of times your portlet has rendered in Show Details mode. You will add functionality to the Java Servlet created in the article Adding Extra Render Modes.

ASSUMPTIONS

1. You have followed through and understood these articles:

   - How to Build a Java Portlet

   - Adding Extra Render Modes

2. All the assumptions described in the above articles apply here too.

IMPLEMENTING SESSION STORAGE

The PDK-Java Framework represents the session with a ProviderSession object, which is established during the call to the Provider's initSession method. This object is associated with the ProviderUser. To make data persistent between requests from Oracle9iAS Portal, you need to write data into the session object using the setAttribute method on the ProviderSession object. This method maps a java.lang.Object to a java.lang.String and stores that mapping inside the session object. The String can then be used to retrieve the Object during a subsequent request, provided the session is still valid.

A session may become invalid for the following reasons:

- session times out

- invalidate method on ProviderSession is called

- JVM process running the servlet container is terminated.

All portlets contained by the same Provider share the same session for a particular ProviderUser. Therefore, data unique to a particular portlet must be mapped to a unique String in the session. This is accomplished using the portletParameter method in the PortletRendererUtil class. This method concatenates the unique PortletReference with a supplied String and returns a String unique to that portlet. This String should be used to write portlet specific data into the session. For more detailed information on the PDK-Java Framework classes, refer to the JavaDoc.

Follow these steps below to implement a render count in your portlet, using session storage.

1. Using your favorite text editor, open the source code MyShowDetailsServlet.java, i.e. the Java Servlet you created in the article Adding Extra Render Modes.

2. Make the changes shown in bold below.

   Note: The changes include the addition of 'Clear Count' and 'OK' buttons to the Show Details mode.

   >     import java.io.*;

   >     import javax.servlet.*;
   >     import javax.servlet.http.*;

   >     import oracle.portal.provider.v1.*;
   >     import oracle.portal.provider.v1.http.*;

   >     public class MyShowDetailsServlet extends HttpServlet
   >     {

   >         public void doPost(HttpServletRequest request, HttpServletResponse response)
   >             throws ServletException, IOException
   >         {
   >             PrintWriter out = response.getWriter();
   >             PortletRenderRequest pr =
   >                 (PortletRenderRequest)request.getAttribute(HttpProvider.PORTLET_RENDER_REQUEST);

   >             // Get the form's action parameter.
   >             String action = pr.getParameter("details_action");

   >             // If an 'OK' was submitted, redirect back
   >             if (action == null)
   >             {
   >                 String user = pr.getUser().getName();
   >                 out.println("<P>Hi " + user + " !</P>");
   >                 out.println("<P>This is the <I>show details</I> mode of your first portlet.</P>");
   >                 out.println("<P>RenderManager has invoked Servlet20Renderer.</P>");
   >             }
   >             else if (action.equals("OK"))
   >             {
   >                 HttpPortletRendererUtil.sendRedirect(pr, pr.getBackURL());
   >                 return;
   >             }

   >             // Retrieve the session from the PortletRenderRequest
   >             ProviderSession session = pr.getSession();

   >             // If session is valid, retrieve the render count, display it,
   >             // increment the count and store the new count in the session.
   >             if (session != null)
   >             {
   >                 // Obtain the unique String key for this portlet
   >                 PortletReference ref = pr.getPortletReference();
   >                 String key = PortletRendererUtil.portletParameter(ref, "count");

   >                 // Use a primitive int array for performance as it is
   >                 // mutable. First, try to retrieve a previously stored value.
   >                 int[] i = (int[])session.getAttribute(key);

   >                 // If none available, initialize a new count
   >                 if ( i == null)
   >                 {
   >                     i = new int[1];

   >                     // Write it into the session.
   >                     session.setAttribute(key, i);
   >                 }

   >                 // If a 'CLEAR' was submitted, redirect to same page
   >                 if (action != null)
   >                 {
   >                     if (action.equals("CLEAR"))
   >                     {
   >                         i[0] = 0;
   >                         HttpPortletRendererUtil.sendRedirect(pr, pr.getPageURL());
   >                         return;
   >                     }
   >                 }

   >                 // Increment the count
   >                 i[0]++;

   >                 // Display the count.
   >                 out.println("<P>Render count in this session: " + i[0] +
   >                             ".</P>");
   >             }
   >             else
   >             {
   >                 // Display a helpful message informing the user that the
   >                 // session has become invalid.
   >                 out.print("<P>The session has become invalid. ");
   >                 out.print("Please login again.</P>");
   >             }
   >             renderForm(pr, out, session);
   >         }

   >         private void renderForm(PortletRenderRequest pr, PrintWriter out, ProviderSession session)
   >         {
   >             // Render the Form tag.
   >             out.print("<FORM name=\"details_form\" action=\"");
   >             String action =
   >                 PortletRendererUtil.htmlFormActionLink(pr, PortletRendererUtil.PAGE_LINK);
   >             out.print(action);
   >             out.println("\" >");

   >             // Render hidden fields.
   >             String fields =
   >                 PortletRendererUtil.htmlFormHiddenFields(pr, PortletRendererUtil.PAGE_LINK);
   >             out.println(fields);

   >             out.println("<INPUT TYPE=\"hidden\" name=\"details_action\" value=\"\" />");

   >             // Render Javascript to avoid language/value issues
   >             out.println("<SCRIPT LANGUAGE=\"JavaScript1.1\">");
   >             out.println("<!-- Comment out script for old browsers");
   >             out.println("function doSubmit(action) {");
   >             out.println("   document.details_form.details_action.value=action");
   >             out.println("   document.details_form.submit()");
   >             out.println("}");
   >             out.println("//-->");
   >             out.println("</SCRIPT>");

   >             // Render the buttons
   >             if (session != null)
   >             {
   >                 out.print("<INPUT TYPE=\"button\" NAME=\"clear\" VALUE=\"Clear Count\""+
   >                           " onClick=\"javascript:doSubmit('CLEAR')\">");
   >             }
   >             out.print("<INPUT TYPE=\"button\" NAME=\"back\" VALUE=\"OK\""+
   >                       " onClick=\"javascript:doSubmit('OK')\">");

   >             // End the Form tag.
   >             out.println("</FORM>");

   >         }

   >     }

3. Save the changes to MyShowDetailsServlet.java.

4. Follow the steps outlined in the article How to Build a Java Portlet to compile the updated Java Servlet.

   Ensure the class file is accessible from your Oracle HTTP Server's CLASSPATH variable.

5. Restart your Oracle HTTP Server to load the updated version of MyShowDetailsServlet.class.

VIEWING THE PORTLET

If you have not already added MyFirstPortlet to a Portal page, do so now.

1. View the Show Details mode by clicking the hyperlink in the portlet title.

2. Use your browser's refresh button to increment the count.

3. Click the Clear Count button to reset the render count.

4. Click the OK button to return to the original Portal page.

Note: You do not need to update your XML provider definition.

Revision History:

- June, 2001