This blog entry describes how you can create a web application which has restful url addresses by using Spring MVC 3.1 and the default-servlet-handler element of MVC XML namespace. The requirements for RESTful urls are given in following:

  • An url address must no have suffix in it (in other words, an url address most not contain a suffix like ’.action’).
  • The context path of the web application must not start with a prefix like ‘app’.

I have figured out three alternative solutions to this problem and first of them is described in following.

Required Steps

You can fulfill the given requirements by implementing the following steps:

  • Configuring the application context
  • Configuring the web application and the dispatcher servlet

I will describe these steps with more details in following Sections.

Configuring the Application Context

First, you have to configure the application context of your application. This step consists of three smaller steps:

  1. Configure the location of static resources such as css files.
  2. Ensure that static resources are served by the container’s default servlet
  3. Create an application context configuration class.

The first two steps can be implemented by creating an application context configuration file which content is given in following (NOTE: As Rossen pointed out, you can use Java configuration as well. See his comment for more details):

 1<?xml version="1.0" encoding="UTF-8"?>
 2<beans xmlns="http://www.springframework.org/schema/beans"
 3       xmlns:mvc="http://www.springframework.org/schema/mvc"
 4       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
 6        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
 7    <!--
 8        Configures the location of static resources such as css files.
 9        Requires Spring Framework 3.0 or higher.
10     -->
11    <mvc:resources mapping="/static/**" location="/static/"/>
12
13    <!--
14        Ensures that dispatcher servlet can be mapped to '/' and that static resources
15        are still served by the containers default servlet. Requires Spring Framework
16        3.0 or higher.
17     -->
18    <mvc:default-servlet-handler/>
19</beans>

The third step of the application context configuration can be implemented by using a simple Java configuration class which enables the Spring MVC support, imports the application context configuration file, sets the component scan base package and configures a view resolver bean. The source code of this configuration class is given in following:

 1import org.springframework.context.annotation.Bean;
 2import org.springframework.context.annotation.ComponentScan;
 3import org.springframework.context.annotation.Configuration;
 4import org.springframework.context.annotation.ImportResource;
 5import org.springframework.web.servlet.ViewResolver;
 6import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 7import org.springframework.web.servlet.view.InternalResourceViewResolver;
 8import org.springframework.web.servlet.view.JstlView;
 9
10/**
11 * An application context Java configuration class. The usage of Java configuration
12 * requires Spring Framework 3.0 or higher with following exceptions:
13 * <ul>
14 *     <li>@EnableWebMvc annotation requires Spring Framework 3.1</li>
15 * </ul>
16 * @author Petri Kainulainen
17 */
18@Configuration
19@ComponentScan(basePackages = {"net.petrikainulainen.spring.restful.controller"})
20@EnableWebMvc
21@ImportResource("classpath:applicationContext.xml")
22public class ApplicationContext {
23
24    private static final String VIEW_RESOLVER_PREFIX = "/WEB-INF/jsp/";
25    private static final String VIEW_RESOLVER_SUFFIX = ".jsp";
26
27    @Bean
28    public ViewResolver viewResolver() {
29        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
30
31        viewResolver.setViewClass(JstlView.class);
32        viewResolver.setPrefix(VIEW_RESOLVER_PREFIX);
33        viewResolver.setSuffix(VIEW_RESOLVER_SUFFIX);
34
35        return viewResolver;
36    }
37}

Configuring the Web Application and the Dispatcher Servlet

Second, you must configure your web application and map the dispatcher servlet to url pattern ’/’. This example configures the web application by using Java configuration which was introduced by the Servlet 3.0 API. However, it should be fairly easy to create a web.xml configuration file based on this example if you cannot use Spring Framework 3.1 and Servlet 3.0. Configuring a web application by using Java is easy. All you have to do is to implement the WebApplicationInitializer interface. My implementation of that interface is described in following:

 1import org.springframework.web.WebApplicationInitializer;
 2import org.springframework.web.context.ContextLoaderListener;
 3import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
 4import org.springframework.web.servlet.DispatcherServlet;
 5
 6import javax.servlet.*;
 7
 8/**
 9 * Web application Java configuration class. The usage of web application
10 * initializer requires Spring Framework 3.1 and Servlet 3.0.
11 * @author Petri Kainulainen
12 */
13public class RestfulInitializer implements WebApplicationInitializer {
14
15    private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
16    private static final String DISPATCHER_SERVLET_MAPPING = "/";
17
18    @Override
19    public void onStartup(ServletContext servletContext) throws ServletException {
20        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
21        rootContext.register(ApplicationContext.class);
22
23        ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, new DispatcherServlet(rootContext));
24        dispatcher.setLoadOnStartup(1);
25        dispatcher.addMapping(DISPATCHER_SERVLET_MAPPING);
26
27        servletContext.addListener(new ContextLoaderListener(rootContext));
28    }
29}

The End

I have now described to you how you can configure your web application to use RESTful url addresses. This solution seems pretty clean but for some reason I was unable to get it to work with Jetty 8.1.0.RC0. This seems pretty weird to me because the mvc:default-servlet-handler Subsection of Spring Framework 3.1 reference documentation states that:

The caveat to overriding the “/” Servlet mapping is that the RequestDispatcher for the default Servlet must be retrieved by name rather than by path. The DefaultServletHttpRequestHandler will attempt to auto-detect the default Servlet for the container at startup time, using a list of known names for most of the major Servlet containers (including Tomcat, Jetty, Glassfish, JBoss, Resin, WebLogic, and WebSphere).

Since I was able to run my example application without any problems with Tomcat 7.0.23, I am wondering if the problem is somehow related to my configuration. At the moment I am suspecting that the problem is related to the default servlet name of Jetty 8.1.0.RC0 because the Spring Framework’s reference documentation also states that:

If the default Servlet has been custom configured with a different name, or if a different Servlet container is being used where the default Servlet name is unknown, then the default Servlet’s name must be explicitly provided

I decided to publish blog entry anyway because I feel that this might be valuable to someone. I had also a selfish motive since I love to use Jetty during development phase and I am hoping that someone can help to find a solution to my problem. I am going to offer you one in the next part of this series but I am not totally satisfied with it. It just does not feel right.

P.S. I have also created an example application which you can use to test the advice given in this blog entry. The source of this application is available at GitHub. If you have any advice concerning the problem I am having with Jetty 8.1.0.RC0, I be would interested to hear it out.