Converting the WorldClock portlet from the IBM Portlet API to the JSR 168 portlet API

This article shows how to convert a portlet that was originally developed for the IBM® WebSphere® Portal proprietary Portlet API to one using the JSR 168 standard portlet API. It describes the main issues in performing such a portlet conversion. If you need to convert a portlet from the IBM Portlet API to the JSR 168 API, this article serves as a good model for your doing so.

Franziska Paeffgen (fpaeffgen@de.ibm.com), Software Development for WebSphere Portal, IBM

Franziska PaeffgenFranziska Paeffgen is software developer within the portlet container development team, that is responsible for providing a portlet runtime environment. Her work responsibilities are the communication between WebSphere Portal and Application Server and the portlet and portlet application deployment.



Birga Rick (brick@de.ibm.com), Portlet Runtime Technical Lead, IBM

Author photoBirga Rick is software developer within WebSphere Portal development team at the IBM Boeblingen Lab in Germany. In 2003, she was part of the team implementing the reference implementation of the JSR 168 Portlet API, which is known as open source project Pluto today. Today she is jointly responsible for the portlet runtime environment of WebSphere Portal.



01 December 2004

Introduction

The Java™ Portlet Specification (JSR 168) defines how local portlets plug into portals. This standardized portlet API was needed since, over the last few years, different portal vendors had defined different APIs, none of them interoperable. The effort to create this standard was co-lead by IBM and Sun, within the Java Community Process. The specification enables interoperability between local portlets and portals, offers portlet developers a simple programming model, provides portability and interoperability with other Java technologies, and leverages and aligns the portlet API with J2EE technologies.

Before the creation of JSR 168, IBM had provided a proprietary API within WebSphere Portal. However, with the advent of JSR 168, it is recommended that portlet developers use the new standardized portlet API. The process of converting a portlet that uses the IBM Portlet API to one that uses the JSR 168 API needs to cover several aspects. There are significant differences within the portlet descriptors, the JSPs and their tags, and the main portlet methods. There are different method parameters and the flow of actions, and some functionality needs to be rewritten completely because there is no one-to-one match from one API to the other.

This article describes how to convert the WorldClock portlet, which was developed for IBM`s WebSphere Portal, from the IBM Portlet API to the JSR 168 API. This example covers the main issues to be addressed when when performing such a portlet conversion and applies to WebSphere Portal version 5 and above. Note that the code snippets shown here are not necessarily best practices; the goal in this conversion was simply to convert the portlet with minimal effort.

IBM WebSphere Portlet API compared to JSR 168 API

The IBM Portlet API and the JSR 168 API are similar in their major aspects. The IBM Portlet API is richer in functionality, since it was defined a few years ago and has been enhanced since then. This implies that there may be some difficulties when converting portlets using the IBM Portlet API to JSR API portlets, as the JSR 168 API might not provide all functionality required by the original portlet. More functionality is being added to the JSR 168 API so that, in time, there will be fewer and fewer difficulties. Nevertheless IBM provides extensions to the JSR 168 portlet API in order to provide at least the same functionality as the traditional IBM portlet API.

The main similarities and differences between the APIs are summarized below. For a more detailed description of the portlet API differences, see Comparing the JSR 168 Java Portlet Specification with the IBM Portlet API

Similar API concepts Different API concepts
  • Portlet Modes: View, Help, Edit, (Configure)
  • Window States: Normal, Minimized, Maximized
  • Portlet life cycle and request processing: Init, handle requests, destroy
  • URL encoding
  • Include Servlets/JSPs
  • Portlet application packaging
  • Expiration-based caching
  • Portlet Session
  • Request and response objects are the same for action and render phase with IBM`s portlet API, but different for JSR portlet API.
  • Portlets may store attributes in the action phase in the request and retrieve it in render. This is not possible with the JSR 168 Portlet API.
  • Portlet Application entities
  • Portlet Entities

The WorldClock portlet

The WorldClock portlet used as an example for the conversion is a simple portlet with basic portlet functionality and thus provides a good example of a conversion. This portlet allows users to set their local time zone and view the current time in that time zone. Users can view the current local time in several time zones around the world at the same time. Users can also quickly search for the current local time in an individual time zone. The portlet is dependent on the time provided by the server machine that is running WebSphere Portal to make its calculations.

