In December 2009, JSR 299 introduced the
Contexts and Dependency Injection (CDI) 1.0 standard into the Java EE 6
platform. In April 2013, JSR 346 updated
CDI to version 1.1 for Java EE 7. In addition, JSR 344,
the JSF 2.2 specification which is
another component of Java EE 7, introduced a dependency on the CDI API for the
javax.faces.view.ViewScoped
annotation and for the Faces Flows feature. JBoss
Weld is the Reference Implementation (RI) for
CDI, and Apache OpenWebBeans is another open
source implementation.
Still wondering what CDI accomplishes? Visit the CDI Specs to learn more about CDI and why it has become a popular component for JSF.
This tutorial covers the following topics:
- Configuring JSF Portlets to Use CDI
- Configuring the Liferay CDI Portlet Bridge
- Understanding CDI in JSF Annotations
First, you’ll configure your portlets to use a CDI implementation, such as JBoss Weld or CanDI.
Configuring JSF Portlets to Use CDI
Several app-server/portal/CDI-implementation combinations support using CDI with JSF on Liferay Portal.
For Liferay Portal 6.2, you can use one of these combinations:
- GlassFish 3 with Weld
- JBoss AS with Weld
- Resin with CanDI
- Tomcat with Weld
- WebLogic 12c with Weld
For Liferay Portal 6.1, you can use one of these combinations:
When developing portlets with CDI 1.0, you must include a WEB-INF/beans.xml
descriptor in your JSF portlet plugin’s .war
deployment, so that when the CDI
implementation scans the classpath it detects the CDI-related annotations of
your classes.
Here’s an example WEB-INF/beans.xml
descriptor for a portlet plugin:
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
If you’re deploying your portlet on JBoss AS 7, you must also include a
WEB-INF/jboss-deployment-structure.xml
descriptor in your portlet plugin’s
.war
deployment to include the CDI-related modules. Here’s an example of a
portlet’s WEB-INF/jboss-deployment-structure.xml
descriptor for JBoss:
<?xml version="1.0"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<exclusions>
<module name="javaee.api" />
<module name="org.apache.log4j" />
</exclusions>
<dependencies>
<module name="com.liferay.portal" />
<module name="javax.annotation.api" />
<module name="javax.enterprise.api" />
<module name="javax.inject.api" />
<module name="javax.interceptor.api" />
<module name="javax.validation.api" />
<module name="javax.mail.api" />
<module name="org.jboss.modules" />
</dependencies>
</deployment>
</jboss-deployment-structure>
For a portlet to use Weld on most app servers (excluding Resin), the portlet’s
WEB-INF/web.xml
descriptor must include the following filter and filter
mapping:
<filter>
<filter-name>WeldCrossContextFilter</filter-name>
<filter-class>org.jboss.weld.servlet.WeldCrossContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>WeldCrossContextFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
Portlets on Resin can use the CanDI implementation of CDI, which Resin includes by default.
If you’re running on Tomcat and you choose not to include Weld in Tomcat’s global
classpath, then you must include it in the portlet’s classpath by adding it to
the portlet’s WEB-INF/lib
folder.
If you’re on Tomcat and you’re using a Maven project for your portlet plugin, you must specify the Weld servlet as a dependency. Here’s an excerpt from a Maven POM file that exemplifies specifying the Weld servlet dependency:
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>1.1.10.Final</version>
</dependency>
If you’re on Tomcat you must also add a Weld servlet listener in your portlet’s
WEB-INF/web.xml
file:
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
Next, you’ll learn how to configure the Liferay CDI Portlet Bridge
Configuring the Liferay CDI Portlet Bridge
The Liferay CDI Portlet Bridge makes it possible to use CDI with your JSF portlets on Liferay. Your JSF portlet projects must include the Liferay CDI Portlet Bridge as a dependency.
For example, to specify the bridge dependency in a Maven project for Liferay
6.2, add to your POM’s dependencies
element a dependency like the following
one:
<dependency>
<groupId>com.liferay.cdi</groupId>
<artifactId>cdi-portlet-bridge-shared</artifactId>
<version>6.2.0.2</version>
</dependency>
The WEB-INF/portlet.xml
descriptor of the portlet must include the following
markup:
<filter>
<filter-name>CDIPortletFilter</filter-name>
<filter-class>com.liferay.cdi.portlet.bridge.CDIPortletFilter</filter-class>
<lifecycle>ACTION_PHASE</lifecycle>
<lifecycle>EVENT_PHASE</lifecycle>
<lifecycle>RENDER_PHASE</lifecycle>
<lifecycle>RESOURCE_PHASE</lifecycle>
</filter>
<filter-mapping>
<filter-name>CDIPortletFilter</filter-name>
<portlet-name>my-portlet-name</portlet-name>
</filter-mapping>
Additionally, the portlet’s WEB-INF/web.xml
descriptor must include the
following declarations:
<filter>
<filter-name>CDICrossContextFilter</filter-name>
<filter-class>com.liferay.cdi.portlet.bridge.CDICrossContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CDICrossContextFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<listener>
<listener-class>com.liferay.cdi.portlet.bridge.CDIContextListener</listener-class>
</listener>
You’ve completed configuring the Liferay CDI Portlet Bridge for you JSF portlet. Now that everything is configured, you are ready to begin development with CDI.
Understanding CDI in JSF Annotations
When developing portlets with CDI, you can annotate Java classes as CDI managed
beans using
@Named
with the
following scopes:
CDI Annotation | Description |
---|---|
@ApplicationScoped | An @ApplicationScoped managed bean exists for the entire lifetime of the portlet application. |
@ConversationScoped | A @ConversationScoped managed bean is created when Conversation.begin() is called and is scheduled for garbage collection when Conversation.end() is called. |
@FlowScoped | A @FlowScoped managed bean is created when a JSF 2.2 Flow begins and scheduled for garbage collection when a JSF 2.2 Flow completes. |
@RequestScoped | A @RequestScoped managed bean exists during an ActionRequest , RenderRequest , or ResourceRequest . Beans that are created during the ActionRequest do not survive into the RenderRequest . |
@SessionScoped | A @SessionScoped managed bean exists for the duration of the user session. |
In addition to CDI scope annotations, it’s important to understand JSF 2 annotations and their equivalence to CDI annotations.
JSF Annotation | Equivalent CDI Annotation |
---|---|
javax.faces.ManagedBean | javax.inject.Named |
javax.faces.ApplicationScoped | javax.enterprise.context.ApplicationScoped |
This should help with your understanding of CDI and JSF annotations. And as you’ve also seen in this tutorial, configuring CDI for your JSF portlets and configuring the Liferay CDI Portlet Bridge is a snap!
Related Topics
Understanding Liferay Faces Bridge
Communicating Between JSF Portlets Using IPC