I spent a few weeks researching different approaches and frameworks to developing portlets. The basis for this research was to find a good methodology to developing portlets for uPortal 3.0. A specific desire was to try to find a way to reuse as much functionality as possible across different portlets.
Portlets are different from uPortal Channels. uPortal Channels are not an industry standard. Portlets are different from Servlets. Portlets are Servlets are both industry standards, but Portlets may not assume complete ownership of the web page they are presented in.
Many frameworks exist for Servlet application development. However, most of these frameworks do not account for the fundamental differences that are inherent to a portlet. Consequently most Servlet based frameworks either do not work, or work, with many restrictions and hacks put in place.
The following frameworks were investigated.
- Struts
- Spring
- MVCPortlet
- JavaServer Faces
MVCPortlet
Let me start off with MVCPortlet. This framework was built by Nabh Information Systems, Inc (http://www.nabh.com/). It is the only framework that was built with Portlets in mind. The framework is available as open source, but appears to be tightly controlled by Nabh. The website itself had a strange feel to it, during navigation (appears cookies, may have tracked which pages you were on, rendering the standard back/forward buttons useless). The framework appears like many others to be based on using JSP pages for a "view" technology and providing a framework of java code for helping write the back-end logic. For me, a very significant impression was made by looking at the JSP pages presented in the documentation, and how most everything was done with scriplets. The JSP pages were more 'java' code then they were anything else. It is my recommendation that if JSP pages are used tag libraries should be used as much as possible, scriptlets should not be required.
I recommend against using MVCPortlet for three reasons. 1) The heavy use of scriplets implies a poor overall design. 2) The framework is still considered beta, and therefore could undergo fundamental api changes causing us to have to rewrite code to upgrade to a stable release. 3) There is no past history with the Nabh community to know what the life expectancy of this framework is.
JavaServer Faces
In the last year the JavaServer Faces (JSF) technology has gathered a pretty decent following. JSF 1.0 was created under the Java Community Process with JSR-127. Since then version 1.1 has been released and version 1.2 is in the works (JSR-252). The goal of JSF was to allow people to think about building web applications in a different way. Allow developers to build components and not worry about creating servlets, pages, or views. The way this is accomplished in a web environment is with the JSF technology owning the servlet that is used and playing a heavy role in the resulting HTML that is sent to the browser. JSP pages seem to be the only view technology current available (although the specification allows room for other view technologies to be developed).
Portlets are not servlets, and there is a slight problem with having your core application be a JSF servlet. A Porlet "add-on" library was written to allow a JSF application to be distributed as a Portlet Web application. I was able to take two examples from the JSF Reference Implementation and get them running as portlets inside of uPortal 2.4+ (CVS Head on March 21, 2005, they would NOT run in uPortal 2.4.2) with this add-on library. My impressions were pretty sub par. The portlets would consistently flake out. It was very common to have to logout/login, or stop/start the server, multiple times, with no other changes, to get the portlets to run. Another design issue seems to be the idea of the 'beans' it creates for each user session. There did not appear to be a way to specify any beans as 'reusuable' across multiple sessions. This means for every user login every bean configured for this application, must be created. The memory overhead that could be associated with this is a concern.
I recommend against using JavaServer Faces for the following reasons. 1) portlets are not officially supported, and the portlet-add on library appears unstable in uPortal 2.4+. 2) memory could be a concern if all beans are always created for all user login sessions and there is no way to reuse a paticular bean acrosss different users sessions. 3) it's very different from other portlet/servlet technologies and could be harder for the uPortal community to initially support. 4) There is no apparent support for Portlet Modes or Preferences.
Struts
Struts is a very popular and widely adopted MVC framework for the web. The current stable version is 1.2.4 and 1.2.6 is currently in beta. Struts is also based on Servlet technology and does not currently directly support Portlets. There are currently two proposals for Struts 2.0.x (Shale and Jericho) and it is not clear what the timeframe is for direct Portlet support.
The Jetspeed-2 portal project developed a library called "portals-brdiges" that can be used to run Struts based applications as portlets. There is a desire to make this library it's own subproject. Using the library requires you to use JSP pages and places numerous restrictions on how you write your struts application. I was never able to successfully pull the 'portals-bridges' library out of jetspeed-2 and get a sample application running in uPortal.
Stuts is very popular and can make creating many web applications quicker, by elinimating writing most of the dispatcher logic that is typically writtent with other frameworks. However, there are many opponents to Struts as well. Regardless, the inability to get any struts based example running in the time of this research, means it is impossible to consider struts an option for now.
Spring
Spring is component based framework that accomplishes a lot more the just an MVC Framework. Spring is being used by uPortal 3 for non-MVC activities. I researched the MVC aspects that Spring current offers. The latest stable release of Spring is 1.1.5. Version 1.2 of Spring was nearing release at the time of this research. And Spring 1.3 is intended as the next release after 1.2, with a possible timeframe of Summer 2005. One component of Spring is called the "Spring Web MVC" component, and offers a framework for Servlet based web applications. The released version of Spring Web MVC does not support Portlets. There is code available in the development area of Spring (the 'sandbox' directory of the spring cvs repository) that extends Spring Web MVC for Portlet support. I followed up on the Spring Mailing Lists, the Wiki pages, and obtained and compiled the code.
At the most basic level the Spring Portlet support appears to be in the form of the PortletController class. You can extend this directly or use one of the convenience classes that extend it for you. One concern I have is the PortletController provides you the ability to override two methods. Both of these methods are named 'handleRequest' but are overloaded with different parameter lists. These two methods are roughly equivalent to the 'processAction' and 'render' methods of the Portlet interface. I assume the names were chosen based on extending support from the Web MVC controller class which contains one handleRequest method. However, that does not excuse what is fundamentally poor design. Effective Java does a good job at describing this situation on page 111. Overloading of methods should NOT be used for two fundamentally different activities. Except for this one poor design choice, I did not find any other notable problems with the framework. I also did not find a lot of value either. The framework simply does not do very much for you.
I do not currently recommend using Spring Web MVC for the following reasons. 1) Portlet support is not part of an official release and could potentially change before making it into one. Changes could cause any uPortal code to need to be rewritten to upgrade to a more stable version of Spring. 2) uPortal 3 is currently using Spring, however, it is being written to a version that does not include Portlet support. There is a chance the version that would include portlet support might be incompatible with the version that the other uPortal code was written to. 3) the design choice of calling both the render and action methods 'handleRequest' diminishes the significant importance of these two operations.
The Code
As part of this research I tried to create an equivalent application in the frameworks I could get running. I was able to get a version of the standard number guessing game running under JavaServer Faces, Spring and "no framework". I was able to convert my "no framework" application to a Spring Portlet based example in less then a couple of hours. I made no attempt to go to/from the JavaServer Faces code, and instead just based my examples on the funcationality provided.
In designing the code for the "no framework" baseline, I tried to come up with a rough framework oriented layout of classes. I created three packages "web", "bean" and "action". The idea was whichever framework was chosen any controller/portlet/dispatcher style classes would go into the "web" package. The data driven (model) style classes would go into the "bean" package. Finally, the "business logic" classes that were responsible for acting on the actual web driven events would go into the "action" package.
I used JSP pages for a view technology because of the existing Portlet tag library defined by the Portlet specification. I also used the JSP Standard Tag Library (JSTL). I avoided using any scriptlets in the JSP pages.
You can see the examples in the attached code. Each .zip file contains a WAR file that can be deployed in uPortal 2.4.2 (or above). The WAR file is located in a 'dist' subdirectory for each .zip archive. When publishing the portlet channel in uPortal the portlet definition Id for each example is simply the WAR filename period WAR filename (e.g., the portlet definition id for GuessNumberPortlet.war is GuessNumberPortlet.GuessNumberPortlet). The two JSF examples (JsfGuessNumberPortlet and JsfCarStorePortlet) will NOT run in uPortal 2.4.2 or 2-4-patches (head of 2.4 branch). These JSF examples will run in the CVS Head (aproximately 2.5) version of uPortal. I believe this might have to do with a newer version of pluto in the HEAD version of uPortal CVS.
Recommendation
I recommend not using any existing framework I reviewed at this time. Instead coding our portlets with a common dispatcher pattern that can be easily converted to another framework in the future (e.g., Spring Portlet MVC). I recommend we use JSP pages for view technology to take advantage of the Portlet tag library for handling Portlet URLs within the view page. We can accomplish reusability between portlets we write by using the include mechanism of JSP pages and writing coresponding backing data beans. This approach leaves uPortal as decoupled as possible from frameworks that are still in development, and does not require us spending a large number of hours writing our own framework.
Future Considerations
Although not originally looked at by this research a couple of other projects seem related that should be considered in the future.
Spring Web Flow and Struts Flow are subprojects to their corresponding parent projects. Each project appears to also be involved in the larger web application framework picture. In paticular the tiny little bit of exposure I had to Spring Web Flow, by reading the Spring Mailing list, it appears like it might bring some of the Struts like action/state configuration to the Srping Web MVC. If the Spring Portlet MVC is ever released and Spring Web Flow integrates with that, the combination could be a significant platform. Struts Flow appears to allow for more complicated struts application configuration. However by virtue of being a sub project, it might be useable by another Portlet compatible framework, whereas Struts itself is not.
JavaServer Faces will need to be looked at periodically. With Sakai 1.5 and beyond based on JSF, uPortal will need to support JSF. As long as uPortal must support JSF, it should be considered a viable framework for consideration. The two things to continue to look at here are the stability and memory concerns.
Tiles offers a more robust way to put together web pages. Although the technology is roughly equivalent to the include mechanism of JSP pages it can offer a lot more if a lot of thought goes into setting up the pieces correctly. There is no reason Tiles cant be used right away with the approach recommended, this is simply pointing out that to make effective use of Tiles, would require some more time in coming up with the best ways to use it.