Figure 1. Sample WorldClock Portlet
Sample WorldClock Portlet

How to convert the WorldClock Portlet

The next sections describe a step-by-step conversion of the WorldClock portlet from the IBM Portlet API to the JSR 168 API. For a better overview about the code differences that result from this conversion, we provide sample source code of both WorldClock portlets. The conversion steps are divided into the following sections:

Each section provides code comparisons between the original and converted portlets. Most of the examples are also linked to fuller examples of the code, allowing you to see the code in the context of the appropriate method within the portlet.

There are general steps that need to be performed when converting a portlet from the IBM Portlet API to the JSR 168 API. These steps include changes to the import statements and the renaming and restructuring of methods.

General portlet conversion issues
IBM Portlet API JSR 168 API
import org.apache.jetspeed.portlet.*;
import org.apache.jetspeed.portlet.event.*;
import org.apache.jetspeed.portlets.*;
import javax.portlet.*;

The imported packages of the IBM Portlet API contain all the required interfaces and implementations of classes a portlet needs to be fully functional. Within the package javax.portlet.*; of the JSR 168 API, these required interfaces and classes have been packaged together, containing, for example, the interfaces for the portlet's action request and response, render request and response, configuration, and so on. Refer to the Portlet API Javadoc for WebSphere Portal 5.0 and the JSR 168 Portlet Specification API for a complete listing of the package contents.

IBM Portlet API JSR 168 API
public class WorldClockController 
    extends PortletAdapter
    implements ActionListener
public class WorldClockController 
    extends GenericPortlet

With the IBM Portlet API the PortletAdapter provides a default implementation for the Portlet interface. The ActionListener interface is an addition to the Portlet interface. If an object wishes to receive action events in the portlet, this interface must be implemented in addition to the Portlet interface.

For JSR 168 portlets, the GenericPortlet class provides a default implementation for the Portlet interface. It provides an abstract class which must be subclassed to create portlets. The GenericPortlet class allows you to implement the processAction method, which handles action processing, provided within the ActionListener interface of the IBM portlet API.

This code is part of the constructor for the WorldClock portlet.

IBM Portlet API JSR 168 API
public void init(PortletConfig portletConfig) 
     throws UnavailableException
public void init(PortletConfig portletConfig) 
     throws PortletException, 
             UnavailableException

The init method can throw the UnavailableException under both the JSR 168 API and the IBM Portlet API specifications. However, under JSR 168, it can also throw the generic exception PortletException, when it is unable to perform its operation successfully.

IBM Portlet API JSR 168 API
public void doView (PortletRequest request, 
          PortletResponse response) 
          throws PortletException, IOException
public void doView (RenderRequest request,
          RenderResponse response)
          throws PortletException, IOException

Within the IBM Portlet API, there is no difference between a render request and response and an action request and response. The JSR 168 API, however, differentiates between whether the following action requires a re-rendering of the portlet's content or the processing of an action. Only the render request and response are passed as parameters within the doView method of JSR 168 API portlets.

The IBM proprietary portlet API does not conform to the Model-View-Controller (MVC) pattern. During the render phase of a portlet, its state can still be changed. This is not true for the JSR 168 portlet API, which does differentiate, by the two different requests (render and action), whether the portlet's state can be modified, or the portlet's content is just being displayed. The doView method of the JSR 168 specific portlet API represents the view component of the MVC pattern. The portlet content may provide links to an action URL that causes the actionPerformed method to be called. The portlet's state can only be changed within this method using the action request. This part represents the controller part of the MVC pattern.

This code is part of the doView method of the WorldClock portlet.

IBM Portlet API
public void actionPerformed(ActionEvent anEvent) 
    throws PortletException 
{
 DefaultPortletAction pAction = 
   (DefaultPortletAction)anEvent.getAction();
   String action = pAction.getName();
   PortletRequest request = anEvent.getRequest();
   }
JSR 168 API
public void processAction(ActionRequest request, 
      ActionResponse response)
      throws PortletException
{          
 String action = 
    request.getParameter(PARAMETER_NAME);
}

The IBM Portlet API defines action handling to be processed separately via ActionListener interface and its implementing classes. A standard implementation for action handling is already provided within the GenericPortlet class of the JSR 168. Since the JSR 168 API differentiates between an action request and response and a render request and response, the processAction method receives ActionRequest and ActionResponse objects as parameters.

