In the first part of this article series, "What's new in the Java Portlet Specification V2.0 (JSR 286)?," we looked at the new programming capabilities that come with the second version of the Java Portlet Specification, JSR 286. You have seen how these extensions allow portlet programmers to tackle new use cases, especially with regard to coordination between independently developed portlets and with improved support for popular AJAX technology.
In this second part of the series, we take you on a tour that shows how the new features are exposed in IBM WebSphere Portal V6.1.
The first JSR 286 feature that we consider is portlet events. As described in the first part of this article, portlet events represent a loosely coupled publish and subscribe communication model, in which a portlet sends out an event that is then relayed to other interested portlets by a broker component running inside the portal.
Interportlet communication has always been an important use case and, therefore, WebSphere Portal for several releases has provided a very similar communication mechanism for brokered information exchange between portlets: the WebSphere Portal cooperative portlets feature, also known as the property broker. With JSR 286 support for portlet events, the same publish and subscribe infrastructure has now been extended to support the new standardized application programming interfaces (APIs).
From an administrative perspective, there is no difference between connecting JSR 168-based cooperative portlets or JSR 286 portlets with event support: Both are done using a wiring-administration, where connections are defined from published information (a publishing event) of one portlet to processing logic (a processing) event in another portlet. Of course, the wiring tool needs to know about the event types that portlets can publish and receive. Therefore, you have to declare all events supported by a portlet in its portlet.xml deployment descriptor, as recommended by the Java Portlet Specification. Otherwise, you are not able to connect your portlets in WebSphere Portal V6.1, and the portlets cannot communicate.
You should provide user-readable display names for all declared events, so that the wiring tool can display the wire sources and targets in a user-friendly way: JSR 286 has added language-specific information that is shared between all portlets in a WAR file; therefore, the new standard defines an application resource bundle (in addition to JSR 168 portlet resource bundles) where translatable information such as these event display names is stored.
The sample portlets provided with this article demonstrate how you define events in the deployment descriptor and refer to them in code and resource bundles, to show you how the parts fit together correctly.
WebSphere Portal currently has no support for dynamic interconnection of portlets by simply placing them on the same page; events are exchanged only between portlets if a matching wire has been defined. Typically, pages are set up by administrators, including the wiring of portlets on the pages. Users with appropriate permissions, who can add portlets to a private view of a page, can also set up private wires that do not apply for others.
Figure 1 is a screen capture of the portlet wiring tool with the two sample portlets wired together.
Figure 1. The portlet wiring tool
The explicit wiring model allows administrators to fully control how portlets deployed in WebSphere Portal can communicate. In particular, this model allows you to define target events as global (visible across pages) and establish cross-page wires that coordinate portlets on different pages. An event from a portlet can be propagated across multiple on-page and cross-page wires. One of the cross-page wires can be additionally marked with a switch-page flag, so that, after event processing completes, the browser is redirected to the target page.
Wires are a part of the data model for pages, which implies that management functions and APIs on pages also include the contained wires: Configuration management tools such as XmlAccess or the new version 6.1 site management tool can export and import wires along with the pages. WebSphere Portal application templates, which allow you to create many instances of a given setup of portlets, pages, and business components, can set up wires as part of an application instance with communicating portlets. Finally, the public model system programming interface (SPI) for reading data model information and the public controller SPI, and the model Atom feed infrastructure (both new features of version 6.1) support reading and modifying the wiring structure of a page.
The JSR 286 specification permits portlets to send and receive complex Java objects as event payloads, as long as these payloads are Java and JAXB XML serializable. This permission allows the transfer of complex objects across class loaders and even servers, for example, when communicating with remote portlets that follow the Web Services for Remote Portlets (WSRP) 2.0 protocol. WebSphere Portal 6.1 supports WSRP 2.0 and allows full interoperability and event propagation between local and remote portlets.
The XML serialization mechanism (based on JAXB 2.0) is also used to convert complex objects between different class loaders. This serialization is commonly the case when custom payload types are packaged in the portlet WAR file because each Web module is deployed in its own class loader. XML serialization implies a performance overhead; therefore, WebSphere Portal attempts to pass direct object references when possible. You can take advantage of this feature by deploying your shared payload classes in a common class loader, for example, by using the WebSphere Application Server shared library concepts, so that serialization is not necessary and optimal performance can be obtained.
In general, you should use simple Java types (usually Strings) as event payloads because this approach maximizes the possibility of interconnecting portlets, even if they were not originally developed together. For portlets that were developed independently, complex event payload classes are rarely compatible.
You should improve the interoperability of your portlets by declaring compatible event names or aliases: Event names typically describe not only the data that is being exchanged, but also the activity that creates or requires the data. For example, a calendar portlet might react to a specific show_week_for_date processing event that takes a date as an input. To wire an input from another portlet to this activity, the other portlet would need to produce a show_week_for_date publishing event in the same portlet-specific namespace; an event name that probably does not make much sense in the context of, say, an order-processing portlet that is producing the date. For this purpose, JSR 286 supports alias names for events. For example, the order-processing portlet can declare an order_added_for_date publishing event with aliases show_week_for_date and show_month_for_date, so that users can wire the order selection event to different actions in the calendar.
Still, this approach implies a relatively tight coupling of both portlet designs. To maximize interoperability, you should declare an alias for each event that describes just the data type that it expects or produces; in other words, the minimum requirement for compatibility. For example, you can declare the calendar portlet processing event as shown in listing 1.
Listing 1. Calendar portlet processing event
<event-definition xmlns:cal=”http://www.acme.com/portlets/calendar” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”> <qname>cal:show_week_for_date</qname> <alias>xsd:date</alias> <value-type> java.util.Date</value-type> </event-definition>
Using the alias name, the show_week_for_date event can be triggered by any source that produces a date, even if both connected portlets have been developed completely independently.
The new order has been added, and the date was sent to the calendar. See figure 2.
Figure 2. The event sample
The JSR 286 event propagation mechanism describes an automated interaction of portlets that takes place whenever a portlet publishes an event. The event phase of the portlet life cycle does not allow any sort of user interaction. WebSphere Portal extends this model with an interportlet communication mechanism in which propagation of information is explicitly controlled by the user: We call this mechanism the click-to-action model.
The idea is that instead of publishing an event during the action phase, a portlet can embed event information into its markup using special HTML constructs for enabling an event source as live text. This event source then becomes an active hotspot in the browser: When clicked, the event source dynamically collects all matching processing targets on the page into a menu that is displayed to the user. The user can then select a processing action for the information that is executed. See figure 3.
Figure 3. Context menu for the shipping date live text in the order portlet
The mechanism for providing an event source is different from JSR 286 in this model (semantic HTML markup instead of a Java call), but JSR 286 event processing fits well into this model as a processing target. Therefore, JSR 286 portlets that define processing events are automatically made available as click-to-action targets in WebSphere Portal V6.1. You can easily combine both programming models by providing JSR 286 source events and live text markup in your portlet. Note that click-to-action, because it is based on HTML markup only, can be used to communicate between all sorts of components that are represented as markup on a portal page. For example, you can add tagging for event sources in content management information that is displayed on a page and then send the information on a JSR 286 portlet on the same page. For more details on click-to-action support see the WebSphere Portal V6.1 Information Center.
Finally, we want to point out that the JSR 286 event support in WebSphere Portal is fully interoperable with the cooperative portlet feature supported in previous releases that we have mentioned earlier: Cooperative JSR 168 portlets can send information that is received as processing events by JSR 286 portlets, and JSR 286 portlets can publish events that are propagated to portlets using the cooperative portlet model. This interoperability allows a smooth migration or extension of existing systems with coordinated portlets onto the new portlet standard, thus protecting customer investments.
Besides portlet events, public render parameters represent an alternative way for coordination between portlets. Although both mechanisms allow exchanging information between portlets, they differ in several aspects. We first take a look at the technical details of public render parameters and their implementation in WebSphere Portal, and then we provide some guidelines to aid you in choosing the most appropriate technology for portlet communication.
As noted in the first part of this article, from a programming perspective, a public render parameter is handled almost identically to an ordinary (private) render parameter: The portlet can set and read this parameter using the same API methods that JSR 168 introduced for private render parameters. From a programmer's point of view, the important difference is that a public render parameter is declared in the portlet.xml deployment descriptor and therefore becomes an external interface of the portlet. See listing 2.
Listing 2. Public render parameter
<public-render-parameter xmlns:dm=”http://www.acme.com/portlets/doc-mgmt”> <identifier>selected-doc</identifier> <qname>dm:doc</qname> </public-render-parameter>
This portlet.xml fragment declares that the portlet code uses a render parameter with the portlet-specific identifier selected-doc and that this render parameter can be shared externally under the global (and, we hope, unique) name http://www.acme.com/portlets/doc-mgmt:doc. If a second portlet also declares a public render parameter with a global name http://www.acme.com/portlets/doc-mgmt:doc (regardless of the portlet-specific identifier that it uses) it can now share the values of this render parameter. Note that WebSphere Portal V6.1 stores the namespace and QName that you’ve declared in the portlet.xml in the URL, and thus you should make these as short as possible.
WebSphere Portal V6.1 does not require any administrative tasks to set up two portlets for sharing public parameters. The simple fact that they both use the same global name is enough; just place the two portlets on a page, and they will start interacting.
Actually, the collaboration works even across pages. By default, all public render parameters set by portlets are placed in the global scope. That fact means that you can interact with one portlet that uses a public parameter, then switch to another portlet on a different page that is using the same public parameter. When you view the second portlet for the first time, it is immediately set up with the information that was provided by the first portlet. This approach makes public render parameters a great tool for scenarios in which you have several portlets, even on different pages, that can all display information related to some global key such as a customer ID. By treating this global key as a public render parameter in all portlets, they will coordinate automatically.
Obviously, there are cases in which this sort of global information sharing is not desired. A common example is the case where you have two pairs of collaborating portlets such as a navigator and a viewer on separate pages. You want the navigator on page 1 to control the viewer on the same page but without affecting the viewer on the other page. In WebSphere Portal V6.1, you can control this behavior by limiting the sharing scope for public parameters to a page. To do so, go to Edit page settings for that page and set param.sharing.scope (under Advanced options - I want to set parameters) to a non-empty value such as scope1. All portlets that are placed on that page now use their own shared values for their declared render parameters, so they can still share information, but they cannot affect portlets on other pages. See figure 4.
Figure 4. The public.param.scope page setting
When you set the page setting to the same value scope1 for another page, that page also becomes part of the same sharing scope. Generally, two portlets share the value for a public render parameter if and only if the following conditions are met:
- They declare the parameter with the same global name in their portlet.xml deployment descriptor.
- They are placed on the same page or on pages that have the same value for the param.sharing.scope setting.
The global sharing scope that we have seen in the beginning is a special case where the page setting is empty.
The idea of render parameters in the Java Portlet Specification 1.0 was to give portlets an API in which they can store information about their internal navigational state and to allow portals to place this information in the URL. This concept means that render parameters can provide the expected user behavior inside portlets for browser operations such as bookmarking and back-button. Each URL for a portal page correctly restores portlet internal navigational state such as user selection, if that state is represented as render parameters. Also, HTTP proxy caches can correctly cache different states of the same portal page depending on the URL.
WebSphere Portal has supported such rich bookmarkable URLs since version 5.1, and consequently public render parameters are also part of this URL information in version 6.1. They are, for example, stored as part of portal bookmarks. In fact, any URL in WebSphere Portal can contain public render parameters, and you can use product-specific URL generation functions, such as the UrlGeneration JSP tag, to set public render parameters for portlets.
As we have seen from the preceding discussion, public render parameters can be regarded as a more lightweight communication alternative compared to portlet events. The following lists contrast some of their respective features to help you decide which mechanism is more appropriate for your use case.
Public render parameters have the following features:
- They do not usually require explicit coding but only a declaration in the portlet.xml deployment descriptor.
- They are limited to simple string values.
- They do not require explicit administration to set up coordination.
- They cause no performance overhead as the number of portlets sharing information grows.
- They are updated by URL changes such as jumping to a bookmark.
- They can be set from links encoded in portal themes and skins.
- They can be set on a link, created with product specific APIs, that leads from one portlet to another portlet on a different page.
Portlet events have the following features:
- They require explicit portlet code to send and receive.
- They can contain complex information.
- They allow fine-grained control by setting up different sorts of wires between portlets (on-page or cross-page, public or private).
- They can trigger cascaded updates with different information. For example, portlet A can send event X to portlet B, which in turn sends a different event Y to portlet C.
- They cause increasing processing overhead as the number of communication links grows.
- They must be initiated by some explicit user interaction (normally, by clicking an action link in a portlet), and they cannot be used to set up a coordinated view when first jumping to a page.
- They can interoperate with the cooperative portlet communication features provided by previous versions of WebSphere Portal.
Both mechanisms allow you to couple data exchange with a page switch. For events, you can define page-switching cross-page wires, as explained above. For public render parameters, you can use product-specific APIs in one portlet to generate a link to another portlet on a different page and set a public render parameter for the target.
Of course, you can even combine both techniques; for example, you can declare a processing event in your portlet that sets a render parameter and at the same time declares this parameter as public, so that information can be received both ways.
This discussion should help you determine which feature is more appropriate for a given use case. As a general rule, use public render parameters where you can, and use portlet events for more complex cases for which render parameters are not sufficient.
We have now covered the portlet coordination features introduced by JSR 286. They are the most important novelties in the specification; also these are features that depend significantly on the portal implementation, which is responsible for brokering the information between portlets.
Most of the other new programming features in JSR 286, such as portlet filters, are defined by the specification in detail and have no dependencies on a particular portal implementation, so there is no need to discuss WebSphere Portal specific topics.
In the following sections, we cover a few specific details about various new JSR 286 features that can be helpful to know when you are programming JSR 286 portlets on WebSphere Portal V6.1.
Resource serving gives you full control over all aspects of the HTTP protocol. WebSphere Portal writes out all response properties that you specify on a resource response as HTTP headers, so you can control language, content type, and other information for the provided content. The flip side is that, in contrast to normal page requests, the portal does not provide any default header information for the response; all information must be explicitly set during resource serving.
WebSphere Portal implements the different cache levels PAGE, PORTLET, and FULL that are defined by the specification. As noted before, WebSphere Portal uses rich URLs that encode the full navigational state of the page. Resource URLs with the default PAGE cacheability contain a lot of specific information about other components in the portal, which in many cases is not needed within the resource request.
If you want to take advantage of HTTP caching for resource requests, be sure to set resource URL cacheability to the highest level (the least information) that is actually required to process the resource request, to generate consistent URLs and improve HTTP cacheability. Also, to make a resource request cacheable, you need to explicitly set the cache control information on the response so that the portal can generate caching headers. Unlike normal render requests, the default caching definitions in portlet.xml deployment descriptor do not apply to resource requests.
JSR 286 adds API methods for reading and writing cookie properties to portlet request and response, but leaves it open to portal implementations about how these cookies are stored and handled. WebSphere Portal directly translates cookie properties into actual HTTP cookies. If you do not explicitly specify a cookie path, the default is set to the URL context of the portal, so the cookie can be correctly received back by future portal requests but not by other Web applications on the same server.
Cookies are not within a namespace, so they can be shared between portlets and, if required, also shared with other Web applications. Cookies therefore provide an alternative mechanism for coordination between portlets that can be useful in some circumstances. New cookies that have been set by a portlet are visible to all portlets in subsequent life-cycle phases of the same client request, and also in later requests unless the client decides to discard them.
Setting cookies in the render phase is currently not supported by WebSphere Portal V6.1. As the client response is already committed during the render phase, these cookies are not transmitted to the client and thus are lost on subsequent requests.
Container runtime options allow the portlet to request a specific runtime behavior from the portal and portlet container. WebSphere Portal V6.1 supports the following container runtime options:
- javax.portlet.escapeXml (defined by JSR 286) to avoid the default XML escaping of URLs generated by JSP tags.
- javax.portlet.actionScopedRequestAttributes (defined by JSR 286) to retain portlet request attributes across request boundaries.
- com.ibm.portal.public.session (product specific) to indicate that a portlet needs a session to operate correctly. It requests that the portal creates a session cookie whenever a page containing the portlet is accessed, even if no user login exists.
All of these runtime options represent workarounds for code that does not play well with the concepts of the portlet specification, but should nevertheless be supported in WebSphere Portal. Using the latter two runtime options can also cause performance degradation on heavily used portals. Therefore, try to avoid use of these runtime options and preferrably write your code in a way that makes them unnecessary.
With the JSR 168 API for URL generation, portlets always had to convert URL objects to a string using the PortletURL.toString() method before writing them out into markup. Because of the rich nature and considerable size of URLs in WebSphere Portal, this string conversion can negatively affect performance for portlets that create large numbers of URLs.
JSR 286 adds a write() method that allows you to stream URL objects directly to the response writer instead, avoiding the creation of temporary string objects. Use this method for writing out URLs. Unlike the toString() method, it also automatically provides the correct XML-escaping of URLs that is required by the XML and HTML specifications. Similar considerations apply to portlet URL tags in JavaServer™ Pages: The tag syntax that directly writes out the URL is preferred over the tag syntax that stores the generated URL in a temporary string variable.
Although WebSphere Portal V6.1 provides a fully compliant implementation of JSR 286 and supports all major features, a few optional aspects of the standard are not supported. For details, refer to the WebSphere Portal Information Center.
Like the first version of the Java Portlet API, the JSR 286 specification was developed in close cooperation with the OASIS committee that defined the Web Services for Remote Portlets (WSRP) standard. As a result, both specifications are closely aligned and represent the same programming model, only for different protocols. JSR 286 defined how local portlets interact with a Java-based portal; WSRP 2.0 defines how remote portlets interact with a portal that supports SOAP-based Web services.
WebSphere Portal V6.1 combines support for both specifications. As a result, the major programming features of JSR 286 – especially portlet coordination and resource serving – work also for remote portlets. That means that you can, for example, deploy a JSR 286 portlet on one portal installation and then consume it remotely from a different portal installation, and it continues to work as if it were installed locally.
With its support for JSR 286, the new WebSphere Portal release provides a range of new features that make portlet programming more powerful, most importantly by supporting versatile, standardized mechanisms for interportlet communication. The specification has intentionally left some aspects of these new functions open for product-specific implementations. This allowance applies particularly to interportlet communication. The specification clearly defines how portlets are programmed to exchange information, but it does not define when this information exchange actually takes place in a portal environment, or by which means portlets must be connected to control the information exchange.
In the second part of this article, we looked at how these product-specific aspects of the new standard are handled in WebSphere Portal V6.1 and how the new features integrate with product capabilities that go beyond the standard, such as click-to-action or advanced URL generation. Together with the first part, this article gives you all the information you need to leverage the new portlet programming features in your new portal projects.
- Participate in the discussion forum.
Refer to the JSR 168 specification.
Refer to the JSR 286 specification.
Consult the reference information for Implementation Pluto.
Learn more about IBM WebSphere Portal.
Stefan Hepper is the responsible architect for the WebSphere Portal and Workplace programming model and public APIs. He co-led the Java Portlet Specification V1.0 (JSR 168) and is now leading the V2.0 (JSR 286) effort. Stefan received a Diploma of Computer Science from the University of Karlsruhe, Germany, and in 1998 he joined the IBM Böblingen Development Laboratory.
Oliver Köth is the lead developer for the portlet container in WebSphere Portal and is responsible for the implementation of the Java Portlet Specification 2.0 in the product. He holds a Diplome of Computer Science from the University of Erlangen, Germany and has been working on IBM’s portal mission since 2001 in the IBM Böblingen Development Laboratory.