Wednesday, August 31, 2005

Understanding JSR168 Portlets by comparison with servlets

What follows is a few loose developer notes for those planning to produce portlets who have an existing understanding of JSP and servlets. I started writing this as a means to crystallise my burgeoning understanding of the portlet specification, if it seems a little dislocated in places that is probably because I don't fully understand the portlet specification properly yet. I've started developing portals using the Pluto portal as my development platform. Using the Pluto admin portlet Deploy War means that I can upload and install my portlets without getting bogged down with hand editing portlet.xml etc.

Firstly for comparisons sake a quick reminder of what should be very familiar to JSP and Servlet programmers. In our servlet containers we have the context interfaces:

  • ServletContext, HttpSession, PageContext
When writing JSP pages these correspond to several attribute scopes:
  • Application (ServletContext)
  • Session (HttpSession)
  • Request (HttpServletRequest)
  • Page (PageContext)

Servlet and Portlet requirements

Whilst a servlet requires only a servlet container to work (i.e. Tomcat, Resin, Orion etc.) a portlet requires a servlet container, a portlet container and a portlet consumer (i.e. a portal). Apache Pluto provides the reference implementation of the JSR168 portlet standard. Pluto is comprised of a portlet container, a simple example portal and some test portlets. The portlet implementation makes use of the underlying servlet container and so there is much direct correspondence between how you would expect a servlet to behave and how the corresponding portlet functionality behaves, there are also some significant differences.

Comparing javax.portlet with javax.servlet

What I have found both comforting and confusing is the apparent similarity between the Servlet specification and the JSR168 Portlet specification. Let us first examine some similarities:

javax.servlet
  • Interfaces
    • RequestDispatcher
    • Servlet
    • ServletConfig
    • ServletContext

    • ServletRequest



    • ServletResponse


  • Classes
    • GenericServlet
javax.servlet.http
  • Interfaces
    • HttpSession
javax.portlet
  • Interfaces
    • PortletRequestDispatcher
    • Portlet
    • PortletConfig
    • PortletContext

    • PortletRequest
    • ActionRequest
    • RenderRequest

    • PortletResponse
    • ActionResponse
    • RenderResponse
  • Classes
    • GenericPortlet
javax.portlet
  • Interfaces
    • PortletSession

Note: The above list is not the full API specification of either javax.servlet or javax.portlet and has been arranged to enable a clear comparison.

Portlets should use portlet methods and portlet tag library

When writing a portlet, however tempting it might be, you should try and abstain from using the javax.servlet specification methods inappropriately. Although technically you can store/access portlet objects using javax.servlet methods there are many facets of the portlet which are wholly dependant on the portlet container and portal implementations. You should learn to make use of the portlet taglib, rather than using relative URLs and such. The portlet taglib will generate portlet instance specific URLs which it obtains via the portlet container and portal.

Pseudo-MVC architecture and the portlet lifecycle

You will notice above that ServletRequest and ServletResponse map to several equivalent Portlet interfaces. For example there are two specialised versions of PortletRequest; ActionRequest and RenderRequest. Much like in MVC frameworks, e.g. Struts, there are several distinct concerns that can be distinguished in a portlet, not all portlet methods need necessarily result in new content being produced in the portal. Like a servlet, a portlet must have the lifecycle methods init() and destroy(). Additionally a portlet must implement processAction() and render() methods. However, if a portlet extends the GenericPortlet it does not need to implement all these methods explicitly and the GenericPortlet adds facility for new "modes" of rendering.

Although clearly related there is an intentional clear separation between ActionRequest and the related RenderRequest object which is usually created subsequently. Attributes stored in ActionRequest scope are not automatically transferred into RenderRequest scope but can be transferred into the render cycle via a special setRenderParameter() methods in the ActionResponse object. To borrow some Struts terminology:

