With the release of GateIn 3.6.0.Final we introduced some new CDI scopes to ease its use within a portlet. This second blog on CDI scopes for GateIn, will cover @PortletRedisplayScoped. This scope can be used with GenericPortlets, Portlet Filters, or JSF Portlets.
This scope is retained beyond a single Portlet Request lifecycle to be retrieved for all subsequent Render Requests that don't involve an Action or Event. The Beans in this scope are destroyed subsequent Action or Event requests, enabling continual refreshing of the portlet by a user to repeatedly display the same exact content as the Bean data will not be re generated for each Render. The following table illustrates when the context for the scope is activated (A), destroyed (X), or when its already present (P):
Portlet Trigger | Action Start | Action Complete | Event Start | Event Complete | Render Start | Render Complete | Resource Start | Resource Complete |
---|---|---|---|---|---|---|---|---|
Portlet Action | X then A | P | P | P | P | P | ||
Portlet Event | X then A | P | P | P | ||||
Portlet Render | A (if not present) | P | ||||||
Portlet Resource | A | X |
An important distinction is that any Beans created within the scope context as part of a Portlet Action, Portlet Event or Portlet Render are not visible within a Portlet Resource call, and vice versa. Each ResourceRequest will receive a completely empty set of Beans that have been constructed, including calls to any @PostConstruct, but that have had no code executed against them.
There is one difference with how Resource Request Beans are handled as compared to @PortletLifecycleScoped, in that any Beans that are used during a Resource Request will be merged into the context of the main portlet lifecycle. What this means is that the values on a @PortletRedisplayScoped bean that was used during a Resource Request will replace the contents of the same Bean type for the next Render Request that is executed. In most cases that wouldn't be a problem, but it's a potential gotcha if you make lots of Ajax calls and suddenly wonder why the values in your Beans are all wrong the next time you Render the portlet.
To begin using the new scope, simply add the following dependency into your portlet project pom.xml:
<dependency> <groupId>org.gatein.api</groupId> <artifactId>gatein-api</artifactId> <version>1.0.0.Final</version> <scope>provided</scope> </dependency>
We mark the dependency as provided since GateIn will automatically link our deployment to the latest API dependency at runtime.
With the above dependency we can then create a bean such as:
@PortletRedisplayScoped public class LifecycleBean implements java.io.Serializable { ... }
Note that we implement Serializable for our Bean, as the context is stored within the User Session, which can potentially be passivated by the container.
As far as CDI is concerned, @PortletRedisplayScoped is a bean scope like all those that it provides. This enables us to inject @RequestScoped, @ConversationScoped, @SessionScoped or @ApplicationScoped beans into a @PortletRedisplayScoped bean, or vice versa.
Hope this and the scope we covered in the previous blog will make developing CDI portlets with GateIn that much easier!