Skip to main content

WebSphere Portal programming: Portlet application programming, Part 2

Give and take -- portlet messaging techniques

David Lection, Senior Programmer, IBM 
David Lection
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.
Varad Ramamoorthy
Varadarajan Ramamoorthy is a contract programmer working on WebSphere Portal and related service offerings. You can contact Varad at varad@us.ibm.com.

Summary:  This is the second article in a series on developing portlets for WebSphere Portal. In this article, David and Varad introduce portlet-to-portlet collaboration using portlet messaging, then cover in depth some techniques for using messaging in your portlets. They also explain how WebSphere Portal supports and processes messages between portlets, and how to build the sample portlets that are included. You can use the sample portlets in this article as building blocks for highly functional messaging portlet applications.

Date:  01 Mar 2002
Level:  Introductory
Activity:  1105 views

The first article in this series provides an introduction to portlet structure and programming.

Introduction

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.

What's in a name?

Part 1 in this series of articles introduces portlet programming with WebSphere Portal Server Version 1.2. Part 2 introduces portlet messaging concepts with WebSphere Portal Version 2.1.

WebSphere Portal Server V1.2 is a standalone product, no longer orderable, but still supported by IBM. WebSphere Portal V2.1 includes the function of WebSphere Portal Server V1.2 and adds additional functions. The information in Part 1 is applicable to the new version.

See Resources for links to more information on these products.


Portlet messaging basics

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:

  1. 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.

  2. 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.

  3. 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.

  4. 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.


Sample portlets

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
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 message sending portlet

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 message receiving portlet

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.

Simplicity with one command

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.


Conclusion

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.



Download

NameSizeDownload method
sampleportlets HTTP

Information about download methods


Resources

About the authors

David Lection

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.

Varad Ramamoorthy

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)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Sample IT projects
ArticleID=86657
ArticleTitle=WebSphere Portal programming: Portlet application programming, Part 2
publish-date=03012002
author1-email=lection@us.ibm.com
author1-email-cc=
author2-email=varad@us.ibm.com
author2-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).