Understanding Portals and Portlets: Part One
Creating a customized portal
November 5, 2004

Related Links: Understanding Portals and Portlets: Part Two

It used to be difficult if you wanted to create a Web-based site that offered users the ability to access various systems from a single page. Systems were too severely disjointed and required a huge investment of time and work in order to bring them together in a single Web page.

Although there are many efforts taking place in the Java arena to provide systems integration, none have made the same impact as portals.

Understanding the JSR 168 Specification
The current breed of portals either already support the JSR 168 specification, or the developers are working quickly to try and bring them up to par with the specification. JSR 168 provides instructions to both portal software manufacturers and portlet developers.

For portal software manufacturers, this JSR provides the details on how a portal should be developed, what interfaces and objects need to exist, the communication process and sequence that should occur, security, and much more. For the portlet developer, it provides the interfaces that need to be implemented and used, the lifetime and scope of the portlets, and other related details.

There is yet a third perspective in this whole story, that of the end user. The end user views a portal as a collection of portlets presented on a single portal page, produced from requests made to a portal site (see Figure 1).

As an example, if you surf over to http://my.yahoo.com, you can register to have a personalized page that presents you with the content you sign up for, all from a single portal page. As shown in Figure 2, the page provided me with a Message Center Portlet, an RSS Headlines Portlet, a Scoreboard Portlet, and several other portlets that I had signed up for.

Before continuing, let's make sure you understand the concepts and terms.

* Portals: An HTTP-based site hosted with special portal software that allows the aggregation of several different back-end systems, processes, or sites brought together through a single portal page. Portals may provide additional services such as single sign-on security, customization, personalization, and back-end administrative/declarative application development.
* Content aggregation: The process of bringing together content from disjointed systems, via portlets, and controlled through the use of a portal.
* Portlet container: Controls the access, lifetime, and interaction of a single portlet. Provides the content returned from a portlet back to the portal for merging with the content of other portlets.
* Portlet: Provides content to its calling portal container for the purposes of being displayed on a portal page.
* Fragments: The content generated by a portlet is known as its fragment or fragment code. This is the HTML code generated from the portlet's rendering code.

Figure 3 depicts the relationship among the entities specified above.

Since a portlet provides the rendering code for its portlet window, it's responsible for providing the implementation. However, most portlets will dispatch and rely on a JSP to provide the actual rendering code. Figure 4 shows the sequence as it applies to a portal page that has just received an action in one portlet. That portlet, along with the other portlets on the page, must also render themselves.

Servlets and Portlets
Portlets share many similarities with servlets except for a few noted items. Portlets don't generate complete HTML documents; they're only interested in generating fragments that are included on the final portal page. They aren't allowed to generate HTML code that contains tags such as base, body, iframe, frame, frameset, head, HTML, or title. Imagine what would happen if all the portlets decided to provide a body tag. The portal wouldn't know whose body tag to use. The portal decides where these tags should go and provides additional tables, rows, and columns as needed for each of the portlets.

Portlets aren't directly tied to a particular URL. Instead, they use methods such as createActionURL() or createRenderURL() to construct a URL that is needed to allow a client to fire actions to retrieve renderings from the currently executing portlet. On the client side, clients aren't allowed to interact directly with a portlet. The requests or submissions are tunneled through the portal server. The URL has all the information that the portlet container needs to determine which portlet must be called and what type of functionality should be executed.

Two other very important differences are elaborately pronounced in the user interface. Anyone viewing a portal page for the first time will notice that they contain special adornments that can be utilized by users to minimize, normalize, or maximize the portlet window. Users also use the decorations to enter the Edit mode or View mode of the portlet (see Figure 5). Finally, portlets can exist on the same page multiple times. Most of the time, the user is given the ability to control which portlets show up on a particular portal page. This is known as personalization.

Although portlets can access both servlets or independent JSPs directly by including their output within the portlet's rendered output, the direct output of a servlet or an independent JSP should not be channeled back to a portal page unless the content is stripped of all of the offending HTML tags mentioned above. Dispatching is handled through a special object known as a PortletRequestDispatcher. Besides passing control directly to another portlet, servlet, or JSP, the portlet may choose to simply include the output from the entity, without losing the ability to provide further output appended to the end, essentially becoming an aggregator.

