Monday, October 14, 2013

How to install CDI in Tomcat?


JSF is moving towards CDI for bean management. Since JSF 2.2, as part of Java EE 7, there's the new CDI compatible @ViewScoped and there's the CDI-only @FlowScoped which doesn't have an equivalent for @ManagedBean. Since JSF 2.3, as part of Java EE 8, the @ManagedBean and associated scopes from javax.faces.bean package are deprecated in favor of CDI.

Now, there are some JSF users using Tomcat which does as being a barebones JSP/Servlet container not support CDI out the box (also not JSF, you know, you had to supply JSF JARs yourself). If you intend to use CDI on Tomcat, the most straightforward step would be to upgrade it to TomEE. It's exactly like Tomcat, but then with among others OpenWebBeans on top of it, which is Apache's CDI implementation. TomEE installs as easy as Tomcat: just download the ZIP and unzip it. TomEE integrates in Eclipse as easy as Tomcat: just use existing Tomcat server plugin. As a bonus, TomEE also comes with EJB and JPA, making services and DB interaction a breeze.

However, perhaps you just have no control over upgrading the server. In that case, you'd like to supply CDI along with the webapp itself then in flavor of some JARs and additional configuration entries/files. So far, there are 2 major CDI implementations: Weld (the reference implementation) and OpenWebBeans. We'll treat them both in this article.

Install Weld in Tomcat (last updated: 8 November 2020)

