Wednesday, March 26, 2014

Servlet 3.0 ServletContainerInitializer and Spring WebApplicationInitializer

Spring WebApplicationInitializer provides a programatic way to configure the Spring DispatcherServlet and ContextLoaderListener in Servlet 3.0+ compliant servlet containers , rather than adding this configuration through a web.xml file.

This is a quick note to show how implementation through WebApplicationInitializer interface internally works, given that this interface does not derive from any Servlet related interface!

The answer is the ServletContainerInitializer interface introduced with Servlet 3.0 specification, implementors of this interface are notified during the context startup phase and can perform any programatic registration through the provided ServletContext.

Spring implements the ServletContainerInitializer through SpringServletContainerInitializer class. Per the Servlet specs, this implementation must be declared in a META-INF/services/javax.servlet.ServletContainerInitializer file of the libraries jar file - Spring declares this in spring-web*.jar jar file and has an entry `org.springframework.web.SpringServletContainerInitializer`

SpringServletContainerInitializer class has a @HandlerTypes annotation with a value of WebApplicationInitializer, this means that the Servlet container will scan for classes implementing the WebApplicationInitializer implementation and call the onStartUp method with these classes and that is where the WebApplicationInitializer fits in.

A little convoluted, but the good thing is all these details are totally abstracted away within the spring-web framework and the developer only has to configure an implementation of WebApplicationInitializer and live in a web.xml free world.

5 comments:

  1. Nice and simple explanation; I am getting an error while imlementing the same in my project. I am using WAS 8.5 and following is the error I am seeing on server start up.
    No Spring WebApplicationInitializer types detected on classpath

    ReplyDelete
  2. We were struggling with this until we stumbled upon the following spring documentation and then implemented the WebApplicationInitializer interface directly. What is bizarre is that it worked in another WAS 8.5.5.x environment without having to implement that interface directly.

    74.4 Deploying a WAR to Weblogic
    To deploy a Spring Boot application to Weblogic you must ensure that your servlet initializer directly implements WebApplicationInitializer (even if you extend from a base class that already implements it).

    A typical initializer for Weblogic would be something like this:

    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.web.SpringBootServletInitializer;
    import org.springframework.web.WebApplicationInitializer;

    @SpringBootApplication
    public class MyApplication extends SpringBootServletInitializer implements WebApplicationInitializer {

    }



    74.4 Deploying a WAR to Weblogic
    To deploy a Spring Boot application to Weblogic you must ensure that your servlet initializer directly implements WebApplicationInitializer (even if you extend from a base class that already implements it).

    A typical initializer for Weblogic would be something like this:

    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.web.SpringBootServletInitializer;
    import org.springframework.web.WebApplicationInitializer;

    @SpringBootApplication
    public class MyApplication extends SpringBootServletInitializer implements WebApplicationInitializer {

    }

    ReplyDelete
    Replies
    1. Wow, that is totally strange. Thanks for the information.

      Delete
  3. See the following spring documentation. I know it's silly, but you need to implement the interface directly. That will solve your problem.


    74.4 Deploying a WAR to Weblogic
    To deploy a Spring Boot application to Weblogic you must ensure that your servlet initializer directly implements WebApplicationInitializer (even if you extend from a base class that already implements it).

    A typical initializer for Weblogic would be something like this:

    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.web.SpringBootServletInitializer;
    import org.springframework.web.WebApplicationInitializer;

    @SpringBootApplication
    public class MyApplication extends SpringBootServletInitializer implements WebApplicationInitializer {

    }

    ReplyDelete
  4. Very nice. Exactly what I was looking for since a long time.

    ReplyDelete