Chapter 26. CDI Portlet Development

Red Hat JBoss Portal supports portlet development using Contexts and Dependency Injection (CDI) as specified by JSR 299. You can perform CDI injection directly into GenericPortlet instances and Portlet Filters. There are two new CDI scopes to specifically support the portlet lifecycle.

26.1. GenericPortlet and Portlet Filter Injection

To activate CDI in portlet applications, the WEB-INF/beans.xml file must be present inside the WAR, as defined by the JSR 299 specification. There is no additional configuration required to use CDI within a portlet or portlet filter.
Even if a portlet class is not managed by the CDI container, it can have CDI beans injected into it. These classes include any portlet class extending GenericPortlet or implementing the Portlet interface. Additionally, filters including PortletFilter , RenderFilter , ActionFilter , EventFilter, or ResourceFilter can use CDI injection. As with any kind of injection, use @Inject and specify the type of the bean to inject.
The point at which the injection is performed on the portlet class or filter, some contexts such as session will not be active. This will cause ContextNotActiveException to appear. Such a situation could arise if the injected bean is produced by a bean that is in session scope.

Note

The examples for CDI Generic Portlet are available in the Quickstarts Collection. See Section C.1, “Quickstarts”. The quickstarts show a basic portlet, and portlet filter using CDI.
The CDI Portlet with JSF quickstart shows how to use CDI in combination with JSF.

26.2. Portlet CDI Scopes

Note

The example titled Portlet Using CDI Scopes project is available in the Quickstarts Collection, see Section C.1, “Quickstarts”. The quickstart demonstrates the usage of CDI Scopes @PortletLifecycleScoped and @PortletRedisplayScoped .
To support the complex Portlet Lifecycle within CDI, @PortletLifecycleScoped and @PortletRedisplayScoped are available for use with either JSF portlets or portlets extending GenericPortlet . These scopes are present within the portal artifact, and are available to your portlet project by adding the Maven dependency described in the example API Maven Dependency.

Example 26.1. API Maven Dependency

There is no <version> necessary in <dependency> if the Bill of Materials (BOM) is imported as described in Section 22.1, “Starting a Portlet Project”.
<dependency>
    <groupId>org.gatein.api</groupId>
    <artifactId>gatein-api</artifactId>
    <scope>provided</scope>
</dependency>

26.2.1. @PortletLifecycleScoped

A bean annotated with @PortletLifecycleScoped is active for the full Portlet Lifecycle, from Action to Render.
If you set a value from within an ActionRequest or EventRequest, then retrieve that value from the bean within a RenderRequest, the value that was previously set is returned.
However, any further RenderRequest events that occur after the initial Portlet Lifecycle has completed will not contain any values that may have been set as part of an ActionRequest or EventRequest.
The @PortletLifecycleScoped is best suited to situations where it does not matter if the value is only present for the first render, such as wanting to display a message on the portlet to the user as a result of some action that was performed.

Note

A ResourceRequest is considered separate from the regular Portlet Lifecycle, therefore any changes to a CDI bean within a ResourceRequest will not be reflected in the instance of the bean used during an ActionRequest , EventRequest or RenderRequest, just as any changes to bean state within these requests will not be reflected in the instance that a ResourceRequest sees.

26.2.2. @PortletRedisplayScoped

A bean annotated with @PortletRedisplayScoped is active until a subsequent Portlet Lifecycle triggered by an ActionRequest or EventRequest is initiated.
This takes @PortletLifecycleScoped a step further by supporting the use case of needing to display the same data each time the portlet is refreshed without any new actions or events being triggered.
It does not matter how many RenderRequest are made, the data will be retained for redisplay until a new ActionRequest or EventRequest is triggered, causing the beans to be re-initialized to their default state.

Important

Because the @PortletRedisplayScoped bean is passivation capable, it must implement Serializable .
A ResourceRequest has any @PortletRedisplayScoped annotated bean initialized to its default state, however any bean that has its methods called will overwrite any existing instances of that bean upon completion of the ResourceRequest . This enables a subsequent RenderRequest to reflect the values that were set as part of a ResourceRequest. The typical use case for this scenario is Ajax calls from the browser.

Important

As @PortletRedisplayScoped beans have a CDI client proxy injected into the beans instead of the actual instance, it's important to remember that calling a get method on a bean during a ResourceRequest will result in its initialized state overwriting whatever is present in the instance that will be used for a RenderRequest .
Therefore it is recommended to only call beans methods during RenderRequest to avoid unexpected data changes on a portlet refresh.