Friday 27 January 2012

Spring MVC and RESTful Web Services

This post is a follow up to the Spring MVC Bare Essentials post and shows how a simple RESTful web service can be implemented using Spring MVC. It'll also show the different ways in which the controller services can be implemented and how the model can be rendered.

The post will use the same classes and XML files as in the Bare Essentials post but change them to make the methods expoed by the controller RESTful.

First of all, the ExampleController class will change to use web bind annotations which will mark the class and the methods within it with URL paths.

@Controller
@RequestMapping("/controller")
public class ExampleController {

    @RequestMapping(value="message", method=RequestMethod.GET)

    public ModelAndView getMessage() {
        Message message = new Message("Spring MVC Rest Example");
        ModelAndView modelAndView = new ModelAndView(
            "example", "message", message);
        return modelAndView;
    }

}


The web.xml below shows the changes to the servlet mapping tag and in particular the url-pattern. This means our URLs will be:

http://<ip>:<port>/<app name>/example/<request mapping>

<servlet-mapping>
    <servlet-name>springMVCRESTExample</servlet-name>
    <url-pattern>/example/*</url-pattern>
</servlet-mapping>


In the servlet's context XML file, we'll auto detect the ExampleController bean by using context:component-scan and then add the BeanNameViewResolver to interpret a view name as a bean name. Finally, add a MarshallingView which will use JAX-B to marshall and unmarshall the com.city81.spring.mvc.rest.domain.Message class.

<context:component-scan base-package="com.city81.spring.mvc.rest" /> 

<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />

<bean id="example" class="org.springframework.web.servlet.view.xml.MarshallingView">
    <constructor-arg>
        <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
            <property name="classesToBeBound">
                <list>
                    <value>com.city81.spring.mvc.rest.domain.Message</value>
                </list>
            </property>
        </bean>
    </constructor-arg>
</bean>


Building a WAR and deploying to a container such as Tomcat would then enable you call the getMessage method of the ExampleController class with the URL:

http://<ip>:<port>/<app name>/example/controller/message

An alternative to implementing the getMessage method is to use the @ModelAttribute instead the the ModelView class as shown below:

@RequestMapping(value = "message", method = RequestMethod.GET)
public @ModelAttribute("example") Message getMessage() {
    Message message = new Message("Spring MVC Rest Example");
    return message;
}


Another alternative is to use <mvc:annotation-driven /> which was introduced in Spring 3. By adding it to the servlet's context XML file (in place of the beans BeanNameViewResolver and MarshallingView), the getMessage method can then be implemented as show below:

@RequestMapping(value="message", method = RequestMethod.GET)
public @ResponseBody Message getMessage() {
    Message message = new Message("Spring MVC Rest Example");
    return message;
}


This is a very simple example that can be built upon to use different RESTful methods. There are also different ways in which XML can be rendered in the view and also different types that can be rendered eg text. It is also worth considering Spring Roo if wanting to implement a RESTful web service. These will hopefully be covered in further posts.