The Java Portlet Specification (originally created through JSR-168) provides a standard for developing portal components with the Java programming language. Although the specification was originally created with the intent of standardizing the API and execution environment of portals and portlets, developers are also leveraging the specification as a standard for developing Web application plugins. By implementing or embedding a portlet container within a Web application, developers allow their Web applications to be extended by third parties through the deployment of compliant portlets.
Apache Pluto, the reference implementation of the Java Portlet Specification, implements a portlet container that can be embedded easily within a portal or Web application. This article provides a comprehensive tutorial that explains how to embed the Pluto Portlet Container (version 1.1) into a Web application. It investigates the basic architecture of Portal Systems, provides an overview of Pluto’s public API, and discusses two different integration techniques.
Portal System Components
The Java Portlet Specification defines three major components of a portal system. The Portal itself provides personalization, single sign on, content aggregation, and other enterprise services. The specification does not specify which services must be implemented by the portal. This decision is left up to the discretion of the portal vendor.
Java Portlets provide content from disparate sources. This content is aggregated into a single presentation by the portal. Portlet developers wanting to create portlets, which are deployable within a compliant portal, implement interfaces defined by the Portlet API and adhere to the lifecycle restrictions defined by the Portlet Specification.
A Portlet Container manages the lifecycle and execution environment of Java Portlets. Portlet containers instantiate, initialize, and invoke portlets in a manner defined by the specification. By embedding a compliant portlet container within a portal or Web application, portlets can be used as an extension point of any Web applications.
The Pluto Portlet Container
The Apache Pluto Project implements an embeddable portlet container and other modules which are used to implement, test, and run it. The container has been implemented to provide a simple, lightweight implementation of the Java Portlet Specification.
The Pluto portlet container is implemented as a lightweight container. The container encapsulates various services used in the processing of requests, and leverages a domain model that represents portlet configuration information. In addition, the container is responsible for providing the execution environment specified by the portlet specification. This environment is provided primarily through the implementation of Portlet API interfaces.
Portlet Container Responsibilities
The container implementation within the Pluto Container fulfills requests through delegation a series of encapsulated components. The container is responsible for the lifecycle of these services, including their initialization, invocation, and destruction.
Each request received by the container includes a small amount of information concerning which portlet should be serviced in its current state. This information, encapsulated within the PortletWindow interface, is provided to the container along with the originating servlet request and response. It is the responsibility of the container to interpret this configuration information into an invocation plan and an environment in which it can be fulfilled.
Internal Container Components
To provide a clear separation of concerns, each of the functions required of the portlet container is serviced by an individual component. These components, integrated either directly or indirectly by the container, fulfill the requests requested of the portlet container.
- Portlet Invoker
The portlet invoker is responsible for dispatching portlet requests to the managed portlet instances. The portlet invoker utilizes the configuration information interpreted and provided by the container to determine which portlet is to be invoked. The invoker is responsible for invoking the proper service method of the portlet.
The portlet context manager is responsibile for ensuring that only one instance of the PortletContext interface exists for each PortletApplication serviced by the container. Internal container services needing to retrieve a Portlet Context request it from the manager. The manager determines whether or not an existing context can be utilized and creates it if necessary.
- PorltetDescriptorRegistry and Descriptor Services
The descriptor service is used to read Web application and portlet application deployment descriptors. The service reads descriptors from their appropriate locations and converts them into a simple domain model that provides configuration information to the container.
The Portlet Container encapsulates the descriptor service within a registry to ensure that the reading of the descriptors is optimized and only performed when necessary. The descriptor registry is responsible for caching the descriptor information.
Note: Because the reading and writing of deployment descriptors is a common requirement of portal systems, containers, and utilities, the descriptor service and implementation utilized by Apache Pluto is implemented as a separate module that is a dependency of the container and can be leveraged outside of the container.
Pluto’s Implementaion Descisions
A few key implementation decisions enable Apache Pluto to be easily embedded and deployed within any compliant servlet container. These decisions are critical to understanding the container, and may effect design decisions of the embedding Web application (or portal).
- Service Interfaces
All critical services within the Portlet Container are defined as interfaces. This allows embedding applications to provide their own implementations of the services, while also allowing Pluto to provide default implementations for many of the services.
An implementation of the org.apache.pluto.PortletContainerServices interface must be provided during the creation of a container instance. This interface defines the services that must be implemented by the embedding container. Additionally, the org.apache.pluto.OptionalPortletContainerServices interface defines services that may be provided by the embedding application. Each individual services is detailed below.
- Instance Container
The mechanism for interacting with a portlet container is the org.apache.pluto.PortletContainer interface. This interface defines methods for managing the container’s lifecycle and for invoking portlets.
Instances of the PortletContainer interface are created through the org.apache.pluto.PortletContainerFactory. The factory is used to create instances so that application integrators are shielded from implementation decisions and changes to Pluto’s implementation.
The decision to utilize an instance container versus a static invocation façade allows Pluto to support the creation of multiple containers within a single JVM while maintaining simplicity. The alternate approach (implemented in previous versions of Pluto) proved to add significant complextity to Pluto’s API by requiring tracking of services and configuration information through ThreadLocal variables and multiple lookup mechanisms.
- Cross Context Dispatching
Pluto utilizes cross-context dispatching, as defined by the servlet specification as the mechanism for invoking portlets. Pluto dispatches portlet requests through an intermediate servlet that configures portlets and invokes them as necessary.
By leveraging this mechanism, Pluto is able to leverage the servlet container’s implementation to manage the execution environment required by the servlet specification—a level of compatibility that is required by the portlet specification.
As a result of this decision, portlet applications are deployed as traditional Web applications through the servlet containers deployment mechanism—and in a seperate Web application context. The portlet container then is configured to provide dispatch requests to the appropriate context as required. Although this result may be confusing to one unfamiliar with the inner workings of the container, it is easily understood once one understands the implementation decision and thinks of a portlet as a view into an application.
One downside of this configuration is the requirement that portlet container libraries that are utilized within both the embedding application and portlet applications must be loaded within a common classpath which is shared by both Web applications.
There are two approaches that can be taken to embed Pluto within an application. The first approach, directly embedding Pluto, provides the most flexibility, but also requires the embedding application to implement the PortletContainerServices. The second approach, utilizing the Pluto Portal Driver, allows users to take advantage of existing service implementations.
Directly Embedding Pluto
To directly embed Pluto, the embedding application must provide an implementation of the PortletContainerService, manage the Container Lifecycle, and properly invoke the container.
Providing a PortletContainerService Implementation
Implementing the PortletContainerService involved implementing an instance of javax.portlet.PortalContext, and org.apache.pluto.service.PortalCallbackService. Implementing the PortalContext is rather straightforward. It simply requires the implementation of several methods used to retrieve general environment information such as custom portal properties and supported portlet modes and window states. The PortalCallbackService provides a mechanism for the portlet container to interact with the Portal. The container utilizes this service to set a portlet title, manipulate portal and request properties, and generate URLs that can be translated by the embedding application.
Managing the Container Lifecycle
Managing the container lifecycle is as simple as instantiating the container, initializing the container, holding an instance of the container for later invocation, and destroying the container upon application shutdown. The initialization of the container is exemplified in the following code:
// // Step 1) Create an instance of the PortletContainerService // PortletContainerServices impl = . . . // // Step 2) Request a new container from the container factory // PortletContainerFactory factory = PortletContainerFactory.getInstance(); PortletContainer container = factory.createContainer( "My Container Name", impl ); // // Step 3) Initialize the Container with the embedding // application's ServletContext // container.init(ctx);
Shutting down the container involves simply invoking the container’s destroy() method during shutdown.
Invoking the Container
For the container to service a request, the embedding application must invoke its service methods by providing a PortletWindow implementation and the current servlet request and response. The PortletWindow defines the servlet context and portlet name of the portlet being requested. The following table details the available service methods and their functions.
|doLoad||Results in the specified portlet being loaded by the container. This call is not required and results in no content being written to the response.|
|doAction||Results in a portlet’s invocation through a call to processAction. The result of this invocation is a redirect to a render request.|
|doRender||Results in a portlet’s invocation through a call to render. The result of this invocation is markup written to the servlet response.|
Embedding Pluto with the Pluto Portal Driver
The Pluto Portal Driver implements the PortletContainerServices and several utilities that can be useful in embedding the Pluto container. Embedders not requiring custom implementations of complex items, such as the URL generators, may find these implementations sufficient within their applications.
The Pluto Portal Driver provides a set of Tag Libraries that can be utilized to embed portlets directly within JSP pages and a controller servlet that can be utilized to capture action requests and forward them to the container. These implementations can be leveraged to eliminate the majority of work required in embedding the container.
Apache Pluto provides a lightweight container environment for leveraging the Portlet Specification within Web and portal applications. The Pluto container can be embedded within a Web application to support external integration with third parties or within a portal to provide standard portlet application support. Whatever the reason, Apache Pluto can be easily embedded either by direct invocation or utilizing the Pluto Portal Driver.
David DeWolf has been developing Web applications, portals, and portlet applications for six years. He is a member of the Apache Portals Project Management Committee and an active commiter to Apache Pluto, the reference implementation of the Portlet Specification. David currently works at Digital Focus, which provides software development, agile coaching, and IT consulting services to Fortune 1000 and medium-sized businesses. Contact David at [email protected].