56

I am working with Spring 4.0.7

I did a research about configure Spring MVC through JavaConfig.

Practically until yesterday I have seen two configurations using these two options

  1. extends AbstractAnnotationConfigDispatcherServletInitializer
  2. extends WebMvcConfigurerAdapter and implements WebApplicationInitializer

Note: (2) are two classes, one for extension and the other for implementation

I am using (2) because I have found many examples where I am able to configure converters, formatters, resources handlers etc…

But in the latest days I have tried to help a question on StackOverflow and I did realize (1) exists.. I did some overview on Google about (1) and exists some examples working with (1)

My question is how the title of this post describe.

Thank You

Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158

2 Answers2

71

With the release of the Servlet 3.0 spec it became possible to configure your Servlet Container with (almost) no xml. For this there is the ServletContainerInitializer in the Servlet specification. In this class you can register filters, listeners, servlets etc. as you would traditionally do in a web.xml.

Spring provides a an implementation the SpringServletContainerInitializer which knows how to handle WebApplicationInitializer classes. Spring also provides a couple of base classes to extend to make your life easier and the AbstractAnnotationConfigDispatcherServletInitializer is one of those. It registers a ContextLoaderlistener (optionally) and a DispatcherServlet and allows you to easily add configuration classes to load for both classes and to apply filters to the DispatcherServlet and to provide the servlet mapping.

The WebMvcConfigurerAdapter is for configuring Spring MVC, the replacement of the xml file loaded by the DispatcherServlet for configuring Spring MVC. The WebMvcConfigurerAdapter should be used for a @Configuration class.

@Configuration
@EnableWebMvc
public class WebConfiguration 
    extends WebMvcConfigurerAdapter implements WebApplicationInitializer
{ ... }

I wouldn't recommend mixing those as they are basically 2 different concerns. The first is for configuring the servlet container, the latter for configuring Spring MVC.

You would want to split those into 2 classes.

For the configuration.

@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter { ... }

For bootstrapping the application.

public class MyWebApplicationInitializer
    extends AbstractAnnotationConfigDispatcherServletInitializer
{

    protected Class<?>[] getRootConfigClasses() {
        return new Class[] {RootConfig.class};
    }
    
    protected Class<?>[] getServletConfigClasses()  {
        return new Class[] {WebConfiguration .class};
    }
    
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }

}

An added advantage is that you now can use the convenience classes provided by Spring instead of manually configuring the DispatcherServlet and/or ContextLoaderListener.

Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • Yes, is not wise mix (1) and (2), currently I am working with (2), therefore (`extends WebMvcConfigurerAdapter and implements WebApplicationInitializer`) – Manuel Jordan Oct 31 '14 at 18:01
  • That is actually mixing the 2 strategies. You now have a single class that is responsible for configuring the servlet container and for configuring the Spring application. I would have 2 classes one for configuring the application and one for the servlet container. – M. Deinum Nov 02 '14 at 16:15
  • I am confused, I have seen some examples about using WebMvcConfigurerAdapter and WebApplicationInitializer, I only use these two *objects*, one to replace the web.xml and the other to configure Spring MVC. – Manuel Jordan Nov 02 '14 at 22:00
  • The Spring Core training material is working with the two elements mentioned in my previous comment. – Manuel Jordan Nov 02 '14 at 22:05
  • What classes do you use? Thank You. – Manuel Jordan Nov 02 '14 at 22:11
  • No you have a single object with 2 responsibilities. Of course you can do it, but for a larger applicatation I wouldn't recommend it. Just create a class that configures the context, generally extending `AbstractAnnotationConfigDispatcherServletInitializer` and pass it the class that should be annotated with `@Configurable` and extending `WebMvcConfigurerAdapter`. That way you have 2 classes both having a single responsibility. – M. Deinum Nov 03 '14 at 06:36
  • Oh, you understood in a wrong way, I have a class that extends WebMvcConfigurerAdapter to configure Spring MVC, and I have **other** class that implements WebApplicationInitializer to configure the two context, the server and web side. – Manuel Jordan Nov 03 '14 at 12:34
  • I had a strange issue with Abstract...ServletInitializer. If anyone can help please post there - http://stackoverflow.com/questions/37498024/nosuchbeandefinitionexception-no-qualifying-bean-of-type-repository-found-for – Shamseer May 29 '16 at 19:46
  • 1
    Where can I get the `RootConfig.class`? – zygimantus Feb 14 '17 at 12:34
23

To start from the beginning it is worth looking into how servlet container starts.

So to start - SpringServletContainerInitializer has to find the right class implementing WebApplicationInitializer. There are two ways of making it happen:

  1. One is by implementing WebApplicationInitializer on its own; the interface was introduced in Spring 3.1
  2. The second is by extending AbstractAnnotationConfigDispatcherServletInitializer class which also implements WebApplicationInitializer. The class was introduced in Spring 3.2 for convenience and it is "the preferred approach for applications that use Java-based Spring configuration." - see the link. It enables you to start servlet application context as well as root application context.

I would also like to higlight that WebMvcConfigurerAdapter you mention should not be confused with WebApplicationInitializer. As it name suggests - it has to do with configuring "Mvc". It is an adapter class that implements empty methods from WebMvcConfigurer. You use it when you configure your Mvc controller with @EnableWebMvc annotation.

Hope this helps.

Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
Witold Kaczurba
  • 9,845
  • 3
  • 58
  • 67