Contexts and Dependency Injection With Maven and Tomcat 7

Introduction

As I worked my way through the Contexts and Dependency Injection (CDI) part of the Java EE 6 tutorial I wanted to learn how to use CDI with Tomcat 7 and Maven. The examples that come with the Java EE 6 tutorial provided by Oracle are NetBeans projects and use the GlassFish 3 server (which has built in support for CDI). Since my development environment is Maven and Tomcat, I wanted to translate the CDI examples in the Java EE 6 tutorial to my environment. Just like with my work on converting the JSF 2 example to Maven and Tomcat, converting the CDI example meant a ride on the JSF 2 - Tomcat 7 pain train.

Contexts and Dependency Injection (CDI)

CDI, JSF 2, and Servlet 3.0 were the three biggest updates to Java EE 6 that I wanted to explore and learn how to use in my own Java web application development. JSF 2 has a form of dependency injection through its ManagedBean configuration. However, CDI is more powerful and can be used as a replacement for JSF's dependency injection. TheServerSide.com has a good article explaining the difference between CDI and JSF 2's dependency injection.

Unlike GlassFish 3, Tomcat 7 doesn't have built-in support for CDI. However, you can use CDI with Tomcat 7 by including an implementation of the CDI specification in your application's classpath. For this example, I used Weld, which is the CDI reference implementation (see: http://seamframework.org/Weld).

Example Application

I used the Simple Greeting example from the Running the Basic Contexts and Dependency Injection Examples section of the Java EE 6 tutorial. The example application is copyrighted by Oracle with a license that allows redistribution (see http://developer.sun.com/berkeley_license.html). You can download a zipped archive of the Maven project here (created using Eclipse 3.6).

After downloading the example application, you can import it into Eclipse. If you don't use Eclipse, you can unzip the download and import the Maven project into any Maven aware Java IDE.

To build the application open a terminal (command) window and navigate to the project's root folder. Then at the command line run mvn -e clean package. To run the application copy the simplegreeting.war file from the target folder to Tomcat 7's webapps folder. Startup Tomcat and then navigate to http://localhost:8080/simplegreeting to view the application. If there are problems with the application view the console.out and localhost log files in Tomcat's log's folder. NOTE: you may need to copy jstl.jar from Tomcat 7's examples/WEB-INF/lib folder to Tomcat 7's lib folder so that it is on the classpath. The simplegreeting application needs the jstl.jar.

CDI, Tomcat 7 and Maven

Tomcat 7 does not provide out-of-the-box support for CDI. So in the example application's pom.xml are these nodes:



<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url>http://repository.jboss.org/nexus/content/groups/public</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
    
...

<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>1.1.0.Final</version>
</dependency>

The above nodes in the pom.xml tell Maven to use the JBoss repository to look for the weld-servlet artifact. The weld-servlet artifact provides a reference implementation of CDI that we can use with Tomcat 7.

In addition to having the weld-servlet artifact on the application's class path I had to add a listener node to the web.xml:



<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>

Of course since the simplegreeting application is using JSF 2, the pom.xml includes those dependencies.

After using Maven to package up simplegreeting application into a war and copying that war file to Tomcat's webapps folder, I started up Tomcat. I'd foolishly hoped that everything would work right out of the gate, but of course that would not happen.

After going to http://localhost:8080/simplegreeting all I got in the browser was:

Simple Greeting Simple Greeting

It looked like the JSF tags in the index.xhtml page were not being processed.

I double checked that I copied everything from the original example simplegreeting project into the correct places in my Maven project. After some research on the web and trial and error, I learned that I had to have a faces-config.xml file in my WEB-INF folder. The original example project, designed to run with GlassFish 3, did not have this file. So I added a faces-config.xml with this content to WEB-INF.



<?xml version="1.0"?>
<faces-config 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/web-facesconfig_2_0.xsd"

version="2.0">

</faces-config>

The file doesn't provide any additional configuration for the application but for some reason running the simplegreeting project in Tomcat 7 requires a faces-config.xml file. I had previously thought faces-config.xml was optional in JSF 2 unless you needed to specify a configuration in your JSF 2 application that could not be done with annotations.

Anyway after adding the faces-config.xml file to WEB-INF, repackaging the war file, and copying it to Tomcat's webapps, the application deployed and ran fine.

Summary

If you want to use the CDI examples from the Java EE 6 tutorial that Oracle has published online, but prefer to use Tomcat and Maven then this article and the example application may be helpful.

References

  1. The Java EE 6 Tutorial, http://download.oracle.com/javaee/6/tutorial/doc/giwhb.html
  2. Weld Home, http://seamframework.org/Weld
  3. Oracle Mojarra JavaServer Faces, http://javaserverfaces.java.net/
  4. Working with CDI and JSF 2.0 on Tomcat 7: Configuring Weld, TheServerSide.com
  5. Apache Tomcat, http://tomcat.apache.org/

Related Blog Entries

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Thinks you for these informations (Je parle français so sorry for my english).
When I try this example, with tomcat 7 maven 2.2.1 eclipse helios, I have a exception thrown:
(but in my browser every run well: Hi, Jo Douk!)
What does ilt mean?
GRAVE: Servlet.service() for servlet [Faces Servlet] in context with path [/simplegreeting] threw exception [javax/servlet/jsp/jstl/core/Config] with root cause
java.lang.ClassNotFoundException: javax.servlet.jsp.jstl.core.Config
   at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1643)
   at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1488)
   at com.sun.faces.application.view.JspViewHandlingStrategy.executePageToBuildView(JspViewHandlingStrategy.java:344)
   at com.sun.faces.application.view.JspViewHandlingStrategy.buildView(JspViewHandlingStrategy.java:154)
   at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:100)
   at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
   at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
   at javax.faces.webapp.FacesServlet.service(FacesServlet.java:313)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
...
# Posted By JoDouk | 3/31/11 9:39 AM
JoDouk - Did you follow this NOTE from the above article:

NOTE: you may need to copy jstl.jar from Tomcat 7's examples/WEB-INF/lib folder to Tomcat 7's lib folder so that it is on the classpath. The simplegreeting application needs the jstl.jar.
# Posted By Bruce | 3/31/11 10:19 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1.002. Contact Blog Owner