This code is part of the actionPerformed method of the WorldClock portlet.

There are detailed steps that may be necessary when converting a portlet from the IBM Portlet API to the JSR 168 API. A deeper understanding of both APIs is required for these changes. Those detailed steps that were necessary to convert the WorldClock portlet are described in this section.

Detailed portlet conversion issues
IBM Portlet API JSR 168 API
import org.apache.jetspeed.portlet.PortletData;
 PortletData data = request.getData();
 data.setAttribute(name, value);
 data.getAttribute(name);
 data.removeAttribute(name);
import javax.portlet.PortletPreferences;
PortletPreferences data = 
    request.getPreferences();
data.setValue(name, value);
data.getValue(name, default_value);
data.reset(name);

The IBM Portlet API provides the basic configuration information about a portlet via a PortletSettings object, while the personalized information for each portlet instance is provided by aPortletData object. Within the JSR 168 API, this information is provided by only one object called PortletPreferences. There are two major differences that need to be taken into account when manipulating preference attributes instead of portlet settings or portlet data:

  • The preference attributes of PortletPreferences allows NULL values. Therefore the JSR 168 API differentiates whether a value is set or not by specifying a default value that is returned if no value is set.
  • The reset method of PortletPreferences removes or resets the preference value to a predefined default value, if available. The IBM Portlet API implements this functionality using the remove method of the PortletData object.

This code is part of the doView method of the WorldClock portlet.

IBM specific API JSR 168 API
getPortletConfig().getContext().include
   ("/WEB-INF/worldclock/WorldClockView.jsp", 
     request, response);
PortletRequestDispatcher dispatcher = 
    getPortletConfig().getPortletContext().
          getRequestDispatcher
      ("/worldclock/html/WorldClockView.jsp");
dispatcher.include(request, response);

Within the IBM Portlet API, an external resource is included in the PortletContext directly using the include method. Under the JSR 168 API, a PortletRequestDispatcher object is provided by PortletContext; the include method of this object is then used to include a resource.

Click here for a code example implemented by the WorldClock portlet.

IBM Portlet API JSR 168 API
org.apache.jetspeed.portlet.PortletURI
PortletURI quick_uri = response.createURI();
PortletAction quickAction = 
    new DefaultPortletAction(QUICK_LOOKUP);
quick_uri.addAction(quickAction);
javax.portlet.PortletURL
PortletURL quick_uri = 
     response.createActionURL();
quick_uri.setParameter(COMMAND, QUICK_LOOKUP);

The generation of a Unified Resource Locator (URL) is different between the two APIs. To create a URL that invokes an action event within the IBM Portlet API, a URI needs to be created and extended by a PortletAction that identifies the action to occur. Using the JSR 168 API, the method createActionURL directly returns a URL that invokes the action method to be called. To identify the action, a parameter can be set.

This code is part of the doEdit method of the WorldClock portlet.

IBM Portlet API JSR 168 API
request.setModeModifier(
     Portlet.ModeModifier.CURRENT);
response.setPortletMode(
     PortletMode.VIEW);

The IBM Portlet API allows the next portlet mode to be defined within event processing by specifying the ModeModifier of the portlet request. Using the JSR 168 API, the setPortletMode method of the action response is used to change to any arbitrary portlet mode. During conversion between the two portlet APIs, bear in mind that the createReturnURI method of the IBM Portlet API changes the portlet mode back to the mode that the portlet was in before the current one (typically changing it from EDIT mode to VIEW mode). To have the same behavior under JSR 168, the createReturnURI call needs to be replaced by RenderResponse.createActionURL. Within the method here called processAction, the portlet VIEW mode can be explicitly set at the action response.

