Startup of servlet contexts without web.xml

Servlets of release 3 can be configured programatically, without any web.xml.
With Spring and its Java-configuration you create a configuration class that implements org.springframework.web.WebApplicationInitializer.
Spring will automatically find all classes that implement this interface and start the according servlet contexts. More excatly its not Spring that searches for those classes, its the servlet container (e.g. jetty or tomcat ).
The class org.springframework.web.SpringServletContainerInitializer is annotated with
@javax.servlet.annotation.HandlesTypes(WebApplicationInitializer.class)
and implements javax.servlet.ServletContainerInitializer
According to the Servlet 3 specification the container will call org.springframework.web.SpringServletContainerInitializer.onStartup(Set<Class<?>>, ServletContext) on every class in the classpath implementing that interface, suppling a set of classes as defined in HandlesTypes

Startup order, if there is more than one context

If there is more than one class that implements WebApplicationInitializer, the order in which they are started can be controlled with the annotation org.springframework.core.Ordered .

Things that may go wrong

Different Spring versions in the classpath

If you have different versions of WebApplicationInitializer in the classpath, the servlet container may scan for the classes implementing WebApplicationInitializer of version 'A' while your configuration classes implement WebApplicationInitializer of version 'B'. And than your configuration classes will not be found and the sercletontexts will not be started.

Unexpected WebApplicationInitializers in the classpath

Do not package any WebApplicationInitializers into jars or wars that you later may have in the classpath of other web applications. They may get found and started when you do not expect it. This happend to me when I packed WebApplicationInitializers with Maven into test-jars, which were resued by other tests.

To many classes in the classpath

The servlet container has to scan the classpath, and the more classes, the longer it takes.
At least Jetty has a build in timeout, so you may get an
javax.websocket.DeploymentException thrown by
org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer

The solution is to tell jetty which jars to scan. This will make the startup much faster and avoids the timeout. In Maven you can do it like this :

pom.xml
<plugin>
     <groupId> org.eclipse.jetty</groupId >
     <artifactId> jetty-maven-plugin</artifactId >
     <configuration>
     <webAppConfig>
         <contextPath> /${project.artifactId}</contextPath >
         <webInfIncludeJarPattern> busines-letter-*.</webInfIncludeJarPattern >
     </webAppConfig>
...

Spring logging

When you have logging configured you should find one of the following entries in your log :
If Spring finds no WebApplicationInitializer at all, you will see in the log :
No Spring WebApplicationInitializer types detected on classpath

If Spring finds at least one WebApplicationInitializer you will see :
Spring WebApplicationInitializers detected on classpath: " + initializers

Comments

comments powered by Disqus