Introduction
JSF was since version 2.2 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 / Jakarta Faces 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 10+ (last updated: 13 July 2024)
Tomcat 10.0.x is the first version to be "Jakartified", i.e. it's using jakarta.*
package instead of javax.*
package for the API classes. It is using Servlet 5.0 API of Jakarta EE 9. Tomcat 10.1.x is the second Jakartified version, using Servlet 6.0 API of Jakarta EE 10.
In order to install CDI on Tomcat 10.x, perform the following steps:
- For Tomcat 10.1.x, drop
weld-servlet-shaded.jar
of version 5.x in webapp's/WEB-INF/lib
. In case you're using Maven, this is the coordinate:<dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-shaded</artifactId> <version>5.1.2.Final</version> </dependency>
For Tomcat 10.0.x, useweld-servlet-shaded.jar
of version 4.x instead:<dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-shaded</artifactId> <version>4.0.3.Final</version> </dependency>
- Create a
/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):<Context> <Resource name="BeanManager" auth="Container" type="jakarta.enterprise.inject.spi.BeanManager" factory="org.jboss.weld.resources.ManagerObjectFactory" /> </Context>
This will register Weld'sBeanManager
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 for Mojarra and OmniFaces because both libraries are able to find it inServletContext
instead. However, there may be other libraries which still expect to findBeanManager
in JNDI, so you'd then best keep this configuration file anyway for those libraries. - Create a (empty)
/WEB-INF/beans.xml
file (no, not in/META-INF
! that's only for inside JAR files such as OmniFaces). - Optionally: if you also want to use JSR-303 Bean Validation (
@NotNull
and friends), then dropjakarta.validation-api.jar
of version 3.0.x andhibernate-validator.jar
of version 8.0.x in webapp's/WEB-INF/lib
, or use below Maven coordinate:<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>8.0.1.Final</version> </dependency>
For Tomcat 10.0.x, usehibernate-validator.jar
of version 7.0.x instead.
Now your webapp is ready for CDI in Tomcat 10+ via Weld!
Install Weld in Tomcat 9- (last updated: 1 Dec 2022)
The difference with Tomcat 10+ is that Tomcat 9- still uses the old javax.*
package instead of the new jakarta.*
package. This is not compatible with Weld 4+, you need Weld 3 instead. Perform the following steps:
- Drop
weld-servlet-shaded.jar
of version 3.x in webapp's/WEB-INF/lib
. In case you're using Maven, this is the coordinate:<dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-shaded</artifactId> <version>3.1.9.Final</version> </dependency>
- 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):<Context> <Resource name="BeanManager" auth="Container" type="javax.enterprise.inject.spi.BeanManager" factory="org.jboss.weld.resources.ManagerObjectFactory" /> </Context>
This will register Weld'sBeanManager
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 inServletContext
instead. However, there may be other libraries which still expect to findBeanManager
in JNDI, you'd then best keep this configuration file anyway for those libraries. - Create a (empty)
/WEB-INF/beans.xml
file (no, not in/META-INF
! that's only for inside JAR files such as OmniFaces). - 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; @FacesConfig @ApplicationScoped public class Config { }
It is indeed utterly unnecessary, but it is what it is. - Optionally: if you also want to use JSR-303 Bean Validation (
@NotNull
and friends), then dropjakarta.validation-api.jar
andhibernate-validator.jar
in webapp's/WEB-INF/lib
, or use below Maven coordinate:<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.2.5.Final</version> </dependency>
Now your webapp is ready for CDI in Tomcat 9- 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 9- version!
Install OpenWebBeans in Tomcat 10+ (last updated: 13 July 2024)
- This is easiest with Maven as OpenWebBeans has quite some sub-dependencies. Here are the coordinates:
<dependency> <groupId>org.apache.openwebbeans</groupId> <artifactId>openwebbeans-jsf</artifactId> <version>4.0.2</version> </dependency> <dependency> <groupId>org.apache.openwebbeans</groupId> <artifactId>openwebbeans-el22</artifactId> <version>4.0.2</version> </dependency>
- 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):<Context> <Resource name="BeanManager" auth="Container" type="jakarta.enterprise.inject.spi.BeanManager" factory="org.apache.webbeans.container.ManagerObjectFactory" /> </Context>
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. - Add the below
<listener>
entry to webapp'sweb.xml
:<listener> <listener-class>org.apache.webbeans.servlet.WebBeansConfigurationListener</listener-class> </listener>
This will make sure that OpenWebBeans initializes before Jakarta Faces, otherwise you may face ajava.lang.IllegalStateException: It's not allowed to call getBeans(Type, Annotation...) before AfterBeanDiscovery
. - Create a (empty)
/WEB-INF/beans.xml
file (no, not in/META-INF
! that's only for JARs such as OmniFaces). - Optionally: if you also want to use JSR-303 Bean Validation (
@NotNull
and friends), add the below Maven coordinate:<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>8.0.1.Final</version> </dependency>
Now your webapp is ready for CDI in Tomcat 10+ via OpenWebBeans!
Install OpenWebBeans in Tomcat 9- (last updated: 3 January 2021)
The difference with Tomcat 10+ is that Tomcat 9- still uses the old javax.*
package instead of the new jakarta.*
package. Perform the following steps:
- 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 byjava.lang.ClassNotFoundException: javax.validation.ConstraintViolation
):<dependency> <groupId>javax.enterprise</groupId> <artifactId>cdi-api</artifactId> <version>2.0</version> </dependency> <dependency> <groupId>org.apache.openwebbeans</groupId> <artifactId>openwebbeans-jsf</artifactId> <version>2.0.20</version> </dependency> <dependency> <groupId>jakarta.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.2</version> </dependency>
- 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):<Context> <Resource name="BeanManager" auth="Container" type="javax.enterprise.inject.spi.BeanManager" factory="org.apache.webbeans.container.ManagerObjectFactory" /> </Context>
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. - Add the below
<listener>
entry to webapp'sweb.xml
:<listener> <listener-class>org.apache.webbeans.servlet.WebBeansConfigurationListener</listener-class> </listener>
This will make sure that OpenWebBeans initializes before OmniFaces, otherwise you may face ajava.lang.IllegalStateException: It's not allowed to call getBeans(Type, Annotation...) before AfterBeanDiscovery
. - Create a (empty)
/WEB-INF/beans.xml
file (no, not in/META-INF
! that's only for JARs such as OmniFaces). - Optionally: if you also want to use JSR-303 Bean Validation (
@NotNull
and friends), add the below Maven coordinate:<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.2.0.Final</version> </dependency>
Now your webapp is ready for CDI in Tomcat 9- via OpenWebBeans!