Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How servlet container finds WebApplicationInitializer implementations [duplicate]

Spring WebApplicationInitializer provides a programatic way to configure the Spring DispatcherServlet and ContextLoaderListener in Servlet 3.0+ compliant servlet containers. But how does it work? How servlet container finds WebApplicationInitializer implementations, is it really load all classes from classpath?

like image 320
Anton Ilinchik Avatar asked Jan 24 '15 22:01

Anton Ilinchik


People also ask

What is the use of AbstractAnnotationConfigDispatcherServletInitializer?

Mostly, developers use AbstractAnnotationConfigDispatcherServletInitializer , which is an implementation of the WebApplicationInitializer , to create Spring web applications. Traditionally, Java web applications based on Servlets were using web. xml file to configure a Java web application.

What is the use of WebApplicationInitializer?

This interface is used for booting Spring web applications. WebApplicationInitializer registers a Spring DispatcherServlet and creates a Spring web application context. Traditionally, Java Web Applications based on Servlets were using the web. xml file to configure a Java Web Application.

Does Spring MVC use servlets?

Spring's web MVC framework is, like many other web MVC frameworks, request-driven, designed around a central Servlet that dispatches requests to controllers and offers other functionality that facilitates the development of web applications. Spring's DispatcherServlet however, does more than just that.

Does spring boot use servlet?

In a Spring Boot application, the servlet is registered either as a Spring @Bean or by scanning the @WebServlet annotated classes with an embedded container. With the Spring @Bean approach, we can use the ServletRegistrationBean class to register the servlet.


2 Answers

I assume you have knowledge about java SPI and the way java.util.ServiceLoader a utility class used to load implementations. Else please read it.

But in brief for the this answer just understand : if there is one SPI, here javax.servlet.ServletContainerInitializer , then the provider should implement it and implementation must be declared in a META-INF/services/javax.servlet.ServletContainerInitializer file of the libraries jar file - Spring is such a provider and declares this in spring-web*.jar jar file and has an entry org.springframework.web.SpringServletContainerInitializer Then the service loader for ServletContainerInitializer can load the implementation. This loading is specific to ServletContainer implementation

I will explain this specific to tomcat7+ ServletContainer.

Tomcat has LifecycleListeners those will listen to lifecycle events like start,stop etc. org.apache.catalina.startup.ContextConfig is such a startup event listener for a ServletContext that configures the properties of that ServletContext, and the associated defined servlets.

So while tomcat initilizes a ServletContext for a web application, it will generate such an event which will notify the ContextConfig's even listening method. Then it will trigger its own processServletContainerInitializers method, which scan JARs for ServletContainerInitializer implementations. It does this via delegating this duty to WebappServiceLoader (a variation of Java's JAR ServiceLoader), who is actually responsible for the loading of ServletContainerInitializer implementaions from WEB-INF/lib jars.

So as conclusion the control flow would be like this.

  1. Tomcat initialize the ServletContext

  2. ContextConfig is notified with this context startup event

  3. service loading is delegated to WebappServiceLoader<ServletContainerInitializer>

  4. WebappServiceLoader scans in WEB-INF/lib jars for the file META-INF/services/javax.servlet.ServletContainerInitializer inorder to load the implementation

  5. once loaded return to step 3 and, ContextConfig will call implementation's (here SpringServletContainerInitializer) onStartup method which will do rest of the things.

HTH!

like image 74
Tom Sebastian Avatar answered Oct 19 '22 10:10

Tom Sebastian


From docs:

Implementations of this SPI will be detected automatically by
SpringServletContainerInitializer , which itself is bootstrapped automatically by any Servlet 3.0 container. See SpringServletContainerInitializer or details on this bootstrapping mechanism.

and:

Mechanism of Operation

SpringServletContainerInitializer

This class will be loaded and instantiated and have its onStartup method invoked by any Servlet 3.0-compliant container during container startup assuming
that the spring-web module JAR is present on the classpath. This occurs through the JAR Services API {@link ServiceLoader#load(Class)} method detecting the spring-web module's META-INF/services/javax.servlet.ServletContainerInitializer
service provider configuration file.

See the http://download.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider JAR Services API documentation as well as section 8.2.4 of the Servlet 3.0 Final Draft specification for complete details.

It is all in docs basically it's part of Servlet specs to detect SpringServletContainerInitializer which implements ServletContainerInitializer so its all down to container doing its job detecting these classes.

like image 35
mariubog Avatar answered Oct 19 '22 11:10

mariubog