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.

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>

Tagged with: ,
Posted in Spring MVC
7 comments on “Migrate Spring MVC servlet.xml to Java Config
  1. Excellent post
    Thanks for the mentioned resources
    And “extends WebMvcConfigurerAdapter” it was really useful

  2. kumar says:

    Thanks Ryan,
    Really very Good post & Explaination.Thanks again!

    Ryan,I am new to Spring MVC.I want to build a small application based on Spring 3.2 MVC with no involvement of XML & without using Mavan.just using STS.
    Can you explain in depth with sample code ? so that it helps for other people like me

  3. Emanuele says:

    Really good guide, tnx.

  4. dever says:

    Thanks from me too Ryan – that was just what I needed and worked a treat – now to write the logic on my controllers

  5. Rick says:

    Sorry, mangled that. Do you know how to migrate this:

    <jsp-config>
    <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
    <page-encoding>UTF-8</page-encoding>
    </jsp-property-group>
    </jsp-config>

    • Ryan says:

      Excellent question, I don’t know of a specific way. There is Spring’s CharacterEncodingFilter but that is still defined as a Servlet filter in the web.xml and won’t fully give you what you are looking for. Other than that I would guess a MVC interceptor to set specifics on the request could work. Still seems like a bad hack. Sorry I don’t have a better answer but will update the thread if I find something.

  6. Rod Woo says:

    Exactly what I needed. Thanks!

Leave a Reply

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

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>