"Action" method of the portlet
processAction(ActionRequest request, ActionResponse response): this is usually called to change state resulting from a user action. It can be called directly from the portlet view by using the portlet taglib <portlet:actionURL> in a hyperlink or form submission.
"View" methods of the portlet
render(RenderRequest request, RenderResponse response): this can either be invoked directly from a view by using the portlet taglib <portlet:renderURL> in a hyperlink or can follow a processAction response.
doView(RenderRequest request, RenderResponse response), doEdit(RenderRequest request, RenderResponse response), doHelp(RenderRequest request, RenderResponse response): called to render specific portlet "MODE" screens
"Controller" component of the portlet
Strictly speaking the Portal and Portlet container act like a MVC controller, at least as far as they control when a portlet is invoked for actions and rendering etc.

To add further MVC-style separation it is advisable that your "View" content should be included using a RequestDispatcher from JSP pages or from XSL transformations but this is not enforced.

I use the term Pseudo-MVC because unlike with Struts the order of interaction is not rigidly enforced by the portlet container. I have yet to understand what best practices for portlet creation are but it is no co-incidence that there is a lot of work around bridging existing MVC architectures like Struts and JSF with the portlet specification. The fit of MVC to portlet appears to be quite a natural one.

crossContext

The Pluto portal is itself a web application. It requires "crossContext" access in order to access portlets stored in other webapp contexts on the application server. This allows the portal to obtain the appropriate ServletContext and invoke the portlets using an appropriate RequestDispatcher.

emptySessionPath for sharing data between servlet and portlet

One thing that confused me was that under certain circumstances, i.e. Tomcat 5.5X with "emptySessionPath" set to true, the portal can use share the same sessionid as the portlets even when they exist outside of the portal's ServletContext. This does not mean that portal and portlet share the same session content. What it does facilitate is that portlets and servlets running in the same web application can share data but the sessions can become very confused if you have both stand alone web applications and portlets sharing the same web application.

PortletSession scopes

The concept of scope extends to the portlet specification but is slightly different when it comes to the PortletSession. There are two possible portlet attribute scopes APPLICATION_SCOPE and PORTLET_SCOPE. A portlet application is stored within a webapp context. There can be several portlets within a single portlet application. Each portlet may have more than one instance in the portal. An object stored in Portlet application scope is available to all portlets and instances thereof installed in that portlet application. An attribute stored in portlet scope is private to a specific portlet instance.

Thursday, August 18, 2005

Using JavaScript to dynamically add Portlet CSS stylesheets

I work as portal developer, currently we use uPortal 2.X but I keep an eye towards future implementations with stronger support for JSR168 portlets. I always endeavour to create (X)HTML standards compliant web applications but sometimes you just have to do whatever it takes in the short term.

First a little portlet and portal background...

Portlets are web applications that, usually, produce little fragments of (X)HTML. Portal software is responsible for assembling these fragments into a web page (in uPortal 2.X speak the portlet mechanism is called a channel). In recent history two related portlet specifications, JSR168 and WSRP, have been created to produce a cross platform standard portlet interface. So in theory once a portlet has been created it should work in any JSR 168 compliant portal.

