Power up Tomcat with CDI 2.0

I hope you have used Tomcat at least once in your developer journey. I am going to tell a secret for those who are using tomcat in their day to day life. Also, this would be a starting point for those who like to try out different java technologies. Power up tomcat with CDI 2.0 seems odd to some people. I’ll give you a reason. There are many scenarios we can’t just upgrade our containers maybe because our clients are not ready. Also, it is because migrating to a new container in one go is risky.

What is CDI?

CDI refer to Context Dependency Injection. It’s a major Java EE specification where dependency injection is its primary component. In 2017, the successor to CDI 1.0, CDI 2.0 released. It has new exciting features such as working on SE stack. You can read more about the specification here.

Why Tomcat?

Tomcat is one of the most loved java containers with relatively fewer functionalities. Tomcat serves its promise well, so Tomcat is being used widely. But it lacks CDI. TomEE is the successor to tomcat where it has a particular specification. So you could use TomEE directly without moving on.

Let’s Power up Tomcat with CDI 2.0

You have two choices. Because there are only two popular, battle-tested CDI implementations. First one is weld and the other one is open web beans. I am going to use open web beans. Now I have two binary releases of Tomcat 9.0.37 and open web beans 2.0.14 (you can try latest version 2.0.16, but I couldn’t find the binaries). If you want to follow along, download both of them.

Now you have to extract both of them. Inside of open web beans directory, there is a bat file named install_owb_tomcat7. Run the bat file by giving the extracted Tomcat path. Also, you can set the CATALINA_HOME environment variable to the extracted path and run the bat file. The script will copy some jars to Tomcat’s lib directory. As you can see in the following screenshot you have to add a lifecycle listener to the context.xml. This is only needed to be done on windows environment. Otherwise, the respective shell script will do the work. After adding the listener, context.xml file will look like below.

<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
    <Listener className="org.apache.webbeans.web.tomcat7.ContextLifecycleListener" />
</Context>

Let’s write a simple CDI application

We have CDI ready tomcat. Let’s write an application that prints a message on startup. I am going to use CDI events. I’ve created a web app project using maven web app archetype. Next, we need following dependencies in provided scope, because we have them covered when we integrate open web beans with Tomcat.

<dependency>
  <groupId>javax.enterprise</groupId>
  <artifactId>cdi-api</artifactId>
  <version>2.0</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>javax.annotation</groupId>
  <artifactId>javax.annotation-api</artifactId>
  <version>1.3.2</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>javax.interceptor</groupId>
  <artifactId>javax.interceptor-api</artifactId>
  <version>1.2</version>
  <scope>provided</scope>
</dependency>

Now we need a java class, my class is as follows.

package com.aptkode;

import javax.annotation.Priority;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Initialized;
import javax.enterprise.event.Observes;
import javax.interceptor.Interceptor;

@ApplicationScoped
public class StartupListener {
    public void onInit(@Observes
                       @Initialized(ApplicationScoped.class)
                       @Priority(Interceptor.Priority.APPLICATION) Object initContext) {
        System.out.println("#######################");
        System.out.println("application initialized");
        System.out.println("#######################");
    }
}

CDI container recognizes application by beans.xml and then it wires all the beans together as well as events. So add following file into webapp/WEB-INF directory.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
       bean-discovery-mode="annotated"/>

Trying It Out

Now kick off tomcat. You can use bin/catalina.bat run command. You will see the following log. We have powered up tomcat with CDI 2.0 using apache web beans. Thanks for reading.

Read Latest Posts

Leave a Comment

Your email address will not be published. Required fields are marked *