CDI injection is not working in Servlets
===

I really need your help. I'm working on this problem for weeks or months now. I apologize for the long post, but I want to explain the problem and my settings as precisely as possible.

My JAVA EE 6 web application mainly contains 3 Servlets: a **javax.faces.webapp.FacesServlet**, a StreamingServlet extending **javax.servlet.http.HttpServlet** and a ClientServlet extending **org.eclipse.jetty.websocket.WebSocketServlet**. I want to use CDI with these Servlets but it only works for the FacesServlet, to be more precisely, for the Beans the JSF actions are routed to. CDI injection doesn't work with the other 2 Servlets.

The setup for my project is as follows: Maven 3.0.4, Jetty 8.1.4 (jetty-maven-plugin), MyFaces 2.1.6, Weld 1.1.8.

The file **pom.xml** contains the dependencies for CDI:

	...
	<dependency>
		<groupId>javax.enterprise</groupId>
		<artifactId>cdi-api</artifactId>
		<version>1.1.EDR1.2</version>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>javax.annotation</groupId>
		<artifactId>jsr250-api</artifactId>
		<version>1.0</version>
	</dependency>
	<dependency>
		<groupId>org.jboss.weld.servlet</groupId>
		<artifactId>weld-servlet</artifactId>
		<version>${weld.version}</version>
		<scope>runtime</scope>
	</dependency>
	...

The file **src/main/webapp/WEB-INF/beans.xml** only contains an empty beans element for activating CDI:

	<?xml version="1.0" encoding="UTF-8"?>
	<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>

The file **scr/main/webapp/WEB-INF/jetty-env.xml** contains the Jetty specific configuration for getting the bean manager via JNDI:

	<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">

	<Configure id="webAppCtx" class="org.eclipse.jetty.webapp.WebAppContext">
		<New id="BeanManager" class="org.eclipse.jetty.plus.jndi.Resource">
			<Arg>
				<Ref id="webAppCtx" />
			</Arg>
			<Arg>BeanManager</Arg>
			<Arg>
				<New class="javax.naming.Reference">
					<Arg>javax.enterprise.inject.spi.BeanManager</Arg>
					<Arg>org.jboss.weld.resources.ManagerObjectFactory</Arg>
					<Arg />
				</New>
			</Arg>
		</New>
	</Configure>

The file **src/main/webapp/WEB-INF/web.xml** contains the servlet listener and the BeanManager reference for bootstrapping CDI:

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

	<resource-env-ref>
		<description>Object factory for the CDI Bean Manager</description>
		<resource-env-ref-name>BeanManager</resource-env-ref-name>
		<resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
	</resource-env-ref>
	...

With these settings I always got the following error when running the application using **mvn jetty:run** (first line is most important):

	2012-07-31 11:09:33,546 [main] ERROR org.jboss.weld.environment.jetty.JettyPost72Container - Unable to create JettyWeldInjector. CDI injection will not be available in Servlets, Filters or Listeners
	java.lang.IllegalArgumentException: Cannot load class for org.jboss.weld.environment.jetty.WeldDecorator
		at org.jboss.weld.environment.servlet.util.Reflections.classForName(Reflections.java:58)
		at org.jboss.weld.environment.jetty.JettyPost72Container.initialize(JettyPost72Container.java:66)
		at org.jboss.weld.environment.servlet.Listener.contextInitialized(Listener.java:162)
		at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:764)
		at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:406)
		at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:756)
		at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:242)
		at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1234)
		at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:699)
		at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
		at org.mortbay.jetty.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:256)
		at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
		at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224)
		at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:167)
		at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
		at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224)
		at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
		at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:90)
		at org.eclipse.jetty.server.Server.doStart(Server.java:262)
		at org.mortbay.jetty.plugin.JettyServer.doStart(JettyServer.java:65)
		at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
		at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:511)
		at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:364)
		at org.mortbay.jetty.plugin.JettyRunMojo.execute(JettyRunMojo.java:516)
		at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
		at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
		at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
		at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
		at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
		at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
		at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
		at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
		at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
		at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
		at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
		at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
		at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
		at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
		at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
		at java.lang.reflect.Method.invoke(Method.java:597)
		at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
		at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
		at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
		at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
	Caused by: java.lang.NoClassDefFoundError: org/eclipse/jetty/servlet/ServletContextHandler$Decorator
		at java.lang.ClassLoader.defineClass1(Native Method)
		at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
		at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
		at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
		at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
		at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
		at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
		at java.security.AccessController.doPrivileged(Native Method)
		at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
		at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:415)
		at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:377)
		at org.jboss.weld.environment.servlet.util.Reflections.classForName(Reflections.java:51)
		... 44 more
	Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.servlet.ServletContextHandler$Decorator
		at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
		at java.security.AccessController.doPrivileged(Native Method)
		at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
		at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:415)
		at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:377)
		... 56 more

The application was running but as the exception message states: CDI injection will not be available in Servlets.