In uPortal 2.X a portal page is constructed by collecting (and coercing by using a Java version of Dave Raggett's Tidy utility) all portal content into XML. Once the XML fragments have been collected a series of XSL transformations occur to build the page.

The problem...

Any good portal software will allow the user to customise their portal, so each user can receive a true personalised experience of the portal. This means that there is almost no telling what portlets might appear on a particular page. Also, the new portlet standards will make it possible to remotely host portlets and therefore the portal platform maintainers may not have any prior knowledge of the format which the portlet will take. Sure there are certain CSS conventions for the most common portal components but there will be times when some clever DHTML rendering mechanism, branding or such will be part of a portlet.

One thing that has always bothered me with respect to portals is that portlets and uPortal channels (remember these are essentially XML fragments) need to follow XHTML standards. SO therefore if you don’t know what portlets are going to appear on a page in advance how can you assemble all the CSS stylesheet information in the head of the page as the XHTML standards demand.

The solution...

People who I’ve spoken to about this have always had so few portlets in their portals that they can create a <LINK> list in the portal page head of all potential portlet possibilities but this isn’t a satisfactory solution for me.

My solution so far has been to break HTML standards (shock, horror) and include <LINK> and <STYLE> elements inside the body of the page.

I think I’ve found a better solution and that is to load the CSS stylesheets with JavaScript! This will produce standards compliant portal pages since <SCRIPT> elements can appear anywhere on the page. This seems to be a trick that is widely known in DHTML circles but I’ve only just discovered it [Note how IE uses a proprietary method createStyleSheet()]:

<script type="text/javascript">

//<![CDATA[

if(document.createStyleSheet) {

document.createStyleSheet('http://server/stylesheet.css');

}

else {

var styles = "@import url(' http://server/stylesheet.css ');";

var newSS=document.createElement('link');

newSS.rel='stylesheet';

newSS.href='data:text/css,'+escape(styles);

document.getElementsByTagName("head")[0].appendChild(newSS);

}

//]]>

</script>

Now all you have to worry about is clashing JavaScript function, variable and CSS class names! I would hope the Portlet tag library <portlet:namespace> element would be helpful here for generating unique class and function identifiers but being careful not to loose the performance benefits of static CSS and JavaScript files (i.e. dynamically JS/CSS generated files aren't usually cached).

Monday, August 15, 2005

Xmaps Library : An unofficial Google Maps API Extension

This unofficial extension to the official Google Maps API is at the Alpha stage but I like what I see so far.

Long may this continue....

Sunday, August 14, 2005

DynamicPageCache filter using EHCache

There are times when you require a dynamically generated JSP page to be cached on the client side for a certain amount of time. For example if you are producing an XML feed or a page that displays information that need only be recent rather than real time. With an appropriate caching mechanism this can significantly reduce the amount of processing that the server has to do, meaning that the same application instance can serve a much larger audience.

Sometimes it is not possible to know when the Last-modified date for a dynamically generated page should be, for example I wrote one application that converted an IMAP folder into an RSS feed and couldn’t find a satisfactory simple way of obtaining a last modified date from the IMAP server. Sometimes an arbitrary caching period is the best choice (e.g. every ten minutes).

I previously extolled the virtues of the HTTP conditional get mechanism and how projects like ROME FeedFetcher were reducing the load on content providers and at the same time improving local performance. Web browsers too have integral support for the Conditional Get.

So the question is how to provide this Conditional Get information for your content consuming client? Well, if you’ve read my recent entries you won’t be surprised to hear me suggest a servlet filter is the answer.

Feed aggregator application example

In the first version of my feed aggregator application I originally had a page that would make a request to a number of RSS feeds on each request. This was obviously very slow and not scalable, so my solution was to introduce a feed cache. Using ROME, ROME FeedFetcher, EHCache and Quartz scheduler I constructed a background process that would periodically poll each feed for new entries and cache the results, this was far more efficient. However, I still had a page that was dynamically querying my feed cache each time it was called, even though the page would only change once every 10 minutes. What I needed was a mechanism to instruct the web browser to cache this page for a certain duration, so that the page behaved as static content that was updated every 10 minutes. Once again I turned to EHCache as my chosen solution. EHCache is a highly performant cache solution, it is the default cache for Hibernate. A subproject of EHCache is something called EHCache constructs, this includes a SimplePageCachingFilter servlet filter. Unfortunately I couldn’t get the SimplePageCachingFilter filter to work properly in Internet Explorer, so I made a couple of extensions and I now have working Dynamic Generated Page Cache (which incidentally also GZips the page for browsers supporting that kind of thing).

Optimizing Client Side JavaScript: an example

I recently installed AppPerfect Code Analyzer, a free IDE plugin (I use it in NetBeans but it works in Eclipse, JDeveloper etc.). This tool scans your Java classes and advises you on improvements to make your code more efficient. What is nice about this tool is that for each problem it gives a short explanation of why the code is sub-optimal. It seems very keen on reducing the number of new object instantiations in loops. Although this is very definitely not a JavaScript optimisation tool it did give me some transferable ideas.

In previous blog entries I have described my feed aggregator application and how recently I was moving some of the functionality from the server side JSP to the client side JavaScript.

I wrote a particularly time consuming JavaScript function which was taking an unacceptably long time to process on the client side. The function traverses the HTML document looking for list items with a particular proprietary attribute and then conducts some processing based on the contents of a cookie and this attribute value. Lets concentrate on this single function, the first incarnation of this function looked like this:


function traverseDates(node, cookieDate) {
if (node.nodeName == 'UL'){
if(node.hasChildNodes()) {
for(var i=0; i< node.childNodes.length; i++) {
if (node.childNodes[i].nodeName == "LI")
{
for(var j=0;j<node.childNodes[i].attributes.length;j++)
{
if (node.childNodes[i].attributes[j].nodeName == "gofetch:date")
{
var linkDate = node.childNodes[i].attributes[j].value;
if (parseInt(linkDate) < parseInt(cookieDate))
{
node.childNodes[i].className="old";
}
}
}
}
}
}

}
if(node.nodeName != "LI")
{
if(node.hasChildNodes()) {
for(var i=0; i < node.childNodes.length; i++)
traverseDates(node.childNodes[i], cookieDate);
}
}
}

It has to be said it was taking an especially long time to process on Internet Explorer, Firefox seemed to be outperforming Internet Explorer in it’s HTML DOM processing. Document traversal is by nature recursive [teacher joke: in the dictionary it says recursion: see recursion]. Recursive functions are essentially loops and therefore anything that reduces the number of unnecessary object instatiations and DOM object lookups will improve performance; so with this I mind I modified the above function to become:


function traverseDates(node, cookieDate) {
var nodeName = node.nodeName;
var hasChildNodes = node.hasChildNodes();
if (nodeName == 'UL'){
if(hasChildNodes) {
var length = node.childNodes.length;
for(var i=0; i<length; i++) {
var currentNode = node.childNodes[i];
if (currentNode.nodeName == "LI")
{
var linkDate = currentNode.getAttributeNode("gofetch:date").value;
if (parseInt(linkDate) < parseInt(cookieDate))
{
currentNode.className="old";
}
}
}
}

}
if(nodeName != "LI")
{
if(hasChildNodes) {
var length = node.childNodes.length;
for(var i=0; i<length; i++)
traverseDates(node.childNodes[i], cookieDate);
}
}
}

This performs better than the first function, I’m not sure why I didn’t think of using getAttributeNode before but introducing this removed an unnecessary loop. Accessing document objects once and reusing these references also made a difference. Below is my final attempt:


function traverseDates(node, cookieDate) {
var hasChildNodes = node.hasChildNodes();
if(hasChildNodes) {
var nodeName = node.nodeName;
var length = node.childNodes.length;
if (nodeName == 'UL'){
for(var i=0; i<length; i++) {
var currentNode = node.childNodes[i];
if (currentNode.nodeName == "LI"){
var linkDate = currentNode.getAttributeNode("gofetch:date").value;
if (parseInt(linkDate) < parseInt(cookieDate)){
currentNode.className="old";
}
}
}

}
if(nodeName != "LI"){
for(var i=0; i<length; i++)
traverseDates(node.childNodes[i], cookieDate);
}

}

}

I’m not saying this is the most optimal solution but the performance in Internet Explorer is now acceptable, problem solved. If people are going to move serious processing into client side JavaScript then the need to optimize JavaScript is going to become more widespread. Maybe we even need a JavaScript optimizer tool that does more than trying to reduce the file size, there may be one out there but I've yet to find a good free one (please advise me if you know different).

Saturday, August 13, 2005

Filters, filters everywhere..

Some interesting servlet filters I’ve been working with recently.

Tags :

Thursday, August 11, 2005

Please KISS (Keep it Simple, Stupid)

KISS (Keep it Simple, Stupid), I’m not a technology guru, poet or philosopher but I value this principle above all others.

I am very suspicious of people who waffle and give over elaborate descriptions that "I simply wouldn’t understand". Rather than question my own intelligence, I put it down to their inability to give simple answers to straight questions. I feel people often babble because they are trying to divert my attention from their ignorance of the subject matter! It is amazing how many experts there are these days and how few people in technical circles are brave enough to say "I don’t know". Socrates said something like "A wise man knows what he doesn't know" and this has never been more true.

Simplicity has been defined as "the absence of unnecessary elements", I don’t mind optional extras but they should be just that optional. My favourite software all has one thing in common, it does one thing and it does it well. I despair when I download some new package and see how much new complexity there is to cope with, IDEs seem to be particularly culpable in this respect and open source offerings are by no means immune from this...

When I can’t use a piece of software straight off, it isn’t because I am stupid or need training (I suspect it was designed this way deliberately?). This is not to say I am not willing to spend time learning new things; XSL, Struts, Hibernate, Maven and Spring for example all require a little time invested in tutorials before you can begin to feel the benefits. You only have to look to nature, each cell and leaf is a simple optimal offering, not without hidden layers of sophistication, repeated hundreds of times over to build something greater than the some of its parts.

Wednesday, August 10, 2005

Unobtrusive AJAX JavaScript with Behaviour JS Toolkit

I just found the Behaviour CSS/JavaScript toolkit, very cool, I can now create drag and drop DHTML interfaces with HTML that will pass accessibility tests! Technically this isn't AJAX but it is very clever and no more a misuse of the term than any of the other's I've seen recently. AJAX seems to have been adopted by any technology doing some kind of clever DHTML lately. True AJAX is about loading and processing XML on the client side. GMail, Google Suggest and Google Maps are excellent examples where lots of clever DHTML thinking is occurring in one place and this phenomenon has been labeled AJAX (even when technically the actual AJAX part is only one component in a suite of cleverness, as it is in Google Maps).

Some other interesting "AJAX" resources are linked from the Behaviour project page:

And here are a couple of real world portals embracing AJAX style:

Tags :

Sunday, August 07, 2005

Adding Proprietary Attributes Saga: The X in XHTML

I was recently working on some modifications to my feed aggregator application and have been inspired by the recent trend in high profile applications (Gmail, Google Maps etc) to move some of the processing from the server to the client side.

What I wanted to achieve was the behaviour of JavaRSS.com but with the "what’s new" processing happening through JavaScript on the client side. In this way I can deliver a static page and with JavaScript manipulation of cookies and a little DHTML I can have it appear to the client that it is doing some sophisticated personalisation.

My simple solution was to add a date attribute to the list items on my unordered newsfeed lists. I can then access this attribute using DOM in client side JavaScript and change the CSS class of the list item to new/old appearance as appropriate.

So I did this and it works, it is well-formed XML but it produces XHTML that does not validate as XHTML (it has potentially hundreds of warnings). Hold on, I thought, doesn’t the X in XHTML stand for Extensible? I can make it standards compliant by adding my additional attribute into the DTD of XHTML and therefore make it standards compliant or so I thought...

I managed to create a page that would pass for XHTML 1.0 strict (actually it said it was tentatively valid) and as valid XHTML 1.1 strict. However the page now has annoying "]>" characters at the top, grrr.

Valid but look bad:

The "]>" disappear in Firefox if you change the extension to ".xhtml" but then IE can’t read it.

I tried defining an external XHTML 1.0 DTD but I didn’t get very far as a lot of online validators seem to ignore external custom DTDs.

Invalid (who knows why!):

I read somewhere that XHTML 1.1 is actually designed to be extensible whereas XHTML 1.0 isn’t really designed that way. So I tried to create an external XHTML 1.1 DTD. Don’t get me wrong, I’m not some kind of genius but I have a fair understanding (or so I thought) of XML, XSLT, DTD and XML Schema and the like. I even check the DTD when something in my Tomcat WEB.XML isn’t working right. So you’d think I’d be able to understand the XHMTL 1.1 Modularisation concepts, sorry to tell you that this appeared to me to be completely unintelligible (perhaps you have to be in the right mood). As I said I’ve been working with XML technology for years. What hope would a novice have of creating an XHTML 1.1 extension? Please note, I only actually wanted to add a single attribute (in a different namespace) to XHTML and so you would think it would be really easy...

Conclusion

My conclusion from all this would be that however well intentioned you might be towards standards you occasionally have to "stuff the standards".
Version 1 of the above works in both the browsers that I care about it working in (IE and Firefox) and that is all that really concerns me.

Resources used: