getServletConfigClasses() vs getRootConfigClasses() when extending AbstractAnnotationConfigDispatcherServletInitializer getServletConfigClasses() vs getRootConfigClasses() when extending AbstractAnnotationConfigDispatcherServletInitializer spring spring

getServletConfigClasses() vs getRootConfigClasses() when extending AbstractAnnotationConfigDispatcherServletInitializer


A Bit on ApplicationContext Hierarchies

Spring's ApplicationContext provides the capability of loading multiple (hierarchical) contexts, allowing each to be focused on one particular layer, such as the web layer of an application or middle-tier services.

One of the canonical examples of using hierarchical ApplicationContext is when we have multiple DispatcherServlets in a web application and we're going to share some of the common beans such as datasources between them. This way, we can define a root ApplicationContext that contain all the common beans and multiple WebApplicationContexts that inherit the common beans from the root context.

In the Web MVC framework, each DispatcherServlet has its own WebApplicationContext, which inherits all the beans already defined in the root WebApplicationContext. These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to a given Servlet instance.

Typical context hierarchy in Spring Web MVC
Typical context hierarchy in Spring Web MVC (Spring Documentation)

If you're living in a single DispatherServlet world, it is also possible to have just one root context for this scenario:

enter image description here
Single root context in Spring Web MVC (Spring Documentation)

Talk is cheap, Show me the code!

Suppose we're developing a web application and we're going to use Spring MVC, Spring Security and Spring Data JPA. For this simple scenario, we would have at least three different config files. A WebConfig that contains all our web related configurations, such as ViewResolvers, Controllers, ArgumentResolvers, etc. Something like following:

@EnableWebMvc@Configuration@ComponentScan(basePackages = "com.so.web")public class WebConfig extends WebMvcConfigurerAdapter {    @Bean    public InternalResourceViewResolver viewResolver() {        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();        viewResolver.setPrefix("/WEB-INF/views/");        viewResolver.setSuffix(".jsp");        return viewResolver;    }    @Override    public void configurePathMatch(PathMatchConfigurer configurer) {        final boolean DO_NOT_USE_SUFFIX_PATTERN_MATCHING = false;        configurer.setUseSuffixPatternMatch(DO_NOT_USE_SUFFIX_PATTERN_MATCHING);    }}

Here I'm defining a ViewResolver to resolve my plain old jsps, poor life decisions, basically. We would need a RepositoryConfig, which contains all the data access facilities such as DataSource, EntityManagerFactory, TransactionManager, etc. It probably would be like following:

@Configuration@EnableTransactionManagement@EnableJpaRepositories(basePackages = "com.so.repository")public class RepositoryConfig {    @Bean    public DataSource dataSource() { ... }    @Bean    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { ... }        @Bean    public PlatformTransactionManager transactionManager() { ... }}

And a SecurityConfig which contains all the security related stuff!

@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {    @Override    @Autowired    protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... }    @Override    protected void configure(HttpSecurity http) throws Exception { ... }}

For gluing all these together, we have two options. First, we can define a typical hierarchical ApplicationContext, by adding RepositoryConfig and SecurityConfig in root context and WebConfig in their child context:

public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {    @Override    protected Class<?>[] getRootConfigClasses() {        return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class };    }    @Override    protected Class<?>[] getServletConfigClasses() {        return new Class<?>[] { WebConfig.class };    }    @Override    protected String[] getServletMappings() {        return new String[] { "/" };    }}

Since we have a single DispatcherServlet here, we can add the WebConfig to the root context and make the servlet context empty:

public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {    @Override    protected Class<?>[] getRootConfigClasses() {        return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class, WebConfig.class };    }    @Override    protected Class<?>[] getServletConfigClasses() {        return null;    }    @Override    protected String[] getServletMappings() {        return new String[] { "/" };    }}

Further Reading

Skaffman did a great job on explaining ApplicationContext hierarchies in this answer, which is highly recommended. Also, you can read Spring Documentation.


Root Config Classes are actually used to Create Beans which are Application Specific and which needs to be available for Filters (As Filters are not part of Servlet).

Servlet Config Classes are actually used to Create Beans which are DispatcherServlet specific such as ViewResolvers, ArgumentResolvers, Interceptor, etc.

Root Config Classes will be loaded first and then Servlet Config Classes will be loaded.

Root Config Classes will be the Parent Context and it will create a ApplicationContext instace. Where as Servlet Config Classes will be the Child Context of the Parent Context and it will create a WebApplicationContext instance.

In your ConServlet Configuration, You don't need to specify the @EnableWebMvc as well the InternalResourceViewResolver bean as they are only required at the WebConfig.