Understanding Portlet 2.0 (JSR 286) - Part 1
Portlet 2.0 or JSR 286 is the latest revision of the Portlet spec. The specification work is still in progress and a early draft was published for review about six months back. However, this is the first time I am having a close look at this new spec – hence these notes.
Portlet 2.0 seems to be a good step forward for the Java EE portals landscape. It tries to address some of the key shortcomings of it's previous version. Portlet 1.0 was a pretty rudimentary spec which left out, perhaps intentionally, a lot of thorny issues and Portlet 2.0 seems to make up for it. That's good.
The first major difference you would notice is the redefinition of the Portlet lifecycle from a 4 phase one to a 6 phase one. The portlet lifecycle in Portlet 1.0 is defined thus:
Here, the init() and destroy() have precisely the same connotation as they do in the servlet world. init() is the callback for resource initialization and destory() is the callback for freeing up resources. The processAction() and render() methods are however interesting. Why would portlets require two different methods while servlets can do with a single service() method ? The answer lies in understanding the difference between the Servlet and Portlets.
A normal web application, being standalone, needs to display content only when it is acted upon i.e user clicking a link, user submitting a form, user scrolling a map that results in an Ajax request etc. On the contrary, a portlet application needs to display content not just when it is acted upon, but also when another portlet on the page is acted upon. This is because portlets typically share a page with other portlets.
Hence Portlet 1.0 defines two request phases. One to denote that a portlet was acted upon (processAction()). And the second to denote that a portlet needs to refresh it's content (render()).
To illustrate this point, consider the case where a user is accessing a portal page that has 10 portlets. If the user clicks a link on one portlet, only that portlet is acted upon. Hence processAction() is called only for that portlet. However, since the entire page needs to be rendered after this action, the render() method is called on all of the 10 portlets on the page. Hence the single user click will result in 1 processAction() call and 10 render() calls.
Let me be quick to point out these calls are not to be confused as separate HTTP requests. In reality, there is only one HTTP request/response between the user and the portal. This one HTTP request can be logically viewed as 1 +10 = 11 calls to the portlets. It would look something like this:
One key assumption in this 2 phase request processing model is that a portlet will change state only when it was acted upon i.e state change will occur only during the processAction() call. No state changes will occur during a render() call. In other words, render() is idempotent and processAction() is not.
Portlet 1.0 fails to take a few important things into consideration. Firstly, the assumption that portlets are always completely independent of each other is not true. Consider a Weather portlet and a Google map portlet being present together on the same portal page. It is perfectly natural for a user to choose a new location on the map and expect the Weather portlet to update accordingly.
Unfortunately, the spec does not provide any means by which one portlet can “notify” changes to it's state to the other portlet, even though both the portlets are present on the same portal page and are contributing to the same aggregated portal content. Hence developers are left with no choice but to resort to workarounds like writing to / reading from a shared memory space. Portlets within the same web application are typically coded to use the HTTP session. For portlets that are in separate web applications, matters are worse.
The second limitation is in the ability to serve dynamic resources. According to Portlet 1.0, a portlet has limited access to the underlying HTTP request and response objects. The rationale behind this restriction is that portlets are responsible for only generating fragments of content. It is the aggregation layer, namely the portal, that is responsible for assimilating these fragments into the final portal page. The spec overlooks the fact that there are valid usecases for a portlet to generate content that are not necessarily fragments. For instance, how would you write a portlet that can dynamically generate a pdf report on click of a link ?
Since the spec prohibits the portlet from accessing the outputstream of the HTTP response, the answer is not so simple. Many developers currently workaround this issue by providing a direct link to a servlet in the fragment generated by the portlet. When the user clicks the button, the servlet is invoked and it can write the generated pdf file back to the client. The problem with this approach is that the entire portal layer is bypassed and hence services provided by the Portal layer like say security is unavailable for such an interaction. Here is an illustration:
Lastly, Portlet 1.0 overlooked something that has become increasingly relevant today – asynchronous HTTP calls or Ajax. Portlet 1.0 was defined at a time when async calls were unreliable across browsers and relying on javascript for functionality was considered a bad thing. Times have changed and the spec needs to play catch up.
Portlet 2.0 addresses all the three key limitations that I mentioned . It also defines a whole lot of new things like Portlet filters, annotations etc. In my next blog entry, I plan to discuss some of these new features in detail.
Posted at 12:29PM Feb 01, 2007 by Navaneeth Krishnan in Portlet | Comments[8]
This work is licensed under a
Creative Commons Attribution-NonCommercial-NoDerivs 2.5 License.
Posted by svenmeier on February 01, 2007 at 03:28 PM IST #
Posted by Craig Doremus on February 01, 2007 at 05:40 PM IST #
Posted by Navaneeth on February 01, 2007 at 08:01 PM IST #
Posted by Bob Balfe on February 03, 2007 at 07:22 PM IST #
Posted by Craig Doremus on February 05, 2007 at 09:58 PM IST #
Posted by Navaneeth on February 13, 2007 at 02:11 PM IST #
Posted by Prasad M on March 07, 2007 at 04:38 PM IST #
Posted by Prasoon on March 12, 2007 at 05:46 PM IST #