JSF 2.0: The most simple CDI integration use cases
Door: Jan-Kees van Andel, 31 January 2010If you have (just like me) been following the Web Beans and Contexts and Dependency Injection (CDI) work, you might be thinking (also just like I did): “That CDI is heavily over-engineered”. My “moment of clarity” was a year ago, at DeVoxx 2008.
It was a talk by Pete Muir of JBoss. He was showing a really simple use case and tried to implement it using CDI. The talk was really technology driven and I hated it. Why? Because it wasn’t an improvement compared with the existing technologies. He wrote an application, containing several interfaces, classes (this is not bad) and custom annotations. If the goal was to show some kind of geniosity, it was a good talk. But if the goal was to show how this new technology would make our lives better… then sorry, he failed miserably.
More than a year further, there have been a lot of movements on the CDI front. And, as an Apache MyFaces developer, I’m of course very interested how to use CDI in a JSF 2.0 application. And as an Apache fanboy, I of course prefer Apache software, in this case MyFaces with OpenWebBeans and OpenJPA.
Configuration
Since OpenWebBeans is still under development, you need to do some additional steps to get it to work.
The following POM should get you up and running quickly in Tomcat:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.myfaces</groupId>
<artifactId>myfaces-example-ebanking</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- Compile dependencies -->
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>${myfaces-version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-impl</artifactId>
<version>${myfaces-version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-all</artifactId>
<version>${openjpa-version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-digester</groupId>
<artifactId>commons-digester</artifactId>
<version>2.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-impl</artifactId>
<version>${openwebbeans.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-jsf</artifactId>
<version>${openwebbeans.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-interceptor_1.1_spec</artifactId>
<version>1.0.0-EA1-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<version>${junit-version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>Apache MyFaces beta</id>
<name>Apache MyFaces beta</name>
<url>http://people.apache.org/~lu4242/myfaces200beta</url>
</repository>
</repositories>
<properties>
<myfaces-version>2.0.0-beta</myfaces-version>
<openwebbeans.version>1.0.0-SNAPSHOT</openwebbeans.version>
<openjpa-version>2.0.0-M3</openjpa-version>
<junit-version>4.7</junit-version>
</properties>
</project>
Note some of the additional dependencies required to run in Tomcat, as opposed to a full blown appserver.
Also, at the moment you need to build OpenWebBeans from source manually. The geronimo-interceptor_1.1_spec dependency will be downloaded to your local Maven repository on a “mvn install”. OpenJPA is not needed for this simple use case, but I use it in my project.
Code
And then, the real code:
public class WebUtils {
private static volatile String basePath;
@Produces @Named public String getBasePath() {
if (basePath == null) {
basePath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
}
return basePath;
}
}
This class contains a so-called Producer Method. As the name suggests, it produces stuff. In this case, it produces a String with Dependent scope. This means the method will be invoked every time the variable is needed. EL expressions or injection are the most common cases for this.
I’m caching the return value, though it’s not necessary, since getting the context path is pretty cheap.
The view could look like this (snippet):
...
<link href="#{basePath}/style/default.css" rel="stylesheet" type="text/css" />
...
Another implementation could put the variable into the Application scope, like this:
public class WebUtils {
@Produces @Named @ApplicationScoped public String getBasePath() {
return FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
}
}
As easy it might seem, the approaches shown above require some responsibility from the programmer though. With producer methods, it becomes really easy to mess things up. After all, you’re effectively creating globals. Tool support may help you here though. For example, the Dependency Analyzer in IntelliJ IDEA 9.0.1 already contains pretty decent support for JSF 2.0 and CDI. And, knowing the reputation of the JetBrains folks, I’m sure they come up with even more fancy stuff.
A more classic implementation
A more classic implementation could look like the following:
@Named
@ApplicationScoped
public class WebBean {
private static volatile String basePath;
public String getBasePath() {
if (basePath == null) {
basePath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
}
return basePath;
}
}
I’m not using producer methods anymore. The WebBean is now a CDI-managed bean.
The client code becomes slightly more verbose, but who cares? I’ll put the client code in a generic template anyway!:
...
<link href="#{webBean.basePath}/style/default.css" rel="stylesheet" type="text/css" />
...
Wrapping up
I haven’t even showed the complete tip of the iceberg. CDI offers several ways to write code and we’ve yet to find out the (anti) patterns.
I would like to point you to the OpenWebBeans documentation for more info, but unfortunately this is still under development. The good news is that JBoss Weld already has extensive documentation.


