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
```java
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! ---");
       }
    }
```
  1. Compile the source file (don’t forget to add the servlet-api.jar to the classpath!) i.e. like this:
```console
javac src/com/nullhaus/MyInitializer.java -cp $TOMCAT7_HOME/lib/servlet-api.jar -d bin/
```
  1. Now create a META-INF/services directories which will use a JAR services API,
  2. 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   
> &nbsp;&nbsp;&nbsp;&nbsp;\`-- services  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\`-- javax.servlet.ServletContainerInitializer
  1. Type the fully-qualified class name of your implementation from step 1 into the file created in step 4
> com.nullhaus.MyInitializer
  1. Wrap everything into an elegant JAR file (the below command is executed within the bin directory)
```
jar cf ../myJar.jar
```
  1. Place the JAR file within your WEB-INF/lib directory,
  2. 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? ;-)