Starting with this post, I would like to describe a new script interface called XMLPortletRequest. The intent of this interface is to provide a means for portlets to implement asynchronous and/or partial page updates within the portal/portlet paradigm, and yet remain compatible with Ajax toolkits and portlet bridges (JSF, Struts, Spring MVC etc.). I developed this approach several months ago, and the portlet-related specification groups, viz., JSR-286 in the Java-land, and WSRP in the language-agnostic web services land, are actively considering this interface as the basis for building Ajax-related solutions. Some specifics of this model are still being debated in these groups, but the semantics of the model are more or less finalized. Please read on for some background and details.
Problem 1: Reacting to XMLHttpRequest
Portlets are like widgets, and are meant to be aggregated in a portal page. For instance, if you think of the various modules on a Google home page, each module is like a portlet, and is designed to be rendered in a page containing other modules as well as other Google-generated markup.
JSR-168 provides a programming model for developing portlets. Alternatively, you can use frameworks like JSF, Struts, Spring MVC etc to build web apps and deploy those as portlets via portlet bridges. These bridge portlets translate respective framework API calls/life cycle into portlet API calls/life cycle.
The JSR-168 API is designed such that all user interactions go through the portal, which then invokes portlets. When you create a URL using this API (such as an action URL or a render URL), the URLs generated point to the portal. When you send a HTTP request to a portal using such a URL, the portal processes the request first, then goes through the lifecycle of each portlet, and at the end of this process, generates a full page and sends it back to the browser. This model works as long as you are using regular GET and POST submissions with action and render URLs over HTTP. When you bring in XMLHttpRequest into this picture, funny things start to happen. See Figure 1 from the paper titled Best Practices for Applying AJAX to JSR 168 Portlets.
XMLPortletRequest is designed such that a portal can deliver what the portlet generated on the server side.
Problem 2: Coordination aka Inter-Portlet Communication
In most cases, portlets are self-contained and do not effect each other. Such portlets can be added/removed at will without effecting other portlets on a page. This decoupled nature makes portlet development and deployment easy. But the down side is that, for the end user, the UI looks less interesting. Silos are not not the best way to present UI in a browser.
The upcoming JSR-286, and WSRP 2.0 specifications allow an exception to this. These specifications add an ability for portlets to communicate with each other in a loosely-coupled manner. One of the key mechanisms for doing this is by using events. Events are named, and can optionally have a payload with them. Using this mechanism, based on some user interaction, one portlet could fire an event that other portlets can handle. Upon handling the event, those portlets can fire more events, and the chain can continue until some system limit occurs. In this model, portlets don’t send events directly to each other, and the portal acts as a coordinator for event distribution. During event processing, portlets can change their own state (e.g. change some back-end data). After the event chain completes, the portal renders each portlet with their latest state. In this way, portlets can still remain loosely coupled, and yet influence each other. In essence, events make it possible for a user interaction with one portlet to change the view of not just the portlet that the user is interacting with, but other portlets on a portal page as well. In some cases, the portal itself may want to handle some events, and its own markup may change.
Here is an example. Let’s say, a portal page is aggregating two portlets, viz A and B. A submits an XMLHttpRequest to the server, which then invokes portlet A. As part of processing the request, A fires an event that B can handle. The portal dispatches the event to B. A then generates some JSON data to be returned via the responseText field of the XMLHttpRequest. While processing the event, portlet B changes its state, and its view in the browser becomes stale. The portal then needs to render B as well, and update its UI in the browser.
Portlet A’s script that started the XMLHttpRequest does not know much about portlet B, and hence the portal can not simply return portlet A’s JSON data and portlet B’s HTML view in the same response to portlet A. It needs do something special. Again, the XMLPortletRequest interface is designed to solve this problem such that (a) portlet A can receive its JSON data, and (b) the portal can update portlet B’s view independently. The approach is not limited to events. Depending on how the portal is implemented and the features it supports, it can update any part of the portal page when several fragments of a page needs to be updated in response to a portlet’s XMLHttpRequest.
Problem 3: Toolkits and Bridges
Component libraries like ICEFaces share both flavors. ICEFaces is an Ajax toolkit, but uses JSF as the programming interface, and hence can be used via a JSF portlet bridge.
The XMLPortletRequest API is designed to minimize the amount of translations to be done in bridges and adoption of Ajax toolkits like Dojo easy.
I will discuss more about this interface in my next post.