Perform the following steps:

  1. Drop weld-servlet-shaded.jar in webapp's /WEB-INF/lib. In case you're using Maven, this is the coordinate:
  2. Create /META-INF/context.xml file in webapp's web content with following content (or, if you already have one, add just the <Resource> entry to it):
        <Resource name="BeanManager" 
            factory="org.jboss.weld.resources.ManagerObjectFactory" />
    This will register Weld's BeanManager factory in Tomcat's JNDI. This cannot be performed programmatically by Weld because Tomcat's JNDI is strictly read-only. This step is not necessary if you're targeting at least Mojarra 2.2.11 and/or OmniFaces 2.4 or newer. Both are able to find it in ServletContext instead. However, there may be other libraries which still expect to find BeanManager in JNDI, you'd then best keep this configuration file anyway for those libraries.
  3. Create a (empty) /WEB-INF/beans.xml file (no, not in /META-INF! that's only for inside JAR files such as OmniFaces).
  4. Only if your web.xml is declared conform Servlet version 4.0 instead of 3.1, then you also need to put the @javax.faces.annotation.FacesConfig annotation on an arbitrary CDI managed bean somewhere in the project (usually the one representing the "application-wide config" would be OK).
    package com.example;
    import javax.enterprise.context.ApplicationScoped;
    import javax.faces.annotation.FacesConfig;
    public class Config {
    It is indeed utterly unnecessary, but it is what it is.
  5. Optionally: if you also want to use JSR-303 Bean Validation (@NotNull and friends), then drop jakarta.validation-api.jar and hibernate-validator.jar in webapp's /WEB-INF/lib, or use below Maven coordinate:

Now your webapp is ready for CDI in Tomcat via Weld! Note that in previous Weld versions you needed to register a <listener> in web.xml. This is not necessary anymore with at least Weld 2.2.0 on a "recent" Tomcat version!

Install OpenWebBeans in Tomcat (last updated: 3 January 2021)

Perform the following steps:

  1. This is easiest with Maven as OpenWebBeans has quite some sub-dependencies. Here are the coordinates (do note that it also includes JSR-303 Bean Validation API as without it OpenWebBeans would unexpectedly fail deployment with java.lang.TypeNotPresentException: Type javax.validation.ConstraintViolation not present caused by java.lang.ClassNotFoundException: javax.validation.ConstraintViolation):
  2. Create /META-INF/context.xml file in webapp's web content with following content (or, if you already have one, add just the <Resource> entry to it):
        <Resource name="BeanManager" 
            factory="org.apache.webbeans.container.ManagerObjectFactory" />
    This will register OpenWebBeans' BeanManager factory in Tomcat's JNDI. This cannot be performed programmatically by OpenWebBeans because Tomcat's JNDI is strictly read-only.
  3. Add the below <listener> entry to webapp's web.xml:
    This will make sure that OpenWebBeans initializes before OmniFaces, otherwise you may face a java.lang.IllegalStateException: It's not allowed to call getBeans(Type, Annotation...) before AfterBeanDiscovery.
  4. Create a (empty) /WEB-INF/beans.xml file (no, not in /META-INF! that's only for JARs such as OmniFaces).
  5. Optionally: if you also want to use JSR-303 Bean Validation (@NotNull and friends), add the below Maven coordinate:

Now your webapp is ready for CDI in Tomcat via OpenWebBeans!


Howard Smith said...

+1 great post BalusC! I like your reference to TomEE and OpenWebBeans (Apache's CDI implementation). :)

James RM said...

Great post BalusC. Lots of your post helped me. By the way can you also help me with this one?

Unknown said...

Thanks for your posts, BalusC! They are all great!

Unknown said...

Have you tried it in a production enviroment? :) It's ok?

ireti Oluwagbemi said...

The Weld guide I just downloaded from the Weld site specifies two listeners to be added for tomcat:
'org.jboss.weld.servlet.WeldInitialListener' and 'org.jboss.weld.servlet.WeldTerminalListener'. I tried that and it didn't work. However, yours works. Is it an outdated method in the guide?

nena said...

Hi BalusC - first, thanks so much for being an expert and for sharing your knowledge to help others.

I tried everything exactly as you posted and I have a custom constraint in jee 6 - but for some reason it's not called? when i attempt to submit the form with a button, my fieldValidator is not called - any idea why that could be?


whaefelinger said...

Are you 100% positive that this is all what is required? I'm getting a

SEVERE: Exception sending request initialized lifecycle event to listener instance of class com.sun.faces.config.ConfigureListener
at javax.faces.context.FacesContext.getExceptionHandler(
at javax.faces.event.ExceptionQueuedEventContext.getListenersForEventClass(

when giving it a try using Tomcat 7.0.x, JSF Mojarra 2.2.5 and weld-servlet 2.1.0.

whaefelinger said...

[..] using the "simplegreeting" example of JavaEE 6 tutorial as (natural) starting point.

Btw, which is your starting point? Would be good to be able to download the example project somehow/somewhere.

whaefelinger said...

Ok, got it working by adding the "Faces Servlet" servlet to web.xml. As it turns out, JavaEE is probably not the best starting point.

Arjan Tijms said...

Note that newer versions of Weld throw the following exception when the org.jboss.weld.environment.servlet.Listener is not configured:

javax.naming.NamingException: WELD-001300: Unable to locate BeanManager
at org.jboss.weld.resources.ManagerObjectFactory.getObjectInstance(
at javax.naming.spi.NamingManager.getObjectInstance(

Also, besides Weld and OpenWebBeans there's a third CDI implementation called CanDI (it's natively used by Caucho's Resin).

أحمد شاهين said...

Hello Balusc,
Thanks for this post, is it possible to install WELD instead of OpenWebBeans for TomEE ?

Admin said...

Muito bom, obrigado pela dica.

Moses Gone said...

I have tried to configure tomcat 7.0.50 to work with Weld( weld-servlet 2.2.6), but I am getting a strange java.lang.NoSuchMethodError: com.sun.faces.util.Util.isCdiOneOneOrGreater()Z

I am using it with a java webapp with jsf 2.2 + omnifaces

BalusC said...

@Moses: The webapp's runtime classpath is polluted with a duplicate JSF (Mojarra) impl JAR file of an older version lacking that method, e.g. 2.0 or 2.1. Just cleanup it.

Gimby said...

Really nice article which has saved me quite a lot of time. I would just like to state that when you use a decently up to date version of Tomcat 7 (or Tomcat 8, or any other servlet 3.0 compatible container) you don't actually need to configure any listener, it will just magically work.

Parminder Singh said...

We package our code in multiple jars under WEB-INF/lib. Does every jar need a beans.xml file?

Unknown said...

Awesome BalusC!!! Great post, was very useful for me. Thank you very much

Unknown said...

I also had to add the dependency org.jboss:jandex:1.2.3.Final to get Weld up and running.

Unknown said...

OWB docs are better now ;)

Unknown said...

Thanks!!! Love you.

Unknown said...

Simplesmente perfeito!
Você salvou minha vida.
Muiito obrigado!

sitio2011 said...

Great post! Tks!

Unknown said...

Well done... Great post... I use CDI env in my work but i couldn't understand why we were using Widfly. But now, reading your post, i got it.


Unknown said...

It doesn't work with weld-servlet-2.3.3.Final.jar and cdi-api-1.2.jar. I am still getting an checkCDIAvailable error.

cthiebaud said...

Thanks for the post. I wrote a 'hello-CDI-on-java-SE-world' project for me to learn the techniques exposed here and elsewhere.

For those that maybe interested:

The code is live here: (at least at this very moment, may not be live for ever)


cthiebaud said...

In fact, the live example for 'hello-CDI-on-java-SE-world' has just changed :

gokareless said...

Many thanks)))

Unknown said...

Thanks BalusC for this post.

I am using WELD 2.4.1.Final for my web application running on Tomcat 7. I am having JSF and Jax-RS Rest services in my web application. I have implemented asynchronous JAX-RS Rest Services. Async Rest call works perfect, but in logs I got following Warnings :

WELD-000715: HttpContextLifecycle guard not set. The Servlet container is not fully compliant.
WELD-000714: HttpContextLifecycle guard leak detected. The Servlet container is not fully compliant. The value was 1
WELD-000335: Conversation context is already active, most likely it was not cleaned up properly during previous request processing

I got from this website :, that these are issues from Tomcat.

Should I consider them or just ignore? If I ignore, does it affect performance of my web app? Is there any Workaround to get rid of this warnings?

Unknown said...

Hey BalusC! First of all I want to thank you for sharing your expertise on these matters. Since I started using JSF for my projects some years ago your apportations in these and other forums have been invaluable for me and I'm sure for many others.
Having say that, I'm curious about something. Can Weld be used with TomEE?

Ximo Dante said...

Hey BalusC!

Very nice post.

Cannot still use session scoped beans in Tomcat with Weld?


megiddo said...

This was such a big help to me... thanks BalusC!!!! +1

Berkson said...

Thank you. My spring application was running in windows without problem, but not in linux. It was a problem with weld. The log only displayed MalformedParameterizedTypeException and nothing more. After try your tip using weld-servlet-shaded worked like a breeze.

Anonymous said...

Thanks balusc for all your contribution, this article helped me a lot. But I have an error that I have not been able to solve.

I am using Tomcat 9 and the weld-servlet-shaded dependency and it throws me this error when importing @Postconstruct

The package javax.annotation is accessible from more than one module: , annotations.api

In my Java Build Path I have the tomcat 9 library and in the pom.xml file the dependency weld-servlet-shaded

Eric Rosas said...

serve what I add to




Eric Rosas