Tutorial:

JSR-286 development tutorial: Data clashes and encoding namespaces

By Cameron McKenzie

TheServerSide.com

The following tutorial, written by Cameron McKenzie and Sal Pece, is the fifth in a series of Portlet 2.0 development tutorials, with this tutorial focussing on the challenge of avoiding variable name conflicts and clashes between various portlets that appear simultaneously on a given portal page. The focus of this tutorial is largely the concept of encoding namespaces using various components from the JSR-286 Portlet 2.0 API.

More Portlet 2.0 development tutorials can be found in the JSR-286 Portlet Development Tutorial and Technology Guide. These tips and tutorials are designed to help software developers  who are interesting in developing JSR-286 programming talents to become competent with basic, intermediate and advanced level portlet programming concepts, helping the IT professional to create portlet-based apps that can be quickly and easily deployed to any of the standards-based portal servers on the market.

 

When a portal page is rendered, the doView method of every portlet on the page is invoked, not just that one portlet with which you might currently be interacting. 

Cameron McKenzie, Editor-in-Chief of TheServerSide

Dealing with data clashes on the portal server

The previous tutorial did a pretty good job of demonstrating the basic concepts and APIs involved in handling web based forms, but a portlet developer with a keen eye would know that there was a troubling little time-bomb hidden in that seemingly innocuous code that was just waiting to explode when the right set of conditions appear at runtime.

Our portlet uses the request.getParameter("number") call to figure out what the user typed into the textfield named 'number'. But remember, our NumberGuesserPortlet isn't necessarily the only portlet on the page.  What if another portlet also uses an HTML form with a textfield named number? That other portlet would get access to our portlet's number, and that isn't good. Furthermore, our portlet might end up reading the number from another portlet on the page and respond to a submission with which it had no business interacting. This isn't a good scenario.

Multiple Portlets and Handling Form Data

Remember, portlets don't exist in a vacuum. The page that contains our NumberGuesserPortlet might also include a StockSellingPortlet that wants to know the number of shares a user wants to sell. That same page might also have a SpousalBenefitsPortlet that needs to know the number of wives or husbands a user has. If each portlet makes a call to request.getParameter("number") in their doView method, each one will get the number that was typed into the form of the NumberGuesserPortlet. When a portal page is rendered, the doView method of every portlet on the page is invoked, not just that one portlet with which you might currently be interacting.

Encoding Form Data with getNamespace( )

To ensure that form data being sent from our portlet to the server doesn't get confused with the form data of another portlet, the RenderResponse object gives us a special method called getNamespace(). This method will return an alpha-numeric character set that uniquely identifies a portlet on a particular page. If we use the getNamespace() call, and attach that identifying String to each data element being sent back to the server, no other portlet on the portal page will mistakenly use our portlet's data.

All form elements should be encoded using the getNamespace() method of the response, and all fields being read in a portlet should assume the field has been namespace encoded.

Note: For simplicity, this xxxbook will use examples that exclude the namespace call. This is fine for learning, but is completely unacceptable in development or production. Uniquely identify all of your form data and JavaScripts code by using the getNamespace call to encode their names.

One caveat that you must be aware of is that if youencode a field in a JSP, make sure you use the same encoding scheme when retrieving that field on the server, or else the field you are looking for will come back as a null. The following example demonstrates how to encode a namespace in a JSP and pull out the encoded value in the portlet:

Encoding an Attribute in the Form: 

<INPUT name="<%=renderResponse.getNamespace()%>number"/>

Un-Encoding the Same Attribute in the Portlet:

String num  = request.getParameter(response.getNamespace() + "number");

Here is the landing page of the NumberGuesserPortlet updated with encoded form elements:

<%@taglib uri="http://java.sun.com/portlet_2_0"
prefix="portlet"%>
<portlet:defineObjects />
<FORM action="<%=renderResponse.createRenderURL()%>">
  I'm thinking of a number between 1 and 10.<BR>
  <I>What is it?</I>
  <INPUT name="<%=renderResponse.getNamespace()%>number" />
  <INPUT name="submit" type="submit" value="Guess!!" />
</FORM>

Here is the updated NumberGuesserPortlet updated to pull value associated with the encoded input field:

