Migrate Spring MVC servlet.xml to Java Config

Since Spring 3, Java configuration (@Configuration) has been moved into spring-core and has caught my attention. This is a quick sample of how to convert an existing servlet.xml file into a java config file extending WebMvcConfigurerAdapter.

Beginning xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

    <!-- Scan for spring annotated components -->
    <context:component-scan base-package="com.luckyryan.sample"/>

    <!-- Process annotations on registered beans like @Autowired... -->
    <context:annotation-config/>

    <!-- This tag registers the DefaultAnnotationHandlerMapping and
         AnnotationMethodHandlerAdapter beans that are required for Spring MVC  -->
    <mvc:annotation-driven/>

    <!-- Exception Resolver that resolves exceptions through @ExceptionHandler methods -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver"/>

    <!-- View Resolver for JSPs -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- This tag allows for mapping the DispatcherServlet to "/" -->
    <mvc:default-servlet-handler/>

    <!-- resources exclusions from servlet mapping -->
    <mvc:resources mapping="/assets/**" location="classpath:/META-INF/resources/webjars/"/>
    <mvc:resources mapping="/css/**" location="/css/"/>
    <mvc:resources mapping="/img/**" location="/img/"/>
    <mvc:resources mapping="/js/**" location="/js/"/>

</beans>

1. Create the configuration class, I like to create a “config” package with a class named appConfig.java
2. Add @Configuration, this will let spring know this contains bean definitions.

package com.luckyryan.sample.config;

import org.springframework.context.annotation.Configuration;

@Configuration
public class appConfig {

}

3. Add @EnableWebMVC, this is the same as <mvc:annotation-driven/>

@EnableWebMvc
@Configuration
public class appConfig {

}

4. Add @ComponentScan(basePackages = {“com.luckyryan.sample”}), this is the same as <context:component-scan base-package=”com.luckyryan.sample”/>

@EnableWebMvc
@ComponentScan(basePackages = {"com.luckyryan.sample"})
@Configuration
public class appConfig {

}

5. Extend the class to use WebMvcConfigurerAdapter. This adds stub implementations from the WebMvcConfigurer interface which is used by @EnableWebMVC. It also gives us a chance to override resources and the default handler.

@EnableWebMvc
@ComponentScan(basePackages = {"com.luckyryan.sample"})
@Configuration
public class appConfig extends WebMvcConfigurerAdapter {

}

6. Declare our static resources. I added cache to the java config but it’s not required.

@EnableWebMvc
@ComponentScan(basePackages = {"com.luckyryan.sample"})
@Configuration
public class appConfig extends WebMvcConfigurerAdapter {

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
    	registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(31556926);
    	registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
    	registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
    	registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
 	}

}

7. Set default servlet handler, this is the same as <mvc:default-servlet-handler/>

@EnableWebMvc
@ComponentScan(basePackages = {"com.luckyryan.sample"})
@Configuration
public class appConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(31556926);
        registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
        registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
        registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public InternalResourceViewResolver getInternalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/pages/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}

8. Add bean for InternalResourceViewResolver

package com.luckyryan.sample.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@ComponentScan(basePackages = {"com.luckyryan.sample"})
@Configuration
public class appConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(31556926);
        registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
        registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
        registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public InternalResourceViewResolver getInternalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/pages/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}

9. Update the servlet declaration in web.xml for the new config class and annotation conf. Note: this replaces the need for <context:annotation-config/> which was not featured in the servlet.xml example.

...
...
<servlet>
    <servlet-name>sample</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </init-param>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            com.luckyryan.sample.config.appConfig
        </param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>sample</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

24 Comments

  1. LanLan Zhang March 31, 2016
  2. Josh Molina March 16, 2016
  3. Maci September 2, 2015
  4. Thrawn June 10, 2015
  5. Alabama Mothman May 28, 2015
    • TS.Nam. April 25, 2016
  6. anand February 14, 2015
  7. Yuva February 13, 2015
  8. Hassan January 31, 2015
  9. Kitty January 22, 2015
  10. Al Mathews January 19, 2015
  11. Rambabu November 28, 2014
  12. pushkar May 27, 2014
    • Ryan May 28, 2014
  13. Abilash May 5, 2014
  14. Rod Woo March 19, 2014
  15. Rick March 9, 2014
    • Ryan March 10, 2014
  16. dever June 29, 2013
  17. Emanuele June 26, 2013
  18. kumar June 4, 2013
    • Alabama Mothman May 28, 2015
      • Patrick Joly November 6, 2015
  19. Spring-Hibernate Dev March 25, 2013

Leave a Reply

Your email address will not be published. Required fields are marked *