The Life of a Portlet
A portlet is initially called by the portlet container. In fact, its entire life is managed by the container (including requests and responses). The portlet inherits from the GenericPortlet class. The container loads the portlet and then calls its init() method. There are two versions of this method. The first version receives the PortletConfig object and stores it away for later use. This version then calls the parameterless version to perform any overridden code provided by the portlet author. Keep in mind that the portlet may be loaded and its init() method may have been called, but it might not be provided with a session until later. This is important to note, because if you need to store attributes within the init() method, you'll need to use the context object.

Within the deployment file that accompanies the portlet distribution file, the author can place initialization parameters, which can be pulled out by the portlet instances at runtime via the configuration object. This object can be pulled out by calling the GenericPortlet's getPortletConfig() method, which returns a PortletConfig object. Using this object, the author can access the initialization parameters by calling the object's getInitParameter() for each parameter that the portlet is interested in.

Portlets can also place titles and other pieces of information in accordance with the XML Schema into the deployment file. In addition, any displayable information can be kept in a resource bundle associated with the deployment descriptor file and be accessible at runtime. The values can be language-specific to assist in internationalizing the portlet.

Each time the client performs an action on a portlet, the portlet is invoked by the container via its processAction() method. When the portlet container finds it necessary to retrieve a viewing of the portlet, it calls the render() method. This method determines the type of view that should be rendered and calls one of three other methods: doHelp(), doView(), or doEdit(). These three methods should be overridden by the portlet author if the author expects to receive calls for any of these methods. The calling of these methods is controlled by the portlet author through the portlet deployment descriptors file (portlet.xml).

When the portlet container calls the action method of the portlet, there are two objects passed to it: first ActionRequest and, second, ActionResponse. Using the ActionRequest, the portlet can access the parameters of the request, the window state, the portlet mode, the portlet context, the session object, and the portlet preferences data.

The same two objects are sent to the render method of the portlet, except with slightly different names: RenderRequest and RenderResponse. Keep in mind that if you wish the parameters to become available in the render method or the resulting JSP, you'll need to move it there yourself using the ActionResponse.renderParameters() method, passing it the result of calling ActionRequest.getParameterMap(). You can later fetch the parameters from within the render method using RenderRequest.getParameter().

Remember the relationship between the URL used to invoke the portlet and the actual method that is called within the portlet. If you expect that an interaction from the user will result in a call to the portlet's processAction() method, you should call createActionURL() to have that type of URL created. For render requests, call createRenderURL().

When the portlet has completed its job, the container will call the portlet's destroy() method.

Portlet Preferences
Users expect that portlets can be modified to provide customized content. To provide customization, portlets support preferences, which are name/value pairs that can be assigned an initial value and later tailored to other values based on user preference.

Preferences can be modified during the processAction()method and inspected during any of the render methods. Preferences are altered or viewed through the PortletPreferences object. The interface provides methods to retrieve, change, or store preferences. Since preferences can be read-only, there is also a method to check if a preference can be modified.

Changes to preferences aren't committed until the store() method is called. It may only be called during the processAction() method.

Preferences are initially defined within the portlet's deployment file and given a default value. In addition, developers may assign a validator object, which implements the PreferencesValidator interface. This object's implementation can verify that values assigned to preferences are legitimate. Otherwise, the validator can throw a ValidatorException. Developers are encouraged to include information in the exception regarding the preferences that failed.

Portlet Modes and Window States
The portlet modes of a portlet are reflective of the kind of data the current portlet is displaying to the user. The standard modes are View, Edit, and Help. In the View mode, the portlet should display the normal content, based on the functionality offered by the portlet. For example, if the portlet is a stock portfolio portlet, it should display the symbols and current price/change for this mode.

In Edit mode, the portlet should present the user with the ability to customize whatever features are customizable for the portlet. For our stock portfolio portlet example, the portlet might present the ability to adjust the stocks in the portfolio, changing the colors to show up and/or down activity or changing the background color for the portlet.

The Help mode should display either a full description of how the portlet can be used (explaining both the View and Edit modes) or context-sensitive help explaining selected features of the portlet.

If the portlet wishes to determine which mode it's currently in when called, it can do so by calling the ActionRequest or RenderRequest objects' getPortletMode() method.

Portlets should specify their desire to handle any of the portlet modes by including the modes within the deployment descriptor's <supports> element.

The render() method will fall back to one of the three methods - doView(), doEdit(), and doHelp() - in order to have the portlet provide the implementation, depending on what portlet mode is currently in use. Most portal pages will provide the functionality that enables the users to choose which mode they wish to enter. This can be done by adornments placed on the title bar of the portlet.