IBM Portlet API JSR 168 API
portletConfig.getContext().getLog().
     debug("WorldClockController(init): 
                    entering init()...");
log("WorldClockController(init): 
     entering init()...");

Both, the IBM Portlet API and the JSR 168 API provide access to the logging facility via PortletContext. However, instead of using a PortletLog returned by the PortletContext.getLog method, the JSR 168 Portlet API provides a log method within the portlet context itself.

Deployment descriptor differences

A portlet deployment descriptor (portlet.xml) is used to describe the portlets packaged in a web archive; this deployment descriptor must be provided in addition to the web deployment descriptor (web.xml), which must be provided in order for the web archive to be valid. The JSR 168 Portlet API does not use the web.xml for portlet information. Therefore the web.xml file of a JSR 168 Portlet application may be empty.

There are detailed steps that must be performed when converting the portlet deployment descriptor from the IBM specific Portlet API to the JSR 168 API. A deeper understanding of both portlet descriptors is required for these changes. Because the portlet deployment descriptors provide the information about the portlet in a very different structure, only those differences that are present in the portlet.xml file of the WorldClock portlet are listed here.

IBM Portlet API
<portlet-app xmlns=
  "http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" 
version="v1.0" id="worldclock_app_id" 
xmlns:xsi=
    "http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation=
 "http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd ">
 </portlet-app>
JSR 168 API
<portlet-app xmlns=
  "http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" 
version="v1.0" id="worldclock_app_id" 
xmlns:xsi=
    "http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation=
 "http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd ">
</portlet-app>

The portlet.xml file describes a portlet application as defined within the IBM portlet Document Type Definition (DTD) or the JSR 168 portlet XML Schema Definition (XSD). While the IBM Portlet API divides a portlet application definition into a portlet-app and a concrete-portlet-app, the JSR 168 API defines only one portlet-app. Therefore the first step in converting portlet.xml is to change the portlet application tag, including the reference to the XML Schema definition of the portlet deployment descriptor.

Each portlet is defined by a <portlet> tag within the portlet application; this is common to both APIs.

IBM Portlet API JSR 168 API
<servlet-class> ... </servlet-class>
<portlet-class> ... </portlet-class>

In the IBM Portlet API, the fully-qualified class name of the portlet is specified within the web.xml file in the same way as it is done for servlets. Since the JSR 168 API portlets are components of their own and not specific servlets, the fully qualified class name of the portlet is defined by the <portlet-class> tag within portlet.xml.

IBM Portlet API JSR 168 API
<supports>
<markup name="html">
<view output="fragment"/>
<edit output="fragment"/>
<help output="fragment"/>
</markup>
</supports>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<portlet-mode>help</portlet-mode>   
</supports>

The portlet modes that are supported by the portlet are indicated within a <supports> block. the IBM Portlet API specifies the supported markup by a <markup> tag; the JSR 168 API uses the <mime-type> tag. The portlet modes that are defined by IBM's proprietary mode tags (for example, <view>, <edit>, <help>) need to be changed to the <portlet-mode> tag of the JSR 168 API. Since the configure mode is defined as optional within the JSR 168 API, this portlet mode must also be defined by a <portlet-mode> tag within a <custom-portlet-mode> tag.

IBM Portlet API JSR 168 API
<concrete-portlet> ... 
<title> ... </title>
<title-short> ... </title-short>
... </concrete-portlet>
<portlet-info>
<title> ... </title>
<short-title> ... </short-title>
</portlet-info>

For portlets using the IBM Portlet API, the title is defined for each concrete portlet. Since the JSR Portlet API does not use the same concept of a concrete portlet, the information is defined once per portlet by a <portlet-info> tag within the portlet definition. To support different settings depending on the locale, this information can be specified in a resource bundle instead, using the JSR 168 specific keys (for example, javax.portlet.title, javax.portlet.short-title, and javax.portlet.keywords). Then the resource bundle must be defined once per portlet by a <resource-bundle> tag within the portlet definition.

Both versions of the WorldClock portlet contain four JSPs, which are used to display its content.

JSP differences
BidiInclude.jsp The BidiInclude JSP is to make BIDI support a little easier. The variables defined within the JSP are meant to supplement the <bidi> tag.
WorldClockEdit.jspThe WorldClockEdit JSP is used to modify the WorldClock portlet and change its settings or preferences.
WorldClockHelp.jspThe WorldClockHelp JSP represents a JSP to display the help page of the WorldClock portlet.
WorldClockView.jspThe WorldClockView JSP is used to display the WorldClock portlet`s content.

There are some differences between the JSPs for the IBM and the standard WorldClock portlet. The JSPs used by the WorldClock portlet, BidiInclude.jsp, WorldClockEdit.jsp, and WorldClockView.jsp use the Portlet API specific JSP tags. The portlet tag library enables JSPs that are included from portlets to have direct access to portlet specific elements such as the portlet request and response. It also allows JSPs to access portlet functionality such as creation of portlet URLs. Within the JSPs, a tag element is always referenced by its defined prefix (for example, portletAPI).

The JSPs reference the IBM-specific portlet tags as follows:

<%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI" %>

.

The JSR JSPs reference the tag library like this:

<%@ taglib uri="http://java.sun.com/portlet" prefix="portletExt" %>

WebSphere Portal provides an additional tag for use in JSR 168 portlets. To make this tag available in a JSP, the following directive is required:

<%@ taglib uri="/WEB-INF/tld/ibm-portlet-ext.tld" prefix="portletExt"%>

The <portletExt/> is then used as follows.

<portletExt:bidi dir="rtl|ltr" locale="locale" />

dir: indicates the normal direction of text in the language.

  • For dir="rtl", the tag content is written only if the client's locale belongs to a bidirectional language. This is the default setting if dir is not specified.
  • For dir="ltr", the tag content is written only if the client's locale does not belong to a bidirectional language.

locale: the tag content is written only if the language belongs to the bidirectional languages defined in LocalizerService.properties.

The following tag elements are used within the already-mentioned JSPs of the IBM WorldClock portlet:

initThe class implementing the functionality represented by this tag creates the following variables to be used in the JSP:
  • portletRequest
  • portletResponse
  • portletConfig
The corresponding portlet tag specified by the JSR 168 API is the <defineObjects>
encodeNamespaceThe class implementing the functionality represented by this tag maps the given string value into this portlet's namespace. Tag parameter:
  • name (mandatory) - the value to be mapped into the portlet's namespace
A similar portlet tag specified by the JSR 168 API is the <namespace>
text (deprecated)The class implementing the functionality represented by this tag writes a localized string to the output stream. When no resource bundle can be found, the text between start and end tags is written to the output stream. The tag parameters are:
  • bundle (mandatory) - name of the resource bundle
  • key (mandatory) - key to be found in the resource bundle
There is currently no corresponding JSTL JSP tag available that reflects this functionality.
bidiThe class implementing the functionality represented by this tag supports text for bidirectional languages. Bidirectional languages are those which are typically read from right to left except when left-to-right text strings are displayed (for example, URLs, code samples, or directory and file names).
There is currently no corresponding JSTL JSP tag available that reflects this functionality, but an IBM extension, as explained above.
encodeURIThe class implementing the functionality represented by this tag creates the PortletResponse object and executes the encodeURI method.
The following portlet tags specified by the JSR 168 API provide equivalent behavior: <actionURL> and <renderURL>.

The following tag elements are used within the already mentioned JSPs of the JSR 168 WorldClock portlet:

defineObjectsThe defineObjects tag must define the following variables in the JSP page:
  • renderRequest
  • renderResponse
  • portletConfig

These variables must reference the same JSR 168 API objects stored in the request object of the JSP. A JSP using the defineObjects tag may use these variables from scriptlets throughout the page. An example of a JSP using the defineObjects tag is:

%<portlet:defineObjects/%>
%<%=renderResponse.setTitle("my portlet title")%%>

After using the defineObjects tag, the JSP invokes the setTitle method of the RenderResponse to set the title of the portlet.

actionURLThe portlet actionURL tag creates a URL that must point to the current portlet and must trigger an action request with the supplied parameters. Parameters may be added to the URL by including the param tag between the actionURLstart and end tags. The following non-required attributes are defined for this tag:
  • windowState (Type: String, non-required) -- indicates the window state that the portlet should have when this link is executed.
  • portletMode (Type: String, non-required) -- indicates the portlet mode that the portlet must have when this link is executed, if no error condition occurred.
  • var (Type: String, non-required) - name of the exported scoped variable for the action URL.
  • secure (Type: String, non-required) -- indicates if the resulting URL should be a secure connection (if the value is set to "true") or an insecure one (if the value is set to "false").
renderURLThe portlet renderURL tag creates a URL that must point to the current portlet and must trigger a render request with the supplied parameters. Parameters may be added by including the param tag between the renderURL start and end tags. The same non-required attributes as already listed for the actionURL tag are defined for this tag as well.
namespaceThis tag produces a unique value for the current portlet. This tag should be used for named elements in the portlet output (such as JavaScript functions and variables). The name spacing ensures that the given name is uniquely associated with this portlet and avoids name conflicts with other elements on the portal page or with other portlets on the page.
paramThis tag defines a parameter that may be added to a actionURL or renderURL.The param tag must not contain any body content. The following required attributes are defined for this tag:
  • name (Type: String, required) - the name of the parameter to add to the URL. If name is null or empty, no action is performed.
  • value (Type: String, required) - the value of the parameter to add to the URL. If value is null, it is processed as an empty value.

For further references to the standardized portlet tags please refer to the The JSR 168 Portlet Specification.

Sample Standard WorldClockEdit JSP code snippet

Click to see code listing

<%@ page session="false" buffer="none"%>
<%@ page import="java.util.*,javax.portlet.*,com.ibm.wps.portlets.worldclock.WorldClockController" %>

<%@ taglib uri="http://java.sun.com/portlet" prefix="portletAPI" %> 


<portletAPI:defineObjects/>

<portletAPI:actionURL var="saveURI">
   <portletAPI:param name="<%=WorldClockController.COMMAND%>" value="<%=WorldClockController.SAVE%>"/>
</portletAPI:actionURL>

......

<!-- build table for edit screen -->
<form name="WORLD_CLOCK_EDIT" action="<%=saveURI%>" method="POST">

   .....

   <table >
    <tr>
       <td>
          <label for="local_time_zone"><%= 
                 WorldClockController.getText ("text.local_time_zone", renderRequest.getLocale ()) %></label>
       </td>
    </tr>
    <tr>
       <td>
          <%--  on the next line width is for Netscape, style is for IE --%>
          <select id="local_time_zone" name="LocalTimeZone" size="1">
          <%
             int selPos = -1;
             String localTimezone = (String)renderRequest.getAttribute("localTimezone");
             if (localTimezone != null) {
               try {
                 selPos = Integer.parseInt(localTimezone);
               }
               catch (NumberFormatException ex) {
               }
             }
             Vector timezoneVector = (Vector)renderRequest.getAttribute("timezoneVector");
             for (int i=0; i < timezoneVector.size(); i++) {
                String id = (String)timezoneVector.elementAt(i);
                // exclude default selection
                if ( selPos != i ) {
           %>
                  <option value="<%= i%>"><%= id %></option>
           <%
                }
                else {
           %>
                  <option selected value="<%= i%><%= id %></option>
           <%
                }
             }
           %>
           </select>

       </td>
    </tr>
 </table>

   .....
 	
</form>

Source code for the WorldClock portlets

This section compares relevant parts of the source code of the WorldClock portlet written using the IBM Portlet API with the converted portlet that uses the JSR 168 Portlet API. The highlighted code indicates changes in the context of the conversion.

WorldClock portlet constructor using IBM Portlet API
// Java libraries
import java.util.*;
import java.io.*;
import java.text.*;

// Portlet API classes
import org.apache.jetspeed.portlet.*;
import org.apache.jetspeed.portlet.event.*;
import org.apache.jetspeed.portlets.*;
import com.ibm.wps.portlets.*;

/**
 * The WorldClockController class controls the 
 *  content display and portlet configuration
 *  behavior of the world timezone clock.
 */
public class WorldClockController 
	extends PortletAdapter 
		implements ActionListener
{
    .....
}
WorldClock portlet constructor using JSR 168 API
// Java libraries
import java.util.*;
import java.io.*;


// Portlet API classes
import javax.portlet.*;




/**
 * The WorldClockController class controls the 
 * content display and portlet configuration
 *  behavior of the world timezone clock.
 */
public class WorldClockController 
	extends GenericPortlet
		
{
    .....
}
WorldClock portlet doView method using IBM Portlet API
/**
* View functionality. Pass the format information 
*  to the JSP for display of local and
*  other time zone times.
*/
public void doView (PortletRequest request,
	PortletResponse response) 
	  throws PortletException, IOException
{
  PortletData data = request.getData();
  .....

  // include JSP for extended search
  getPortletConfig().getContext().
     include("/WEB-INF/worldclock/WorldClockView.jsp", 
         request, response);
    ....
}
WorldClock portlet doView method using JSR 168 API
/**
* View functionality. Pass the format information 
*  to the JSP for display of local and
*  other time zone times.
*/
public void doView (RenderRequest request,
	RenderResponse response) 
	   throws PortletException, IOException
{
  PortletPreferences data = request.getPreferences();	
  .....
			    
  // include JSP for extended search
  PortletRequestDispatcher dispatcher = getPortletConfig().
      getPortletContext().getRequestDispatcher
        ("/worldclock/html/WorldClockView.jsp");
  dispatcher.include(request, response);
  ....
}
WorldClock portlet doEdit method using IBM Portlet API
/**
* Edit functionality. 
* Allow the user to adjust the local time and 
* time zone. They can also pick the other time 
* zones in the world to display in view mode.
*/
public void doEdit (PortletRequest request,
	PortletResponse response) 
	   throws PortletException, IOException
{
  .....

  // include JSP for extended search
  getPortletConfig().getContext().include
      ("/WEB-INF/worldclock/WorldClockEdit.jsp",
       request, response);
  ....
}
WorldClock portlet doEdit method using JSR 168 API
/**
* Edit functionality. 
* Allow the user to adjust the local time and 
* time zone. They can also pick the other time 
* zones in the world to display in view mode.
*/
public void doEdit (RenderRequest request,
	RenderResponse response) 
	  throws PortletException, IOException
{
  .....

  // include JSP for extended search
  PortletRequestDispatcher dispatcher = 
      getPortletConfig().getPortletContext().
       getRequestDispatcher
         ("/worldclock/html/WorldClockEdit.jsp");
   dispatcher.include(request, response);
   ....
}
WorldClock portlet doHelp method using API Portlet API
/**
* Help functionality. 
* The help JSP of the portlet is displayed.
*/
public void doHelp ( PortletRequest request,
	PortletResponse response) 
       throws PortletException, IOException
{
    // include JSP for extended search
    getPortletConfig().getContext()include
        ("/WEB-INF/worldclock/WorldClockHelp.jsp",
         request, response);


}
WorldClock portlet doHelp method using JSR 168 API
/**
* Help functionality. 
* The help JSP of the portlet is displayed.
*/
public void doHelp (RenderRequest request,
	RenderResponse response) 
	   throws PortletException, IOException
{
    // include JSP for extended search
    PortletRequestDispatcher dispatcher = 
        getPortletConfig().getPortletContext().
         getRequestDispatcher
           ("/worldclock/html/WorldClockHelp.jsp");
    dispatcher.include(request, response);
}
WorldClock portlet actionPerformed using IBM Portlet API
/**
* Implements the save action for the portlet's 
* edit mode. The action is executed as part of 
* the submit URI before doView gets control. The
*  parameters that have been set by the user in the
*  edit form are retrieved from the request and 
* written to the portlet database through PortletData.
*/
public void actionPerformed(ActionEvent anEvent) 
	throws PortletException
{
  DefaultPortletAction pAction = 
      (DefaultPortletAction)anEvent.getAction();
  String action = pAction.getName();
  PortletRequest request = anEvent.getRequest();
  .....

  // save parameters to the user's config data
  PortletData data = request.getData();
  .....

  // go back to edit view
  request.setModeModifier(Portlet.ModeModifier.CURRENT);
  ....
}
WorldClock portlet actionPerformed method using JSR 168 API
/**
* Implements the save action for the portlet's 
* edit mode. The action is executed as part of 
* the submit URI before doView gets control. The
*  parameters that have been set by the user in the
*  edit form are retrieved from the request and 
* written to the portlet database through PortletData.
*/
public void processAction(ActionRequest request, 
	ActionResponse response) throws PortletException
{
  String action = request.getParameter(COMMAND);

  .....

  // save parameters to the user's config data
  PortletPreferences data = request.getPreferences();

  ....
   
}

Conclusion

This article demonstrated a simple way to convert a portlet originally developed with the IBM Portlet API into a portlet that conforms to JSR 168. Although not all differences between the APIs were covered, this conversion example addresses common issues of such a conversion,without covering best practices of a JSR 168 portlet programming model. This example gives developers a better understanding about the main differences between the APIs and the how to change functionality from a portlet that uses one API to the other.


Download

DescriptionNameSize
WAR file for the JSR 168 World Clock portletStdWorldClock.war  ( HTTP | FTP )210 KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=32180
ArticleTitle=Converting the WorldClock portlet from the IBM Portlet API to the JSR 168 portlet API
publish-date=12012004