« Back to Liferay Faces

Developing JSF Portlets with CDI

Overview of CDI #

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 (JSF 2.2 – another component of Java EE 7) introduced a dependency on the CDI API for the javax.faces.view.ViewScoped annotation and also for the Faces Flows feature. JBoss Weld is the Reference Implementation (RI) for CDI and Apache OpenWebBeans is another open source implementation.

Compatible Portal Servers #

In order to utilize Weld in Liferay portlets, one of the following servers must be used:

Liferay Portal EE Patches #

Liferay Portal 6.1.20 EE GA2 #

Customers using Liferay Portal 6.1.20 EE GA2 typically have the following patch installed:

  • liferay-fix-pack-plugin-deployment-1-6120.zip

However simply applying this patch with the patching-tool is not enough. There are also a collection of properties that must be added to $LIFERAY_HOME/portal-ext.properties in order for the patch to work correctly. See the description page for "Update 2012-09-18 Plugin Deployment-1" in the Customer Portal for more information.

Additionally, if you need to modify WEB-INF/context.xml in your portlet, then you will need to request a hotfix for LPS-29750.

CDI Configuration #

When developing portlets with CDI 1.0, it is necessary to include WEB-INF/beans.xml in the WAR deployment so that the CDI implementation will scan the classpath for classes annotated with CDI related annotations. In addition, for JBoss AS 7, it is necessary to include WEB-INF/jboss-deployment-structure.xml in the WAR deployment.

Sample WEB-INF/beans.xml #

<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>

Sample WEB-INF/jboss-deployment-structure.xml #

<?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>

Weld Configuration #

If using Resin, then it is not necessary to configure JBoss Weld since Resin includes the CanDI implementation of CDI by default. For all other servers, it is necessary to configure the JBoss Weld implementation of CDI.

Weld Configuration for All Servers (except Resin) #

The WEB-INF/web.xml descriptor of the portlet must include the following markup:

<!-- Required for all servers except Resin -->
<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>

Additional Weld Configuration for Tomcat #

If running in a Java EE application server like Oracle GlassFish or JBoss AS, then Weld is automatically included in the global classpath. But on Tomcat, it is necessary to include the weld-servlet.jar dependency in either the tomcat/lib global classpath, or directly in the WEB-INF/lib folder of a portlet:

<!-- Required only for Tomcat -->
<dependency>
    <groupId>org.jboss.weld.servlet</groupId>
    <artifactId>weld-servlet</artifactId>
    <version>1.1.10.Final</version>
</dependency>

Additionally, the following listener must be added to the WEB-INF/web.xml descriptor:

<!-- Required only for Tomcat -->
<listener>
    <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener> 

Liferay CDI Portlet Bridge Configuration #

In order to utilize CDI in a portlet with Liferay, it is necessary to include the Liferay CDI Portlet Bridge as a dependency:

<dependency>
    <groupId>com.liferay.cdi</groupId>
    <artifactId>cdi-portlet-bridge-shared</artifactId>
    <version>6.2.0.1</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>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 WEB-INF/web.xml descriptor of the portlet must include the following markup:

<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>

CDI Scopes #

When developing portlets with CDI, it is possible to annoatate Java classes as CDI managed beans with @Named with the following scopes:

AnnotationDescription
@ApplicationScopedManaged bean exists for the entire lifetime of the portlet application.
@ConversationScopedManaged bean exists when Conversation.begin() is called and is scheduled for garbage collection when Conversation.end() is called.
@RequestScopedManaged bean exists during an ActionRequest, RenderRequest, or ResourceRequest. Beans that are created during the ActionRequest do not survive into the RenderRequest.
@SessionScopedManaged bean exists for the duration of the user session.

JSF CDI Portlet Development #

The Liferay Faces Project features the jsf2-cdi-portlet demo (which is a variant of the jsf2-portlet demo). It is recommended that you download and deploy the jsf2-cdi-portlet demo in your development environment in order to verify that CDI will function properly.

The following table illustrates JSF 2 annotation usage and the equivalent CDI annotations.

JSF AnnotationEquivalent CDI Annotation
javax.faces.ManagedBeanjavax.inject.Named
javax.faces.ApplicationScopedjavax.enterprise.context.ApplicationScoped
javax.faces.RequestScopedNo such equivalent, since javax.enterprise.context.RequestScoped does not span portlet lifecycle phases.
javax.faces.SessionScopedjavax.enterprise.context.SessionScoped
javax.faces.ManagedProperty(pluscorrespondingsettermethod)javax.inject.Inject (corresponding setter method not required)
0 Attachments
18792 Views
Average (2 Votes)
The average rating is 3.0 stars out of 5.
Comments
Threaded Replies Author Date
Is LPS-35558 still relevant for Liferay EE 6.1.30? Guillaume Malartre January 22, 2014 8:30 AM

Is LPS-35558 still relevant for Liferay EE 6.1.30?
Posted on 1/22/14 8:30 AM.