Portlet API version 3.0 Overview

This section presents some of the main new features introduced by JSR 362. JSR 362 Portlet Specification 3.0 introduces many improvements to the portlet programming model. It adds configuration through annotation, asynchronous support similar to the servlet asynchronous support, multipart form support, support for CDI beans, method annotation support allowing portlet methods to reside in different classes, and a JavaScript API that allows portal pages to function as single-page applications. The Pluto 3.0 portlet container implements all JSR 362 features and passes the TCK. While doing so, Pluto 3.0 remains fully compliant to the 2.0 Portlet Specification, meaning that version 2.0 portlets can run on the version 3.0 portlet container.

Additional Resources:

Configuration by Annotation

The version 3.0 portlet API introduces the @PortletApplication and @PortletConfiguration annotations to allow portlets to be configured without using the deployment descriptor. Note that the deployment descriptor can still be used. When both configuration annotations and a portlet deployment descriptor are present, values from the deployment descriptor override those provided by annotation.

@PortletApplication(
      defaultNamespaceURI="https://www.java.net/",
      events = {
          @EventDefinition(qname=@PortletQName(namespaceURI="http://www.apache.org/",
                           localPart="event1") ,   payloadType = String.class),
          @EventDefinition(qname=@PortletQName(namespaceURI="", 
                           localPart="event4"))
      }
)


@PortletConfiguration(portletName="Portlet1", 
   initParams = {
      @InitParameter(name="color", value="#cafeba"),
   },
   title={
      @LocaleString(locale = "EN", value="Annotated Portlet"),
   }
)
      

Extended Method Annotations

Version 3 extends the idea of method annotations introduced with version 2. Portlet methods may now be located in classes that do not implement portlet interfaces. Also, lifecycle methods belonging to a single portlet need not be in the same class.

The extended method annotations @HeaderMethod, @RenderMethod, and @ServeResourceMethod have relaxed method signature requirements as compared to the methods defined by the portlet interfaces. See the portlet API documentation for details.

Use of the extended method annotation @RenderMethod implicitly configures a portlet. No additional configuration is required. The following example defines a simple portlet render method. If this method were located in a class with a default constructor within a web application deployed on a version 3 portal, it would define and automatically configure a portlet by the name of "BeanPortletDemo".

@RenderMethod(portletNames = "BeanPortletDemo")
public String simpleRender() {
   return "Hello, World!";
}
      

CDI Support

Version 3 provides support for CDI in several ways. Portlet classes are instantiated through the CDI container to enable dependency injection while respecting scope annotations on the portlet classes. Dependency injection supported in portlet filters and listeners as well as in asynchronous threads started through the PortletAsyncContext object. Many portlet artifacts have been made injectable - the request and response objects, parameter objects, the portlet configuration object, etc.

Custom CDI scopes for portlets have also been introduced.

  • The portlet session scope - @PortletSessionScoped
  • The portlet request scope - @PortletRequestScoped
  • The render state scope - @RenderStateScoped

Asynchronous support

The portlet programming model provides asynchronous support similar to that provided by servlets. Using asynchronous support, long-running requests can run in separate thread in order to free up application server resources. Asynchronous support is provided for resource requests only.

Asynchronous processing must be started within original resource request. The asynchronous thread runs in context of original resource request, providing that it is started through the PortletAsyncContext#start(Runnable) method. This means that CDI injection can be used within async thread in the same manner as for the original request. The asynchronous listener and any portlet filters also run in context of original request.

The asynchronous thread can dispatch directly to JSP or servlet for producing output and can also dispatch back to the resource method, if desired.

The following diagram illustrates a sample asynchronous processing sequence. Note that this shows only one of many possible scenarios. When the portal receives a resource request targeted to the asnychronous portlet, the portlet container invokes the portlet resource method. The portlet starts asynchronous processing, adds an asynchronous listener, uses the portlet asynchronous context object to start a thread, and returns to the container. The asynchronous thread does its long-running work and dispatches back to the original resource method. The resource method then includes a JSP to produce output and completes asynchronous processing.

The Portlet Hub JavaScript API

The portlet specification defines a JavaScript API that can be used by portlet code running on the browser to read and set render parameters, carry out portlet actions, and generate resource URLs while remaining in an Ajax paradigm. Updating parameters and executing actions through the portlet hub does not cause a page refresh. Instead, the portlet hub communicates with the portal, causing the portal to carry out any required portlet processing. The portlet hub then informs the portlet client code running on the browser about any new parameters. The portlet client can then create a resource URL to obtain any data or markup required to update the page. The portal implementation is responsible for making the portlet hub module available on the portal page.

The following diagram illustrates portlet action processing initiated through the portlet hub. In this scenario, the portal page contains three portlets that make use of the portlet hub. Portlet B initiates an Ajax action through the portlet hub. The portlet hub transmits the action request along with any form data and action parameters to the portal server. On the server, action processing is executed for portlet B. During action processing, portlet B fires an event that portlet A can process. The server executes the event phase for the event and transmits the new render state information to the portlet hub running on the browser. The portlet hub fires onStateChange events to portlets A and B to inform them of the updated render state information. The portlets can now use the portlet hub API to create resource URLs in order to retrieve information corresponding to the new render state.

The main JavaScript functions provided by the portlet hub are listed below.

Promise(PortletInit) register(<Portlet ID>)
Registers a portlet client designated by portlet ID with the Portlet Hub and returns object that provides access to remaining Portlet Hub functions.
ListenerID addEventListener(<listener type>, <listener method>)
The Portlet Hub informs Portlet Client of state changes by calling the event listener function and passing the updated portlet state.
Promise(url) createResourceUrl(<resource parameters>, <cacheability>, <resource ID>)
Creates a resource URL containing the current page / portlet state. The URL can be used with the framework of choice to retrieve the resource.
setPortletState(<new portlet state>)
Allows portlet client to set private and public parameters, portlet mode, window state
action(<action parameters>, <form element>)
Carries out a portlet action in Ajax mode (Ajax action)