Introducing the Portlet Specification, Part 2
The Portlet API‘s reference implementation reveals its secrets
Summary In this second and final article in Stefan Hepper and Stephan Hesmer‘s portlet series, the authors move beyond the Portlet API basics outlined in Part 1 to detail the API‘s reference implementation (RI), known as Pluto. They also offer a series of example portlets to illustrate how you can extend the API‘s standard functions. (1,700 words; September 5, 2003) By Stefan Hepper and Stephan Hesmer
nterprise portal vendors use pluggable user-interface components, known as portlets, to provide a presentation layer to information systems. Unfortunately, in the past each vendor defined its own portlet API, producing incompatibilities across the industry. To standardize the process, the Java community launched Java Specification Request (JSR) 168: the Portlet Specification.
Part 1 of this two-part series examined JSR 168 in detail. This final article focuses on the Portlet API‘s reference implementation (RI), also known as Pluto. The RI provides a working example portlet from which you can launch your own development efforts.
Read the whole series on the Portlet Specification:
This article‘s first section describes the RI‘s architecture, including the portlet container‘s plug-in concept and how to reuse the container in other projects. The second section explains how to install and use the RI, as well as how to quickly deploy portlets. The article concludes with a series of progressively more complex portlet examples.
Note: You can download this article‘s source code from Resources.
Pluto‘s architecture Let‘s begin by examining Pluto‘s architecture and underlying concepts. First, we briefly explain the portal that runs the RI, and see where to find a portlet container inside a portal architecture. Next, we investigate Pluto‘s architecture in detail. Last, we look at how it solves one challenging item of the portlet container: portlet deployment.
The portal Pluto normally serves to show how the Portlet API works and offers developers a working example platform from which they can test their portlets. However, it‘s cumbersome to execute and test the portlet container without a driver, in this case, the portal. Pluto‘s simple portal component is built only on the portlet container‘s and the JSR 168‘s requirements. (In contrast, the more sophisticated, open source Apache Jetspeed project concentrates on the portal itself rather than the portlet container, and considers requirements from other groups.)
Figure 1 depicts the portal‘s basic architecture. The portal Web application processes the client request, retrieves the portlets on the user‘s current page, and then calls the portlet container to retrieve each portlet‘s content. The portal accesses the portlet container with the Portlet Container Invoker API, representing the portlet container‘s main interface supporting request-based methods to call portlets from a portal‘s viewpoint. The container‘s user must implement the portlet container‘s Container Provider SPI (Service Provider Interface) callback interface to get portal-related information. Finally, the portlet container calls all portlets via the Portlet API.
Figure 1. The simple portal included with Pluto. Click on thumbnail to view full-size image.
|
The portlet container The portlet container, the portlets‘ runtime environment and a core component of each portal, requires knowledge about the portal itself and must reuse common code from it. Consequently, the portlet container remains completely separated from every other portal component. That said, you can embed the standalone portlet container in any portal by complying with the portlet container‘s requirements, such as implementing all SPIs.
The Portlet Container Invoker API, also called an entrance point, acts as the portlet container‘s main calling interface. The API combines a portlet container‘s lifecycle (init , destroy ) with request-based calling methods (initPage() , performTitle() , portletService() , and so on). Because the portlet container calls a portlet in the end, the method signature resembles the Portlet API‘s main portlet interface, except that a portlet identifier must be passed. With this additional portlet identifier, the container can determine the portlet and call it accordingly.
Besides using the APIs to access the portlet container, the portal must implement SPIs defined for the portlet container. Therefore, the RI introduces container services: pluggable components that can be registered at the container to either extend or provide basic functionality. The RI includes the following built-in container services (the first four must be implemented to run the portlet container, while the fifth is optional):
- Information provider: Gives the portlet container information about the portal and its framework. Only known information or information that should be stored within the portal is present through this interface. Such information includes URL generation with navigational state, portlet context, portlet mode, and window-state handling.
- Factory manager: Defines how to get an implementation through a factory. (A normal portal should already own such an implementation.)
- Log service: Defines a logging facility. (A normal portal should already own such an implementation.)
- Config service: Defines how to get configuration values. (A normal portal should already own such an implementation.)
- Property manager (optional): A property manager interface implementation lets a portal handle properties as defined in the JSR 168 specification.
Strictly speaking, the Portlet Object Model also acts as an SPI, but has an exceptional position among the SPIs. Therefore, don‘t consider it part of the container services as it deals with all portlet objects and comprises a collection of interwoven interfaces.
Figure 2. The portlet container‘s architecture. Click on thumbnail to view full-size image.
|
Portlet deployment The portlet container can leverage the servlet container‘s functionality, upon which the portlet container is built. To accomplish that, the portlet container must inject servlet artifacts into each portlet-application war file, as Figure 3 shows. The portlet component, Deployment, takes the original war file, then injects a new or modified web.xml and a servlet to wrap each portlet and uses it as a calling point. Then the portlet deployment passes the modified war file to the application server deployment, which deploys it into the application server‘s system. During the portlet‘s invocation, the portlet container calls the injected servlet as an entrance point into the deployed portlet war file.
Figure 3. Portlet deployment in the RI. Click on thumbnail to view full-size image.
|
Pluto and the WSRP standard As described in Part 1, JSR 168 aligns closely with the Web Services for Remote Portlets (WSRP) standard. Both standards, which emerged at the same time, released open source implementations capable of all necessary functions described in the respective specifications. As a mutual goal, both standards strive to work well together. As a result, the portlet container can run WSRP portlets as a consumer as well as a producer.
Pluto must be able to run multiple portlet containers in one portal. Consequently, Pluto‘s portlet container can be instantiated multiple times and, more importantly, it can be instrumented in different ways. Each portlet container, therefore, can use different implementations for SPIs.
Install the RI You‘ll find Pluto‘s installation process straightforward and easy—simply execute the install command, either install.bat or install.sh , located in the build directory /build . After you start the command, the installation asks for Tomcat‘s installation directory. (Note: In Microsoft Windows don‘t use backslashes in the directory.)
After that, the installation process builds the RI and all portlets, then installs the portlets into the designated Tomcat directory. Please read all the important notes printed after the installation to ensure you perform all necessary manual steps.
Now simply start Tomcat and access the RI via http://localhost:8080/pluto/portal . That‘s all!
How to deploy portlets Portlet deployment in Pluto is even easier than the installation process. Just remember you must install Pluto first, as that process sets the prepareRun.properties correctly, which the deployment process requires. Simply open a command prompt pointing to the build directory, and then enter the following line in which the parameter defines the portlet war file to be deployed:
deployPortlet.bat C:\pluto\portlets\bookmark_04\driver\bookmark_04.war
Example portlets Let‘s look at an example portlet, the Bookmark, to put the Portlet API to its best use and apply the concepts you‘ve learned. Beginning with the first simple example, each section below extends the Bookmark portlet step by step, finishing with an advanced portlet that employs nearly all aspects of the Portlet API.
Bookmark portlet: Version one The first simple Bookmark portlet employs the following Portlet API features:
- The Portlet API interface
- JavaServer Pages (JSP) pages
- The Portlet API tag libraries
- Deployment descriptors
The first example Bookmark portlet‘s two JSP pages render in the view or edit mode. Each JSP page simply shows the portlet‘s currently active portlet mode and window state. To display that information, use the Portlet API tag library:
public void doView (RenderRequest request, RenderResponse response) throws PortletException, IOException { response.setContentType("text/html"); String jspName = getPortletConfig().getInitParameter("jspView"); PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(jspName); rd.include(request,response); }
Next, the following code shows a simple JSP page used in the example:
<%@ page session="false" %> <%@ page import="javax.portlet.*"%> <%@ page import="java.util.*"%> <%@ taglib uri=‘/WEB-INF/tld/portlet.tld‘ prefix=‘portlet‘%> <portlet:defineObjects/>
Hello,<br> I am the bookmark portlet.<br> <br> Current Portlet Mode: <%=portletRequest.getPortletMode()%><br> Current Window State: <%=portletRequest.getWindowState()%><br> <br>
Bookmark portlet: Version two The second Bookmark portlet advances to the Portlet API‘s persistence concept. In addition to the Portlet API aspects from the first version above, the second version employs:
- Action handling
- Portlet preferences
- A preferences validator
- Predefined preferences in the deployment descriptor
In the second Bookmark example, two new JSP pages replace the two from version one. First, edit.jsp lets you add or delete bookmarks by using portlet actions. All bookmarks entered in that JSP page become stored in the portlet preferences. Second, view.jsp shows the bookmarks stored in the portlet preferences as clickable hyperlinks. Beyond those changes, version two uses a preferences validator, which checks that a preference doesn‘t start or end with whitespaces.
Bookmark portlet: Version three Version three includes the same functionality as version two, except it additionally supports English and German. To support multiple languages, the Portlet API employs standard methods based on the Java technology and servlet specifications. The Bookmark portlet version three, consequently, uses the Portlet API‘s and Java technology‘s localization features to support multiple languages:
- Localizable deployment descriptor
ResourceBundles
Now the deployment descriptor and both JSP pages, which get all their displayable text from ResourceBundles , support English and German.
Bookmark portlet: Version four The final portlet example demonstrates the navigational state concept, which the Portlet API realizes with render parameters. Version four shows, per default, seven bookmarks, but displays only five on one page, as Figure 4 shows. By clicking on the next and back hyperlinks, the user can navigate to the next or previous five bookmarks. The starting point, stored as a render parameter, lets users use the browser‘s reload, back, and forward buttons.
Figure 4. Bookmark portlet version four‘s view mode. Click on thumbnail to view full-size image.
|
Portlets to the rescue As you‘ve seen, the Portlet Specification‘s RI features two main components: a portal and a portlet container. The portal acts as a simple test driver to run the portlet container. The portlet container acts as a generic component quickly adaptable to run in other portals, such as Jetspeed.
The example portlets outlined in this article employ many important Portlet API concepts. Going forward, you can extend the examples further by using all of the Portlet API and Servlet API features. For example, you could enhance the Bookmark portlet with a servlet that outputs a complete markup inside a new window, such as a print preview, and communicates with the portlet via the HttpSession . Indeed, because portlets represent such powerful technologies, the possibilities are boundless.
About the author Stefan Hepper received a Diploma of Computer Science from the University of Karlsruhe. After working for three years in the Research Center Karlsruhe in medical robotics and component-based software architectures for real-time systems, he joined the IBM Pervasive Computing division. He is now an architect for the WebSphere Portal team, responsible for Java standards. Stefan has been working with Java since 1997 and is one of the two specification leads for JSR 168.
Stephan Hesmer received a Diploma of Information Technology from the University of Cooperative Education Stuttgart in 2000. After graduating, he joined the IBM Boeblingen Development Laboratory to work with the WebSphere Portal team. Currently he is the architect and team lead of the Portlet Environment in WebSphere Portal and of the JSR 168 reference implementation. Stephan has worked with C++ and Java for many years. Outside work, he enjoys hiking, squash, and skiing.
|