The Window states allow the port-let to know the user's aspiration to have the portlet minimize its window, maximize its window, or normalize the window (bringing it from minimized or maximized mode). The portlet should always check what Window mode it's in before rendering data.

Portal Context and Session
The portlet can retrieve context information about the portal hosting it by accessing the PortalContext object. Utilizing this object, the portlet can call getPortalInfo() to retrieve vital information such as the portal vendor and portal version. It can also retrieve portal properties utilizing getProperty() and getPropertyNames(). The PortalContext object can be retrieved by calling the getPortalContext() method.

Portlets can store session data associated with the user's active session. There are several ways in which a server process can store data for later use within the session. These include:

* HTTP cookies
* SSL sessions
* URL rewriting

The portlet specification provides the developer with an interface named PortletSession that hides the implementation details, providing a simple interface for managing the various data pieces in a session utilizing the above-mentioned methods. The portlet session is guaranteed to be the same session across all portlets that result from requests made by the user.

Portals can provide portlets with a cache to store rendered output. The cache can be set to expire at a particular time, such as every 500 seconds. When required, each cache is created one to one with the user session and only for that particular portlet. The uniqueness of the cache is based on both the portlet and the user. The settings are placed in the portlet's deployment descriptor file distributed with the portlet. However, the portlet can alter the settings at runtime utilizing the RenderReponse object.

The portlet container can choose to use the requested portlet cache if resources permit; otherwise, it can shut down caching altogether. If the portlet container chooses to use caching, any request from the client to simply render content causes the portlet container to first check if the content has expired and, if it hasn't, returns the contents without calling any of the portlet's render methods. Otherwise, the methods are called once again, and the content is cached for later requests.

Putting the Pieces Together
The true advantage to producing portlets is realized when content providers are able to integrate existing portlets onto a single page, essentially providing users with portal pages that result in a portal site.

The actual semantics for achieving this will differ from one portal vendor to another. For example, some vendors will provide an administrative tool that can be accessed to build the portal site, bringing together the portlets by allowing administrators/developers to search for the type of portlets they wish to offer users, and then providing the plumbing to make this all happen.

The end result of all the administrative effort will be a portal page deployment file or perhaps some kind of registry (which can even be handled via an LDAP system) to produce the resulting site. The portal then utilizes the information stored in these data stores to produce the site at runtime. The data stores might have information such as:

* The name of the portal class and its logical name
* A description of the portal class
* Preferred real estate location and size
* Roles that may view the portlet

The portal may also maintain information about the individual pages, such as:

* Which portlets are included in what pages
* Initial portlet modes or Window states
* Flow of one portal page to another

These are just some of the pieces of information that a portal may potentially store as the site is administered.

Handle Your Threads
The portlet container handles multiple requests to a portlet by reusing the same instances of a portlet class, calling them on different threads through the same methods. This means that your code should be thread safe but yet avoid locking methods that can degrade performance or, worst yet, cause a deadlock. How can you provide a fast and efficient thread-safe method and yet still avoid locks? Make your portlets stateless. Sometimes object locks are unavoidable, but if they're necessary, try to do it with code that performs well and has the least chance of causing deadlocks.

What Does the Future Hold?
Although the portlet specification is in final release, this is simply version 1.0 of this specification. Future versions of this specification will outline the plans for:

* Filters: Similar to servlet filters - in fact, some vendors have already implemented this optional feature using the same type of method offered by servlets.
* Interportlet communication: This will allow one portlet to hook itself into another portlet, so that it can immediately be alerted to changes to the second portlet.
* Outer markup modification: Today portlets can only produce markup kept within their fragments. Future versions of the specification will allow portlets to influence the markup outside of their fragments (perhaps influencing the background colors of other portlets based on changes to the preferences of one portlet).

The information presented in this article was based solely on the portlet specification in its final release form. However, the only true way to learn any technology is to start using it. If you visit the Apache.org Web site (www.apache.org), you'll find the portals project. You should download and install the Pluto project and begin to generate some portlets. Pluto is the reference implementation for the portlets technologies and, as such, is completely compliant with the latest and greatest iteration of the portlet specification.

Next month, I'll be back to show you how to build an Image Viewer Portlet that will allow you to select images from the Web site you wish to view. In the process, you'll become acquainted with many of JSR 168's features, and also learn how to deploy portlets to Pluto.

Copyright 1994-2005 SYS-CON Publications, Inc.

Questions or problems regarding this web site should be directed to abeckman@outdoorssite.com.

Copyright 2008 Art Beckman. All rights reserved.

Last Modified: March 9, 2008