The first article in this series provides an introduction to portlet structure and programming.
Web site developers face an increasingly complex task of integrating all kinds of user-oriented content into a seamless, well-designed interface. Portal servers provide the framework for you to build a superior experience that provides users with compelling integrated content.
Portlets are the building blocks of a high quality portal. Dynamic and reactive portlets provide users with a fresh experience every time they view the portal page.
WebSphere Portal Version 2.1 is the latest release of IBM's prominent portal server software. WebSphere Portal empowers portlet programmers to provide compelling content for their users. With built-in support, WebSphere Portal allows portlets in a portlet application to communicate by sending messages to peer portlets in the application.
When portlets react and update to underlying messages, it gives the portal a more live and reactive feel. For example, users see the price of IBM stock going down (remember, this is only an example) in one portlet, while another portlet informs them "buy IBM now." Specifically, one portlet presents some data and the other portlet suggests an action to the user. Portlets operating in this fashion give users a more personal experience, and portlet messaging makes this possible.
Adding messaging to a set of cooperating portlets is a straightforward task. One portlet typically is the message sender, while another portlet is the message receiver. As the sender detects some condition it formats a message and sends it to the receiver. The receiver portlet then receives the message from a message event handler and processes the message. A single portlet can both send and receive messages.
There are some basic rules to know about portlet messaging. First, the portlets must belong to the same portlet application. A portlet application is a set of one or more portlets packaged together in the same portlet archive, or PAR file. The message object sent between the portlets is typically a custom, application-specific Java object. WebSphere Portal uses a unique class loader for each portlet application to provide protection and security between the applications. Because the messaging portlets need to share the Java message object they must be loaded by the same class loader, and therefore reside in the same portlet application.
The second rule is that the portlets must be displayed on the same portal page, primarily for performance reasons. Since only one portal page is visible at any moment, there is little need to send a message to a portlet that is not on the same page.
Portal event and messaging process
When a portlet submits an event to the portal server, the portal aggregations process begins. It is important to understand the underlying portal event and message process; it will let you implement portlets that send messages at the right time, so the receiver portlets receive their messages at the appropriate time.
The event handling and aggregation process has four steps:
- Process all action events
When the portal receives an event from a client, it decodes the action URI sent by the client and propagates an action event to the appropriate portlet. Typically this is a single event to a single portlet. When a portlet's action listener is called to process an action event, this is a good time to send a portlet message.
- Process all message events
Portlets can send multiple messages, so this process continues to loop until all message events have been processed. A portlet's message listener is called if a message is sent to the portlet. If a portlet sends a message as a result of receiving a message, the second message will also be sent to and processed by the second target portlet. This continues until there are no more pending message events.
- Process all window events
Portlets can be minimized, maximized, or restored to normal size by users. A portlet may also request a particular size. Sizing operations result in a potential series of window events sent to portlets whose sizes are changing. This process continues until all window events are processed.
- Portlet rendering process
Once all events have been processed in the above order, the portal aggregator begins calling each portlet on the display page to have it return the content contribution of the portlet to the page aggregation. When the aggregation process is complete, the finished page is returned to the browser.
Events are not processed in Step 4 of the event and aggregation process above. If a portlet sends a message during Step 4, from a view method in the portlet, the message will not be delivered or processed. So if a visible collaborative result is expected in the portal display, the portlet must send any messages during Steps 1 and 2 of the event and aggregation process.
The sample portlets MessageSender and MessageReceiver show how to implement messaging between portlets. Figure 1 below is a sample screen showing the portlets.
Figure 1. Messaging portlets
You begin by selecting a city from the map on the left. A pop-up menu prompts you to select the store location or the number of employees.
Once selected, a message is generated by the map (MessageSender) portlet and
sent to the target receiver (MessageReceiver) portlet instance. The receiving
portlet displays the data for the selected city.
The two portlets on the right in Figure 1 are instances of the same MessageReceiver portlet. The top instance shows the city's
store location and the bottom instance shows the number of employees at the selected store.
Next we'll discuss the sample portlets step by step.
The structure of our MessageSender portlet follows the standard model-view-controller (MVC) design pattern. JavaServer Pages (JSP) technology is used to display the content of the portlet.
MessageSenderPortlet sample code
public class MessageSenderPortlet extends AbstractPortlet
{
protected final static String viewJSP
= "/PORTLET-INF/MessageSender/html/MessageSenderView.jsp";
public final static String DEFAULT_ACTION = "SendMessage";
public final static String CITYNAME = "cityName";
public final static String MESSAGE_ID = "MessageSender";
public final static String PORTLETNAME = "portletname";
public void doView ( PortletRequest request, PortletResponse response )
throws PortletException, IOException
{
// Format the default action event URI
PortletURI baseURI = response.createReturnURI();
DefaultPortletAction
action = new DefaultPortletAction(DEFAULT_ACTION);
baseURI.addAction(action);
request.setAttribute("BaseURI", baseURI.toString());
// Call the JSP to display the portlet output
getPortletConfig().getContext().include(viewJSP, request, response);
}
}
|
The portlet is small and straightforward. A portlet URI is constructed. This URI defines the action event that propagates the submit action back to the portlet's action listener. Once the URI is constructed, the portlet's content is rendered by delegating the rendering to the MessageSenderView JSP page. This is accomplished in the call to the portlet context include method shown above. The portlet displays a map of the state of North Carolina and some descriptive help text to guide users with the map.
When users click on a city, a snippet of JavaScript in the MessageSenderView JSP page displays a popup context menu from which they select either the store location or number of employees. The JavaScript then saves both the city name and the data item requested, and submits them to the portal server as an action event.
The event is presented to the actionPeformed method of the action listener class; action listener is in
MessageSenderActionListener.java.
MessageSenderActionListener's actionPerformed Method
public void actionPerformed(ActionEvent event)
{
DefaultPortletAction action = (DefaultPortletAction)event.getAction();
if ( action != null )
{
AbstractPortlet portlet = (AbstractPortlet)event.getPortlet();
PortletRequest request = event.getRequest();
if(action.getName().equalsIgnoreCase
(MessageSenderPortlet.DEFAULT_ACTION))
{
String portletName
= (String) request.getParameter(MessageSenderPortlet.PORTLETNAME);
try
{
String cityName
= (String) request.getParameter(MessageSenderPortlet.CITYNAME);
// Create a portlet message and add message parameters.
DefaultPortletMessage dpm
= new DefaultPortletMessage(MessageSenderPortlet.MESSAGE_ID);
dpm.addParameter(MessageSenderPortlet.CITYNAME, cityName);
// Here you can specify the name of the portlet that you want to
// send the message to or you can specify "null", so
// that the message
// will be sent to all the portlets on that page.
portlet.getPortletConfig().getContext().send
(portletName, dpm, request);
}
catch( AccessDeniedException ade )
{
PortletLog pLog = portlet.getPortletLog();
pLog.error
( "MessageSenderActionListener: error sending message to: "
+ portletName );
}
}
}
}
|
Within the try block of code above, the portlet message is constructed as an
instance of the DefaultPortletMessage class and sent to the target portlet.
Both the target portlet name and the city name are extracted from attributes in the portlet request. The city name is added to the portlet message as a parameter using the addParameter method, and the portlet name is used in the send method to determine which portlet is the target for the message. If an error occurs during message creation or sending, the catch block is invoked and an error message is written to the portlet message log.
The structure of our MessageReceiver portlet also follows the MVC design pattern. Because the portlet can display either the store location or number of employees, the portlet must select a particular JSP page for the portlet display. To do this, you specify the JSP in a configuration parameter in the portlet.xml file. The following fragment of XML from the portlet.xml file shows the specification of the JSP page for the store location.
<config-param> <param-name>viewJSP</param-name> <param-value>/PORTLET-INF/MessageReceiver/html/AcmePartsLocationView.jsp </param-value> </config-param> |
The MessageReceiver portlet contains two methods:
- init method - determines the JSP to use for the portlet rendering.
- doView method - is responsible for rendering the portlet's content. The value of the selected city name is placed in the portlet request object for subsequent use by the JSP.
The portlet context include method is called to complete the portlet rendering process.
MessageReceiverPortlet sample code
public class MessageReceiverPortlet extends AbstractPortlet
{
protected String viewJSP = null;
public final static String VIEW_JSP_ATTRIBUTE = "viewJSP";
public void init(PortletConfig pConfig) throws UnavailableException
{
super.init( pConfig );
viewJSP = pConfig.getAttribute( VIEW_JSP_ATTRIBUTE );
if ( viewJSP == null || viewJSP.trim().equals("") )
{
throw new
UnavailableException("MessageReceiver: Parm viewJSP not defined");
}
}
public void doView( PortletRequest request, PortletResponse response )
throws PortletException, IOException
{
PortletData portletPersistence = request.getData();
String cityName = (String)
portletPersistence.getAttribute(MessageSenderPortlet.CITYNAME);
if ( cityName == null )
{
cityName = "";
}
// Store the fieldname value in the portlet request for the JSP
request.setAttribute(MessageSenderPortlet.CITYNAME, cityName);
// Call the JSP to display the portlet output
getPortletConfig().getContext().include( viewJSP, request, response );
}
}
|
The two portlets, the portlet application descriptor portlet.xml, and the associated JSP pages are packaged into a PAR file for installation on the portal server.
Building the portlet application
If you make modifications or enhancements to the portlets, you should recompile the classes and package the portlet application into a PAR file. The build process has been automated and the source archive contains command files for compiling each portlet separately. The following command file compiles all of the classes that comprise MessageSenderPortlet.
rem echo off cls set pardir=C:/WPS-Portlet-Messaging/Par set builddir=C:/WPS-Portlet-Messaging/MessageSender javac -classpath %pardir%/PORTLET-INF/classes;%CLASSPATH% -d %pardir%/PORTLET-INF/classes %builddir%/MessageSender*.java |
You'll need to modify the two set statements so they point to the paths where you've copied the portlet application source code. Before building the portlet ensure you have your Java class path set to include the required portal JAR files:
- allportlets.jar
- Jetspeed-portlets.jar
- framework.jar
- Jetspeed.jar
- turbine-2.0.jar
The MessageReceiver portlet also includes a similar command file for building the portlet. Once again, you need to modify the set statements in the command file prior to compiling the portlet.
In the root directory of the portlet source archive is the command file buildall.bat, which builds the entire portlet application and packages it into the portlet archive file MessagePortlets.par. It is advantageous to use this command because the command automatically builds both portlets, and it builds MessageSenderPortlet first. This is required because the MessageReceiver portlet uses Java constants defined in the MessageSender portlet class.
echo off cls cd MessageSender cmd /c build.bat cd .. cd MessageReceiver cmd /c build.bat cd .. cd Par jar cvf0 MessagePortlets.par images jar uvf0 MessagePortlets.par PORTLET-INF cd .. |
The buildall.bat command file calls the other build command files to build each portlet. The jar command is called to build the PAR file. A PAR file is a specialized JAR file that includes the portlet.xml application descriptor and all portlet-protected resources in the "PORTLET-INF" directory.
Once you have successfully built the portlet application, copy the PAR file to your portal server for installation.
Installing the messaging portlet application
To begin installing the messaging portlet application, proceed to your portal home page and log into the portal as an administrator. Click on the Administration tag to display the Portlet Administration page. You'll install the MessagePortlets.par file using the Portlet Application Administration portlet. Click Install and import the portlet application. You'll be presented with a series of screens and confirmations. Once the portlet application is installed, activate it using the administration portlet.
After you have installed and activated the portlet application, you'll need to add the individual portlets to a portal page using the portal page customizer. For the portlets to operate they must be installed on the same portal page.
To easily observe the interactions between the portlets, place the two receiver portlet instances to the immediate right or left of the map portlet instance on your portal page. When a receiver portlet instance changes based on city selection, the selected city is persisted by the portlet so it is selected the next time the portlet is viewed.
The example portlets in this article have been tested to work on Internet Explorer Versions 5.50 and 6.00, and Netscape Navigator Version 4.72. If you test the portlets on other HTML browsers and find an incompatability, please send us an e-mail explaining the symptoms of the error.
We've only skimmed the surface of what can be accomplished when portlets collaborate using messaging. The messaging concept is easy and straightforward, but portlets that communicate with messaging achieve powerful and compelling results. So let your imagination guide you, and your programming skills drive you!
Our next article will have a sneak peek of the next release of the WebSphere Portal, which runs on WebSphere Application Server Version 4 and features an updated and more powerful portlet programming API. We'll discuss the changes and enhancements in the portlet API, and give you several strategies and tips for migrating portlet applications to this exciting new release.
| Name | Size | Download method |
|---|---|---|
| sampleportlets | HTTP |
Information about download methods
- Participate in the discussion forum.
- Read the first article in this series, "Introduction to portlet structure and programming" (developerWorks, November 2001).
- Download a zipped file that contains the sample code for this article.
- Visit the WebSphere Portal product site, which includes the InfoCenter and information about WebSphere Portal Version 2.1.
- Download portlets from the Portlet marketplace.
- Learn how to make portal applications mobile at the pervasive computing portal site.
- Consider working with IBM to build your own custom portal Web site. Visit PartnerWorld for Developers IBM WebSphere Portal for information (including an extensive resource list of related technical articles).
- Take this tutorial on developing portlets for WebSphere Portal.
- Learn how to take advantage of single sign-on in WebSphere Portal in this article from WebSphere Developer Domain.
- Get in-depth information in the IBM Redbook, Access Integration Pattern using IBM WebSphere Portal.
- Enroll in the IBM course offering, Implementing WebSphere Portal.

David B. Lection is a Senior Programmer and chief tools architect for WebSphere Portal and related products. You can contact David at lection@us.ibm.com.

Varadarajan Ramamoorthy is a contract programmer working on WebSphere Portal and related service offerings. You can contact Varad at varad@us.ibm.com.
Comments (Undergoing maintenance)

