This brief report discusses inter-portlet use cases in the context of the SPP continuation project and outlines the inter-portlet communication capabilities of the new portlet standards JSR 286 and WSRP 2.0.
This work was carried out under the JISC SPP continuation project.
Jasper Tredgold. December 2007.
JSR 168 and WSRP 1.0 provide the current generation of portals and portlets with the standards required to ensure a level of interoperability. They allow portals to aggregate separate portlets, both local and remote, and present users with customisable and interactive displays of their content. One area that they do not cover though is that of inter-portlet communication. This refers to the ability of a portlet to communicate information to another displayed portlet, allowing user actions in one to produce effects in another. Some suggestions have been made as to how inter-portlet communication might be implemented within the current standards (see, for example, the Archaeology Data Service HEIRPORT portlet, described in this presentation), but the new portlet standards (the nearly finalised JSR 286 and WSRP 2.0) address the issue explicitly.
It is possible to envisage many use cases where the ability to communicate between co-located portlets would be an asset to the the user experience. With regard to the domain of this project's work, a couple of examples can be drawn from the functionality surrounding alerting and searching.
The current implementation of the Alerting Portlet user interface allows the user to navigate through a series of separate views in order to create or edit their subscriptions, the key ones being the list of the user's subscriptions, and the individual subscription editing view (shown here).
At present the user must navigate between these views. Inter-portlet communication introduces the option to divide functionality such as this into multiple, co-located portlets. So the selection of a subscription from the user's subscription list portlet would result in the display of the subscription details in a second, subscription editing portlet. This would allow the user to maintain an overview of their subscriptions while making changes to individual ones. A related use case would be the use of a co-located portlet to display further information about an option without taking the user out of the main flow of their task. In this context, an example would be the data sources, currently only displayed as titles in a list. A user selection of one could result in the display of further descriptive information about that data source in a neighbouring portlet, while maintaining the visual and navigational state of the editing portlet.
The current implementation of the Searching Portlet user interface has two main user results views, that of the list of records resulting from a successful search, and that of an individual selected record's details. This would be a clear point at which the use of two related and communicating portlets could bring benefits in application usability. One portlet would maintain the result set output, while the other would display the details of a particular record, selected by the user from the first. Extending this, the search history functionality might benefit from implementation as a separate portlet, as might any future saved records or saved searches functions. Being able to bookmark the state of multiple, co-located portlets also raises the possibility of bookmarking, and therefore making easily repeatable, keyword searches across groups of portlets, each targeted by the user at a different data source.
JSR 286 is the Java Portlet Specification 2.0 standard and, at the time of writing, has just been released as a proposed final draft. It is the successor to JSR 168, the 1.0 standard. It can be found from the JCP site: http://jcp.org/en/jsr/detail?id=286
It introduces some key new features to the portlet API, two of which, events and public render parameters, have a bearing on the topic of inter-portlet communication. These are the first two considered below.
Events enable portlets to communicate with each other. They allow portlets to react to occurrences that are not the direct result of a user interaction with that portlet. Events can be triggered by user interaction with other portlets or by the portal itself. A portlet can include the generation of an event as part of its handling of a received event.
The event model is a loosely-coupled one. Portlet events are wired together by the portal, or portlet container, and it brokers the event messaging. Events are defined at the portlet application level. Portlets then declare their wish to support a particular event within their portlet-level definitions, and whether their support is to publish the event or process it. Here's an example definition based on the specification:
<portlet-app ... > <event-definition> <qname xmlns:s="http://spp/events/">s:event1</qname> <value-type>java.lang.String</value-type> </event-definition> ... <portlet> ... <supported-processing-event xmlns:s="http://spp/events/"> s:event1 </supported-processing-event> ... </portlet> ... <portlet> ... <supported-publishing-event xmlns:s="http://spp/events/"> s:event1 </supported-publishing-event> ... </portlet> </portlet-app>Portlet code then must of course handle their declared support by implementing the relevant interfaces. Events are supported by a new method in the portlet lifecycle,
processEvent, which occurs after any user-initiated actions are handled, but before the render stage.
Examples, first of publishing an event, then of processing one, following on from the definition example above:
void processEvent(EventRequest req, EventResponse resp)
{
String sample = "sampleEvent";
QName name = new QName ("http://spp/events/", "event1");
resp.setEvent(name, sample);
}
void processEvent(EventRequest req, EventResponse resp)
{
Event event = req.getEvent();
if ( event.getName().equals("event1") )
{
String payload = (String) event.getValue();
...
}
}
An example of the use of such events would be the implementation of the use case described above. A user selecting a to view a record displayed in a list of search results would initiate a user action in the search portlet. Part of this action would be to trigger an event, containing the parameters required to identify the record selected. This event would be handled by the record display portlet, which would update its state to record the identity of the record selected. Upon the execution of that portlet's render lifecycle method, the new state would result in the display of the record selected by the user in the search portlet.
Public render parameters are included to enable view state to be shared across portlets. Assuming the portal implementation stores these render parameters in the URL, this would also allow the view state of the displayed portlets to be recalled by user use of browser navigation history or by bookmarking.
Public render parameters are declared across portlet applications, and portlets then declare their support for particular public render parameters. Here's an example:
<portlet-app ...> <public-render-parameter> <identifier>render1</identifier> <qname xmlns:s="http://spp/params/">s:render1</qname> </public-render-parameter> ... <portlet> <portlet-name>portlet1</portlet-name> ... <supported-public-render-parameter>render1</supported-public-render-parameter> </portlet> ... </portlet-app>The parameters are then available to the portlet in all the lifecycle methods of the portlet,
processAction, processEvent,
render and serveResource.
These public render parameters can also be viewed
and altered by other portlets. Note that the portlets sharing the same render parameters do not have
to be in the same portlet application.
An example of code that sets the parameter:
public void processAction(ActionRequest req, ActionResponse res) ...
{
res.setRenderParameter("render1","sample");
...
}
An example of the use of public render parameters would be to encode a search query as a parameter in a portal URL, thus sharing the search terms across multiple search portlets and providing a link that can be bookmarked. This use case is described above.
Resource serving allows portlets to create links in order to serve resources from within its portlet
web application. They can do this is two ways. Firstly by creating direct links to the resource. This
type of link will not give the resource access to the portlet context, nor link through the portal server.
When these are not needed, this technique can provide more efficiencies in serving resources directly.
The second method creates resource links that point to the portlet. These links allow the portlet to
serve the resource, via its serveResource method. This technique makes the portlet context
available to the resource and serves it via the portal, allowing the use of portal services, for
instance its security. One example use of this feature is to introduce Ajax-style interactions into
portlet user interfaces by introducing javascript functions that can call the portlet's dynamically
provided resource serving URL.
The resource serving feature introduces a new method into the portlet lifecycle, serveResource.
Portlet filters are modelled on Java Servlet filters and allow developers to modify portlet requests and responses. They allow for the altering of the content being passed before or after any of the four lifecycle methods of the portlet. The standard defines interfaces that filter classes must implement, and the filters are then declared and configured in the portlet application definition file. Filters can also be chained together. Filtering provides a powerful tool for the introduction of cross-cutting concerns like, for example, logging.
The Web Service for Remote Portlets Specification 2.0 was nearing its final version at the time of writing. It is the successor to WSRP 1.0, and can be found on the OASIS site: http://docs.oasis-open.org/wsrp/v2/wsrp-2.0-spec.html.
Its development has been done in coordination with that of JSR 286, and as such some of its new features support the inter-portlet communication model described in that specification. These are the features considered here.
As with JSR 286's public render parameters, WSRP 2.0 provides a mechanism to allow a remote portlet to expose its navigational state to the portlet's consumer. This is via the NavigationalContext data type. It allows the consumer (for instance a portal) to provide bookmarkable links to a remote portlet's state by encoding the navigational parameters into a URL, and allows for portlet co-ordination (inter-portlet communication) via the passing of shared parameters. The remote portlet consumer thus becomes the broker for this method of inter-portlet communication.
The new specification also supports portlet co-ordination via an eventing model. The consumer can co-ordinate events across its portlets by distributing events either set by the consumer itself or set by portlets in their action lifecycle stage (processAction (JSR) or performBlockingInteraction (WSRP)). Similarly to JSR 286, this distribution involves an additional step in the protocol. WSRP 2.0 defines handleEvents, making the 1.0 two-step protocol into the new performBlockingInteraction, handleEvents, getMarkup three-step sequence. This allows the consumer to broker the events across both its remote portlets and portlets local to it.
The co-ordinated development of the JSR 286 and WSRP 2.0 standards has provided a mature and scalable specification which opens up a significant area of functionality lacking from the 1.0 versions, that of inter-portlet communication. The use cases described here give just a couple of simple examples of how this functionality could improve the user experience of working with portals. In conjunction with the rich internet application-type interations made possible by the portlet resource serving features, this should provide the foundations for more responsive and usable portlets, and hence portals. As the platforms that implement the new specifications emerge we will undoubtably see many much more interesting innovations that take full advantage of these new interactions.