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:
- Configure the location of static resources such as css files.
- Ensure that static resources are served by the container’s default servlet
- 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):
<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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<!--
Configures the location of static resources such as css files.
Requires Spring Framework 3.0 or higher.
-->
<mvc:resources mapping="/static/**" location="/static/"/>
<!--
Ensures that dispatcher servlet can be mapped to '/' and that static resources
are still served by the containers default servlet. Requires Spring Framework
3.0 or higher.
-->
<mvc:default-servlet-handler/>
</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:
* An application context Java configuration class. The usage of Java configuration
* requires Spring Framework 3.0 or higher with following exceptions:
* <ul>
* <li>@EnableWebMvc annotation requires Spring Framework 3.1</li>
* </ul>
* @author Petri Kainulainen
*/
@Configuration
@ComponentScan(basePackages = {"net.petrikainulainen.spring.restful.controller"})
@EnableWebMvc
@ImportResource("classpath:applicationContext.xml")
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 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:
* 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 = "/";
@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);
servletContext.addListener(new ContextLoaderListener(rootContext));
}
}
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.



{ 4 comments… read them below or add one }
Just one small suggestion. You don’t actually need to use the MVC namespace (i.e. mvc:resources, etc.). Since you’re already using the MVC Java config you can configure your resource paths and the default servlet handling in Java config like it’s done here:
https://github.com/SpringSource/spring-test-mvc/blob/master/src/test/java/org/springframework/test/web/server/samples/context/WebConfig.java
As for Jetty you haven’t mentioned any details on what the exact problem you see is. Have you tried specifying the name of the default servlet?
Thanks for the tip! That is very useful since I am not anymore a fan of XML configuration files. My problem with Jetty Maven Plugin 8.1.0.RC2 (It does not work this version either) is that when I start the web application and write the url localhost:8080 to my browser, it shows a list of files instead of the home page. I presume that this means that the request is handled by the default servlet of Jetty instead of the dispatcher servlet. I have planned to test this with standalone Jetty but I have not got time to do it yet. I did try to change the name of the default servlet to ‘default’ but this did not help. Anyway, I think that I will try running the web application with standalone Jetty and see how it goes.
I ran into this Stackoverflow question: http://stackoverflow.com/questions/8066943/spring-3-1-servlet-3-code-based-configuration-using-the-jetty-maven-plugin I have to test this approach on the weekend. Maybe it will solve my problem.
I managed to solve my problem. The solution was to download the Jetty 8.1.0.RC (The download is available here: http://download.eclipse.org/jetty/8.1.0.RC2/dist/) and follow the instructions found from that Stackoverflow question.