In recent years, many organizations have implemented an enterprise portal to host internal and external applications. There are numerous J2EE portal vendors offering products in this lucrative market. In the past, each of these portal offerings defined their own proprietary APIs for building portlets, application components that run inside portals. Unfortunately, coding to these various APIs translated into vendor lock-in for portlet developers. The Java Portlet Specification (JSR 168) changes this.
This specification, developed by a committee of J2EE portal vendors, aims to achieve interoperability between portals and portlets. Vendors prove compliancy by passing a series of tests defined in Sun Microsystems’ Technology Compatibility Kit, or TCK. This standardization will help to simplify portlet development and enable developers to create pluggable components that run on any compliant, J2EE portal server.
This article begins with high-level definitions of portals, portlets, and portlet containers. Following that, we will highlight the most important aspects of the Java Portlet Specification. Later this month, a follow-up article will demonstrate how to develop a portlet from scratch, reinforcing the concepts described below.
Portals, Portlets, and Portlet Containers
There are three logical components to consider when developing to the Java Portlet Specification.
A portal is an application which aggregates portlet applications together in a presentable format. Beyond merely being a presentation layer, a portal typically allows users to customize their presentation, including what portlet applications to display. A portal can also provide a convenient single sign-on mechanism for users.
A portlet is an individual web component that is made accessible to users via a portal interface. Typically, a single portlet generates only a fragment of the markup that a user sees from his or her browser. Users issue requests against portlets from the portal page. The portal in turn forwards those requests to a portlet container, which manages the lifecycle of a portlet.
A portlet container sits between a portal and its portlets. A portlet container provides the run-time environment to portlets, much in the same way a servlet container provides the environment for servlets. The portlet container manages portlets by invoking their lifecycle methods. The container forwards requests to the appropriate portlet. When a portlet generates a response, the portlet container sends it to the portal to be rendered to the user. The sequence of events that result in a user’s portal page is illustrated below. It should be noted that the distinction between a portal and portlet container is a logical one. These may be one physical component.
As we begin to dive into some of the concepts behind the Java Portlet Specification, you will see many similarities to J2EE servlets. This is understandable when you realize that portlet applications are essentially extended web applications, a layer on top of servlets if you will. As a result, portlet developers have access to not only portlet-specific objects, but also the underlying servlet constructs.
The Portlet Lifecycle
As stated earlier, it is the job of the portlet container to manage a portlet’s lifecycle. Each portlet exposes four lifecycle methods.
The init(PortletConfig config) is called once, immediately after a new portlet instance is created. It can be used to perform startup tasks and is akin to a servlets init method. PortletConfig represents read-only configuration data, specified in a portlet’s descriptor file, portlet.xml(more on this file later). For example, PortletConfig provides access to initialization parameters.
The processAction(ActionRequest request, ActionResponse response) method is called in response to a user action such as clicking a hyperlink or submitting a form. In this method, a portlet may invoke business logic components, such as JavaBeans, to accomplish its goal. The ActionRequest and ActionResponse Interfaces are subinterfaces of PortletRequest and PortalRequest. In processAction, a portlet may modify its own state as well as persistent information about a portlet.
The render(RenderRequest request, RenderResponse response) method follows processAction in the chain of lifecycle methods. Render generates the markup that will be made accessible to the portal user. RenderRequest and RenderResponse methods, also subinterfaces of PortletRequest and PortletResponse, are available during the rendering of a portlet. The way in which the render method generates output may depend on the portlet’s current state.
The destroy() method is the last lifecycle method, called just before a portlet is garbage collected and provides a last chance to free up portlet resources.
Portlet Mode and Window State
A portlet container manages a portlet’s lifecycle but it also controls two pieces of information that represent a portlet’s state, portlet mode and window state.
A portlets mode determines what actions should be performed on a portlet. View, Edit, and Help are the three standard modes. Optional modes can be specified too however.
The class GenericPortlet, found in the portlet.jar archive file, is a convenience class that implements the render method and defines three empty methods, doView, doEdit, and doHelp. Your subclass of GenericPortlet can implement any of these methods that you desire. When the container invokes the render method, render will call one of these methods, based upon portlet mode. For example, doEdit might prepare an HTML form to customize a portlet. doView will help generate display markup, and doHelp might build a portlet’s help screen.
Window State determines how much content should appear in a portlet. There are three standard window states defined in the specification: Normal, Minimized, and Maximized. Normal will display the portlet’s data in the amount of window space defined by the portal application, Maximized will present only that portlet in the user’s window, and Minimized may perhaps display a single line of text or nothing at all.
Window state and portlet mode are programmatically accessible throughout the life of a portlet application. They can be read from any portlet API method, such as render. A portlet’s processAction method has the ability to modify their values.
PortletPreferences and PortletSession
The specification defines a few different methods that involve storing user information, either permanently or for the length of a client’s session. The two most important are PortletPreferences and PortletSession.
PortletPreferences is an object that can be used to store persistent data for a portlet user. PortletPreferences stores pairs of names and values that are retrievable during the render phase through a getValue method. In processAction, values can be set and saved through the setValue and store methods, respectively. Optionally, you may include a PreferencesValidator object to check values prior to persisting preferences (via it’s validate method). Default preference values may be specified in a portlet’s descriptor file.
In servlet programming, HttpSession lets you to store session-specific data. Additionally, the Java Portlet Specification defines the PortletSession interface for storing information within a user’s session. PortletSession identifies two scopes, PORTLET_SCOPE and APPLICATION_SCOPE. In portlet session scope, you can store data specific to a single portlet instance, within a user’s session. The application session scope can store data across all of a user’s portlets within the same session.
Other Important Features
Below is a list of some of the additional features defined by the Java Portlet Specification.
- An include mechanism for incorporating servlets and JSP pages into your portlets. A PortletRequestDistpacher accomplishes this, much the same way a RequestDispatcher would in the servlet world. This allows your portlet methods to act as controllers, redirecting work to specified servlets and JSPs.
- A way to create non-standard portlet extensions, such as custom portlet modes. The PortalContext object can be used to query information about a portal vendors supported extensions. Then, portlet developers could decide if they would like to take advantage of any of those non-standard features.
- A taglib is provided for use in a portlet’s JSP pages. These tags provide a way to construct the URLs a portlet needs to refer back to itself. The taglib also provides a way to include all the necessary portlet-specific classes a JSP will need.
- The ability to manage portlet security, like designating a portlet to run only over HTTPS.
- A Method for accessing ResourceBundles for portlet localization.
- The option of declaratively specifying an expiration cache for a portlet
Also, when discussing the Java Portlet Specification it is relevant to mention its relationship to another standard, the Web Services for Remote Portlets, or WSRP. WSRP is a standard for accessing content generated by remote portlets, possibly portlets using a technology other than J2EE. Though separate specifications, the Java Portlet Specification and WSRP were each developed with the other’s standards in mind. As a result, the two specifications share many of the same concepts, like portlet modes and window states, allowing a portal to use both quite effectively.
Packaging a Java Portlet
The Java Portlet Specification allows a portlet or portlets to be packaged as a .war file for deployment to a J2EE application server. Just like a .war file used to deploy a typical J2EE web application, it contains a WEB-INF/web.xml file to configure the application context. However, with a portlet application, the WEB-INF folder must also contain a portlet.xml file. The portlet.xml file is a descriptor file, containing configuration details about all bundled portlets in the .war file.
The following listing shows a simple example of a portlet.xml file. Note how many of the previously-described constructs (portlet mode, preferences, etc.) are defined in this file.
A portlet.xml example
<portlet-app> <portlet> <portlet-name>MyPortlet</portlet-name> <portlet-class>com.abc.portlet.MyPortlet</portlet-class> <init-param> --Init param, available in portlet's PortletConfig instance.<name>view-to-present<value>/portlet/MyPortlet/startup_view.jsp</value> </init-param> <expiration-cache>300</expiration-cache> --Default expiration for portlet cache (5 minutes) <supports><mime-type>text/html</mime-type> --Portlet supports HTML markup <portlet-mode>VIEW</portlet-mode> --MyPortlet supports modes view and edit <portlet-mode>EDIT</portlet-mode> </supports> <resource-bundle>com.abc.portlet.MyResourceBundle</resource-bundle> <portlet-preferences> <preference> <name>Country1</name> --PortletPreferences name/value pairs. <value>USA</value> </preference> <preference> <name>Country2</name> <value>Japan</value> </preference> --A PreferencesValidator will check any preferences set. <preferences-validator>com.abc.portlet.validate.CountryValidator</preferences-validator> </portlet-preferences> </portlet></portlet-app>
The Java Portlet Specification has already been widely adopted by several commercial and open-source vendors. Going forward, portlet developers can take advantage of this standard, thereby insuring compatibility among many different portals. Updates made to this specification are sure to provide an even greater set of capabilities. For more information on the specification and its progress, visit its Java Community Process page.
My next Java article on the Java Portlet Specification will step through the coding and deployment of a working portlet application.
About the Author
Michael Klaene is a Senior Consultant with Sogeti LLC. He has spent over 7 years in IT, specializing in J2EE and Oracle analysis and development.