package com.mcnz.portlet;
import java.io.*;import javax.portlet.*;
public class NumberGuesserPortlet extends GenericPortlet {   protected void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {     String number=request.getParameter(response.getNamespace()+"number");     if (number == null) {       String url = "/numberguesser.jsp";      getPortletContext().getRequestDispatcher(url).include(request,response);     } else {       response.setContentType("text/html");       PrintWriter out = response.getWriter();       out.print("You guessed " + number);       out.print("<BR>The number was 5.<br/>");       out.print("<A href=\"");       out.print(response.createRenderURL());       out.print("\">Try Again</A>");     }   } }


Displaying Images in a Portlet

A similar problem to linking back to a portlet is figuring out how to display an image in a portlet. After all, if we have trouble creating a URL that points back to our original portlet, how do we code a JSP to link back to a resource such as a JPG or GIF file in the portlet's images subdirectory?

The solution is to use a special method in the renderRequest called getContextPath(). This returns a path to the root of the portlet application. From there, you can map to resources such as image files in subfolders. So, if you had an image named wiw.jpg in an images folder off the root of the war, the following code would pull the image out:

renderRequest.getContextPath() +  "/images/wiw.jpg";

To display the image in a portlet, you would combine this code with the standard html IMG tag:

<IMG src='<%=renderRequest.getContextPath()+"/images/wiw.jpg" %>'/>

Ultimately though, the resource should also be encoded, so the getContextPath() method is nested in a call to encode the URL:

<img src='<%= renderResponse.encodeURL(renderRequest.getContextPath() + "/images/wiw.jpg") %>'  />


A quick look at some portlet custom tags

Since creating render and action URLs, not to mention namespace encoding form variables, are such common tasks in our JSP files, the Portlet API provides a couple of handy-dandy custom tags that makes these tasks just a little bit easier. Comparatively speaking, it is much slicker to use the <portlet:renderURL/> custom tag to spit out a link back to the current portal page,than it is to use the corresponding scriptlet.

With a JSP Expression:

<FORM action="<%=renderResponse.createRenderURL()%>">

With a Custom Tag:

<FORM action="<portlet:renderURL/>">

Similarly, using a custom tag to encode a variable name used in a form is much more readable and maintainable than using a JSP expression. Additionally, portlet parameters can be attached to a URL with the param tag:

<portlet:renderURL> 
 <portlet:param name="book" value="portal"/>
</portlet:renderURL>

Here is how the input field number was namespace encoded using an expression:

<INPUT name="<%=renderResponse.getNamespace()%>number"/>

And here is the exact same namespace encoding being performed using a custom tag:

<INPUT name="<portlet:namespace/>number"/>

Our input form with portlet custom tags

Here is the landing page of the NumberGuesserPortlet updated to use custom tags instead of scriptlets or expressions:

<%@taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<portlet:defineObjects />
<FORM action="<portlet:renderURL/>">
I'm thinking of a number between 1 and 10.<BR> <BR>
      <I>What is it?</I>
      <INPUT name="<portlet:namespace/>number" type="text"/>
      <INPUT name="submit" value="Guess!!" type="submit" />
</FORM>

Deployment descriptors

With the JSPs coded, and the NumberGuesserPortlet doing what it should, the last thing our portlet application needs before being zipped up, is a good portlet.xml file, and web.xml file.

<?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.mcnz.portlet.NumberGuesserPortlet.c821e08104" >
<portlet>
 <portlet-name>NumberGuesser</portlet-name>
 <portlet-class>com.mcnz.portlet.NumberGuesserPortlet</portlet-class>
 <expiration-cache>0</expiration-cache>
 <supports>
  <mime-type>text/html</mime-type>
  <portlet-mode>view</portlet-mode>
  </supports>
 <portlet-info>
  <title>NumberGuesser</title>
 </portlet-info>
</portlet>
<default-namespace>http://NumberGuesser/</default-namespace>
</portlet-app>

Once the manifest file has been created, which simply states Manifest-Version: 1.1, the NumberGuesserPortlet application can be zipped up as a WAR file and deployed to the portal server.

Summary

Sometimes portlet development makes difficult things easy, and other times seemingly simple concepts are made more difficult. Working with images, JavaScript and HTML forms is one example. But if developers are armed with the knowledge of the potential problems that might arise when using these components, along with a good knowledge of the API components and methods that are designed to deal with these very issues, the challenges can be dealt with easily and relatively effortlessly.

How are you using the Portlet 2.0 API to simplify application development and delivery? Let us know.

27 Jul 2013

Related Content

Related Resources