Using Servlets 3.0 ServletContainerInitializer

Servlets 3.0 in Java EE 6, brings new interface called ServletContainerInitializer. The name is very self-explanatory, but the question is – how it’s different from the ServletContextListener?

Well, technically, the ServletContainerInitializer is not a listener – it is an initializer and it’s executed before any servlet context will even be ready. You can use this initializer to do some programmatic servlet/filters/listeners addition (which is also possible in Servlets 3.0!).

The ServletContainerInitializer.onStartup(Set<Class<?>> c, ServletContext ctx) can pass a set of classes which are a point of interest for the implementor (first argument). You can define such classes using @HandlesTypes annotation (also new for Servlets 3.0) which can be added to your ServletContainerInitializer implementation. For more information about the annotation, take a look at the linked javadocs.

Below I’ll try to do some quite detailed guide on how to create an exemplary initializer implementor.

  1. So, firstly you need to create a class which will implement the ServletContainerInitializer

    package com.nullhaus;
    
        import javax.servlet.*;
        import java.util.*;
    
        public class MyInitializer implements
                                       ServletContainerInitializer {
           public void onStartup(Set<Class<?>> c, ServletContext cx) {
               System.out.println("--- CONTAINER INITIALIZER! ---");
           }
        }
    
  2. Compile the source file (don’t forget to add the servlet-api.jar to the classpath!) i.e. like this:

    javac src/com/nullhaus/MyInitializer.java -cp $TOMCAT7_HOME/lib/servlet-api.jar -d bin/
    
  3. Now create a META-INF/services directories which will use a JAR services API,

  4. Create a file within META-INF/services directory which will be named javax.servlet.ServletContainerInitializer. The structure should look similar to this one (the current directory is bin):

    .
    |– com
    |   `– nullhaus
    |       `– MyInitializer.class
    `– META-INF
        `– services
            `– javax.servlet.ServletContainerInitializer

  5. Type the fully-qualified class name of your implementation from step 1 into the file created in step 4

    com.nullhaus.MyInitializer

  6. Wrap everything into an elegant JAR file (the below command is executed within the bin directory)

    jar cf ../myJar.jar
    
  7. Place the JAR file within your WEB-INF/lib directory,

  8. Start the servlet container.

The result should be something similar to this log file:

2011-03-20 23:44:26 org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
2011-03-20 23:44:26 org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.5
2011-03-20 23:44:26 org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory jee6_tests
– CONTAINER INITIALIZER! –
2011-03-20 23:44:27 org.apache.catalina.startup.HostConfig deployDirectory

You have just created a Servlet 3.0 Container Initializer. Pretty neat, huh? ;-)