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.