A couple of days ago, I found the article [Starting a CDI webapp from Maven with Weld-Servlet and Jetty Plugin](http://agorava.org/news/2012/07/10/Starting-a-CDI-webapp-from-Maven-with-Weld-servlet-and-jetty-plugin/) and especially the section **Last trick to allow injection in servlets**. The author explains that Weld needs to decorate some Jetty internal classes in order to use the @Inject annotation in servlets and that we have to tell the Jetty classloader where to find this class in order to have the Weld servlet to decorate it.

I was waiting so long for this special information. So I added the file **src/main/webapp/WEB-INF/jetty-context.xml**:

	<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">

	<Configure id="webAppCtx" class="org.eclipse.jetty.webapp.WebAppContext">
		<Set name="serverClasses">
			<Array type="java.lang.String">
				<Item>org.eclipse.jetty.servlet.ServletContextHandler.Decorator</Item>
			</Array>
		</Set>
	</Configure> 

I also updated the **pom.xml** in order to incorporate the file jetty-context.xml (last line):

	...
	<plugin>
		<groupId>org.mortbay.jetty</groupId>
		<artifactId>jetty-maven-plugin</artifactId>
		<version>${jetty.version}</version>
		<configuration>
			<webApp>
				<contextPath>/${project.build.finalName}</contextPath>
			</webApp>
			<jettyEnvXml>src/main/webapp/WEB-INF/jetty-env.xml</jettyEnvXml>
			<contextXml>src/main/webapp/WEB-INF/jetty-context.xml</contextXml>
			...

Now the above error disappeared. I was so happy for that short moment :)

In src/main/resources/log4j.properties I increased the log level for Weld:

	...
	log4j.logger.org.jboss.weld=DEBUG, stdout
	log4j.additivity.org.jboss.weld=false
	...

When starting the application I get the following Weld log messages:

	...
	2012-07-31 12:00:08,968 [main] INFO  org.jboss.weld.Bootstrap - WELD-000101 Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
	2012-07-31 12:00:09,109 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000103 Enabled alternatives for Manager
	Enabled alternatives: [] []
	Registered contexts: [interface javax.enterprise.context.SessionScoped, interface javax.enterprise.context.ApplicationScoped, interface javax.enterprise.context.Dependent, interface javax.enterprise.context.RequestScoped, interface javax.enterprise.context.ConversationScoped, interface javax.inject.Singleton]
	Registered beans: 0
	: [] []
	2012-07-31 12:00:09,109 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000104 Enabled decorator types for Manager
	Enabled alternatives: [] []
	Registered contexts: [interface javax.enterprise.context.SessionScoped, interface javax.enterprise.context.ApplicationScoped, interface javax.enterprise.context.Dependent, interface javax.enterprise.context.RequestScoped, interface javax.enterprise.context.ConversationScoped, interface javax.inject.Singleton]
	Registered beans: 0
	: []
	2012-07-31 12:00:09,109 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000105 Enabled interceptor types for Manager
	Enabled alternatives: [] []
	Registered contexts: [interface javax.enterprise.context.SessionScoped, interface javax.enterprise.context.ApplicationScoped, interface javax.enterprise.context.Dependent, interface javax.enterprise.context.RequestScoped, interface javax.enterprise.context.ConversationScoped, interface javax.inject.Singleton]
	Registered beans: 0
	: []
	2012-07-31 12:00:09,171 [main] INFO  org.jboss.weld.environment.jetty.JettyPost72Container - Jetty7 detected, JSR-299 injection will be available in Listeners, Servlets and Filters.
	2012-07-31 12:00:09,265 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Implicit Bean [javax.enterprise.inject.spi.InjectionPoint] with qualifiers [@Default]
	2012-07-31 12:00:09,265 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: org.jboss.weld.bean-flat-Built-in-org.jboss.weld.context.DependentContext
	2012-07-31 12:00:09,281 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.util.MediaType] with qualifiers [@Any @Default]
	2012-07-31 12:00:09,281 [main] WARN  org.jboss.weld.interceptor.util.InterceptionTypeRegistry - Class 'javax.ejb.PostActivate' not found, interception based on it is not enabled
	2012-07-31 12:00:09,281 [main] WARN  org.jboss.weld.interceptor.util.InterceptionTypeRegistry - Class 'javax.ejb.PrePassivate' not found, interception based on it is not enabled
	2012-07-31 12:00:09,281 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.web.LoginBean] with qualifiers [@Any @Default]
	2012-07-31 12:00:09,281 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: org.jboss.weld.bean-flat-Built-in-org.jboss.weld.context.http.HttpRequestContext
	2012-07-31 12:00:09,281 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: org.jboss.weld.bean-flat-Built-in-org.jboss.weld.context.http.HttpSessionContext
	2012-07-31 12:00:09,281 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.web.CustomerBean] with qualifiers [@Any @Default @Named]
	2012-07-31 12:00:09,281 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: org.jboss.weld.bean-flat-Built-in-org.jboss.weld.context.bound.BoundConversationContext
	2012-07-31 12:00:09,281 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: org.jboss.weld.bean-flat-Built-in-org.jboss.weld.context.ApplicationContext
	2012-07-31 12:00:09,281 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.util.LocaleBean] with qualifiers [@Any @Default @Named]
	2012-07-31 12:00:09,281 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: org.jboss.weld.bean-flat-Built-in-org.jboss.weld.context.bound.BoundRequestContext
	2012-07-31 12:00:09,281 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: org.jboss.weld.bean-flat-Built-in-org.jboss.weld.context.SingletonContext
	2012-07-31 12:00:09,281 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Implicit Bean [javax.enterprise.inject.Instance] with qualifiers [@Default]
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.DataReader] with qualifiers [@Any @Default @Named]
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.SessionBean] with qualifiers [@Any @Default @Named]
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.ConnectionTable] with qualifiers [@Any @Default @Named]
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: org.jboss.weld.bean-flat-Built-in-org.jboss.weld.context.http.HttpConversationContext
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.servlet.ClientServlet] with qualifiers [@Any @Default]
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: org.jboss.weld.bean-flat-Built-in-org.jboss.weld.context.RequestContext
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: org.jboss.weld.bean-flat-Built-in-javax.enterprise.context.Conversation
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Implicit Bean [javax.enterprise.event.Event] with qualifiers [@Default]
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.CustomerListBean] with qualifiers [@Any @Default]
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.Customer] with qualifiers [@Any @Default]
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.servlet.StreamingServlet] with qualifiers [@Any @Default]
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: org.jboss.weld.bean-flat-Built-in-org.jboss.weld.context.bound.BoundSessionContext
	2012-07-31 12:00:09,296 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106 Bean: Managed Bean [class de.telexiom.cardiom.SessionInfo] with qualifiers [@Any @Default]
	2012-07-31 12:00:09,312 [main] DEBUG org.jboss.weld.Reflection - WELD-000601 interface javax.inject.Named is missing @Target. Weld will use this annotation, however this may make the application unportable.
	2012-07-31 12:00:09,312 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000100 Weld initialized. Validating beans
	...

