• No results found

Developing JSF Portlets with CDI

In document Liferay 6.2 Developer Guide (Page 159-163)

4. Developing JSF Portlets with Liferay Faces

4.1. Developing JSF Portlets

4.1.8. Developing JSF Portlets with CDI

public EventNavigationResult handleEvent(FacesContext facesContext, Event event) {

EventNavigationResult eventNavigationResult = null;

String eventQName = event.getQName().toString();

if

(eventQName.equals("{http://liferay.com/events}ipc.customerEdited")) { ...

}

return eventNavigationResult;

} ....

}

And here's the descriptor for registering the CustomerEditedEventHandler class as a bridge event handler for the Customers portlet. The following <init-param> belongs in the Customers portlet's <portlet> element, in the WEB-INF/portlet.xml descriptor.

<init-param>

<name>javax.portlet.faces.bridgeEventHandler</name>

<value>com.liferay.faces.example.event.CustomerEditedEventHandler</value>

</init-param>

Note: For a complete example demonstrating JSF 2 IPC events, see the JSF2 IPC Events - Customers and JSF2 IPC Events - Bookings demo portlets on GitHub.

Now that we've discussed some common basic JSF portlet development topics, let's consider how to use dependency injection in JSF portlets.

4.1.8. Developing JSF Portlets with 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, 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.

In this section we'll cover the following topics:

Configuring CDI on Liferay Portal

Configuring the Liferay CDI Portlet Bridge

Understanding CDI in JSF Annotations

Let's look at configuring Weld on Liferay Portal for leveraging CDI with JSF portlets.

Liferay 6.2 Developer Guide Page 159

4.1.8.1. Configuring CDI on Liferay Portal

You must use one of the following portal/app-server combinations to use Weld with Liferay Portal:

Liferay Portal 6.1/6.2 (Tomcat)

Liferay Portal 6.1/6.2 (GlassFish)

Apply patch attached to LPS-35558.

Upgrade Mojarra in GlassFish to version 2.1.21 (or higher).

Upgrade Weld in GlassFish to version 1.1.10.Final (or higher).

Liferay Portal 6.1/6.2 (JBoss AS)

Apply patch attached to LPS-35558

Upgrade Mojarra in JBoss AS to version 2.1.21 (or higher).

Upgrade Weld in JBoss AS to version 1.1.10.Final (or higher).

Liferay Portal 6.1/6.2 (Resin)

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 the CDI implementation can detect the CDI-related annotations of your classes when it scans the classpath.

Here's an example WEB-INF/beans.xml descriptor:

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

For 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

WEB-INF/jboss-deployment-structure.xml descriptor for JBoss:

<?xml version="1.0"?>

Next, we'll cover Weld configuration on the app server. Their are some different configuration steps for different app servers. We'll look at the most common configuration steps first.

Liferay 6.2 Developer Guide Page 160 For 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>

If you are using Resin as your app server, you don't need JBoss Weld, as Resin includes the CanDI implementation of CDI by default.

The next section contains information about specifically configuring Tomcat, so developers running other application servers can skip it.

Additional Weld Configuration for Tomcat

If Weld is 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>

Next we'll discuss configuring the Liferay CDI Portlet Bridge.

4.1.8.2. 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, you'd add the following <dependency> to your POM's <dependencies> element:

<dependency>

<groupId>com.liferay.cdi</groupId>

<artifactId>cdi-portlet-bridge-shared</artifactId>

<version>6.2.0.2</version>

Liferay 6.2 Developer Guide Page 161

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

Tip: The Liferay Faces Project features the jsf2-cdi-portlet demo (which is a variant of the jsf2-portlet demo). It's a good idea download and deploy the jsf2-cdi-portlet demo in your development environment in order to verify that CDI functions properly.

Now that everything is configured, you are ready to begin development with CDI.

4.1.8.3. Understanding CDI in JSF Annotations

When developing portlets with CDI, it is possible to annotate Java classes as CDI managed beans with @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

Liferay 6.2 Developer Guide Page 162 CDI Annotation Description

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.ApplicationSc oped

javax.enterprise.context.ApplicationS coped

javax.faces.RequestScoped No such equivalent, since

javax.enterprise.context.RequestScope d does not span portlet lifecycle phases.

javax.faces.SessionScoped javax.enterprise.context.SessionScope d

javax.faces.ManagedProper ty (corresponding setter method required)

javax.inject.Inject (corresponding setter method not required)

Now that we have discussed JSF portlet development with CDI, let's take a look at some UI component tags included with Liferay Faces Bridge.

In document Liferay 6.2 Developer Guide (Page 159-163)