I released the intermediate package of my Test With Spring course. Take a look at the course >>

Creating RESTful Urls with Spring MVC 3.1 Part Two: Dispatcher Servlet Url Mappings

The first part of this series described how you can create RESTful urls with Spring MVC 3.1 and default-servlet-handler element of the MVC namespace. This blog entry will describe how you can use the dispatcher servlet url mappings for the same purpose. As you might remember from my previous blog entry, a RESTful url must fulfill these requirements:

  • 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 will give you a brief description of my idea next.

The Solution

As I mentioned to you before, you can use the dispatcher servlet url mappings for configuring your web application to use RESTful url addresses. This means that you must create section specific context path prefixes and map the dispatcher servlet to these url patterns. This idea might seem a bit confusing at first so I will provide an example which will hopefully explain this idea.

Lets assume that your web page has two sections: products and services. This would mean that you would map your dispatcher servlet to following url patterns: ‘/products/*’ and ‘/services/*’. This approach works rather well if the next part of the context path does not contain a path variable. Lets take a closer look of this in following:

  • Following context paths would not work: ‘/products/1’ and ‘/services/5’.
  • Following context paths would work: ‘/products/phones/1’ and ‘/services/training/1’.

The reason for this behavior is that the dispatcher servlet removes the url pattern from the beginning of the request’s context path and tries to look for a handler to the request by using the resulting string. (E.g. If you have mapped your dispatcher servlet to url pattern ‘/products/*’ and the context path of the incoming request is ‘/products/phones/1’, the dispatcher servlet is looking for a handler which request mapping matches with the string ‘/phones/1’). This naturally means that context paths like ‘/products/1’ and ‘/services/1’ will not work because the resulting request mapping is not “unique”.

Enough with the theory. The steps needed to create RESTful url addresses by using this technique are described next.

Required Steps

The steps needed to fulfill the given requirements are following:

  • Configuring the application context
  • Configuring the web application
  • Creating an index page

Each of these steps is described with more details in following.

Configuring the Application Context

First, you must configure your application context. I have a created a simple Java configuration class which is used to enable Spring MVC, set the component scan base package and configure the view resolver bean. The source code of the configuration class is given in following:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * An application context Java configuration class. The usage of Java configuration
 * requires Spring Framework 3.0 or higher.
 * @author Petri Kainulainen
 */
@Configuration
@ComponentScan(basePackages = {"net.petrikainulainen.spring.restful.controller"})
@EnableWebMvc
public class ApplicationContext {
    
    private static final String VIEW_RESOLVER_PREFIX = "/WEB-INF/jsp/";
    private static final String VIEW_RESOLVER_SUFFIX = ".jsp";
    
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix(VIEW_RESOLVER_PREFIX);
        viewResolver.setSuffix(VIEW_RESOLVER_SUFFIX);

        return viewResolver;
    }
}

Configuring the Web Application

Second, you must configure your web application. In this case the web application configuration consists of two phases:

  1. Configure the url mapping of the dispatcher servlet.
  2. Configure the welcome file of your application.

I decided to configure my web application by implementing the WebApplicationInitializer interface. My example adds dispatcher servlet url mappings for the home page, products section and services section of the web application. The source code of my implementation is given in following:

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.*;

/**
 * Web application Java configuration class. The usage of web application
 * initializer requires Spring Framework 3.1 and Servlet 3.0.
 * @author Petri Kainulainen
 */
public class RestfulInitializer implements WebApplicationInitializer {
    
    private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
    private static final String DISPATCHER_SERVLET_MAPPING_HOME = "/home";
    private static final String DISPATCHER_SERVLET_MAPPING_PRODUCTS = "/products/*";
    private static final String DISPATCHER_SERVLET_MAPPING_SERVICES = "/services/*";
    
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(ApplicationContext.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, new DispatcherServlet(rootContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping(DISPATCHER_SERVLET_MAPPING_HOME);
        dispatcher.addMapping(DISPATCHER_SERVLET_MAPPING_PRODUCTS);
        dispatcher.addMapping(DISPATCHER_SERVLET_MAPPING_SERVICES);

        servletContext.addListener(new ContextLoaderListener(rootContext));
    }
}

Since it is not yet possible to configure the welcome page of a web application by using Java configuration, I had to create a web.xml configuration file and configure the welcome file of my application in it. My web.xml file looks as follows:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
</web-app>

Creating an Index Page

Third, you must create an index page which redirects user to your home page. In my example, the url mapping of the home page is ‘/home’. I used the Meta Refresh Tag for this purpose. The source code of my welcome file is given in following:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta HTTP-EQUIV="REFRESH" content="0; url=/home">
    <title></title>
</head>
<body>
</body>
</html>

Final Thoughts

I have now described to you how you can use the dispatcher servlet url mappings for creating RESTful url addresses with Spring MVC. I am having some doubts about this approach for three reasons:

  • If new sections are added to your web application, you must always remember to add the correct mapping for the dispatcher servlet. This feels a bit cumbersome.
  • The actual url address of your home page is not invisible for the users of your application. I prefer url addresses like http://www.example.com over http://www.example.com/home. This might sound ridiculous but in some situations this is not acceptable.
  • The context path of your application must have more than one “level” because otherwise Spring cannot find the correct handler for the requests. This might not a problem in most cases but if it is, you cannot use the approach described in this blog entry.

If you are interested of playing around with my example application, you can get the source code from GitHub. The third and last part of this series will describe how you can create RESTful urls with Spring MVC and UrlrewriteFiter. Stay tuned.

About the Author

Petri Kainulainen is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.

About Petri Kainulainen →

6 comments… add one
  • thank you for this work, i am currently trying to code a embedded jetty application with a gwt module and spring, my problem is setting the “/” for the dispatch servlet so that post requests can pass thru to standard web.xml mapped servlets and currently they are hijacked by the spring dispatch servlet. I really appreciate the style of writing here, you have a great balance between code and description, a terse but complete description with simple but complete code. Thank you

    Reply
    • Thank you for your nice words. I really appreciate them. About your problem, were you able to solve you it by using this advice or do you need some help with it?

      This approach can solve it as long as you can set different urls for different servlets. This naturally mean that if you follow this path, all requests send to a specific url are always processed by the same servlet (the request method does not matter). Mapping urls manually like this can be a bit troublesome but in your case it seems justified.

      Anyway, if you need more help with this problem, let me know.

      Reply
  • Hello Petri!
    Do you know, how I can configure my servlets from Java, for communication with GWT?
    GWT is MVP-framework, without Controller. Communication with services provides by rpc-calls from GWT-module on client.

    I am using spring4gwt (http://spring4gwt.blogspot.ru/)
    I have this web.xml file:

    myproject

    org.springframework.web.context.ContextLoaderListener

    springGwtRemoteServiceServlet
    org.spring4gwt.server.SpringGwtRemoteServiceServlet

    springGwtRemoteServiceServlet
    /myproject/springGwtServices/*

    30

    myproject.html

    Thanks!

    Reply
    • Hi,

      Unfortunately I have never used GWT so I have no idea how this is done. I hope that you find a solution to this problem!

      Reply
      • good website ,Thanks so much

        Reply
        • You are welcome!

          Reply

Leave a Comment