I use the **Servlet 3.0 API**, the StreamingServlet and the ClientServlet are configured via annotations. The problem is that the application scoped beans **connectionTable** and **dataReader** are not injected:

	@WebServlet(value = "/stream", initParams = @WebInitParam(name = "maxIdleTime", value = "0"))
	public class StreamingServlet extends HttpServlet
	{
		@Inject
		private ConnectionTable connectionTable;
		...

	@WebServlet(value = "/push", loadOnStartup = 1, initParams = @WebInitParam(name = "maxIdleTime", value = "0"))
	public class ClientServlet extends WebSocketServlet
	{
		@Inject
		private ConnectionTable connectionTable;

		@Inject
		private	DataReader dataReader;
		...

Calling the (not) injected properties, I always get NullPointerExceptions. The problem also remains when configuring the Servlets via web.xml. I have no more ideas about what I am doing wrong. Reading all the articles about CDI in combination with Jetty and Maven, I wonder if I am the only one having these injection problems.

In my JSF bean class **UserBean.java** the injection works, I don't have to use setter methods for the properties connectionTable and dataReader to be initialized.

Using the output statements below in the DataReader constructor (and also in the ConnectionTable class)

	@ApplicationScoped
	public class DataReader implements Serializable
	{
		...
		public DataReader()
		{
			System.out.println("DataReader.DataReader(): " + this);
		}
		...

I wonder about the 2 DataReader instances which show up on stdout:

	...
	2012-07-31 14:03:04,843 [qtp5435124-17] DEBUG org.jboss.weld.JSF - WELD-000504 Resuming conversation with id null
	31.07.2012 14:03:05 org.apache.myfaces.util.ExternalSpecifications isUnifiedELAvailable
	INFO: MyFaces Unified EL support enabled
	DataReader.DataReader(): DataReader$Proxy$_$$_WeldClientProxy@506e6d
	ConnectionTable.ConnectionTable(): ConnectionTable$Proxy$_$$_WeldClientProxy@93b16c

	2012-07-31 14:03:19,093 [qtp5435124-16] DEBUG org.jboss.weld.JSF - WELD-000504 Resuming conversation with id null
	DataReader.DataReader(): DataReader@1cbd382

The first 5 lines are printed after form-based authentication and the last 2 lines appear when my JSF action is handled for the first time where the injected dataReader property is used. Since the beans are application scoped, I really wonder about the 2 constructor passes. But from the behavior of the application I think there is nothing wrong with it.

My last assumption is that the servlets somehow live in seperated, independent contexts or containers or something like that. Because it is also not possible to get the FacesContext in the 2 other Servlets: **FacesContext.getCurrentInstance()** gives **null**. But I don't know if this is important in some way.

I hope anyone can help me to figure out the problem. Thank you in advance

Sebastian