Thursday 22 March 2012

RestTemplate and Spring MVC

This post is a follow up to the Spring MVC and RESTful Web Services post and shows a simple example of using Spring's RestTemplate class for client side access to, in this case, the Spring MVC RESTful web service built in the aforementioned post.

The RestTemplate class is, as it's javadoc describes, "the central class for client-side HTTP access. It simplifies communication with HTTP servers, and enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs (with possible template variables) and extract results."

In this example, we'll only be using the GET HTTP method (as that is all we have on our MVC example!) but the idea will be pretty much the same for other methods.

First, the Spring config and the XML below lists three beans. The Jaxb2Marshaller bean lists the classes that the JAXBContext needs to be aware of. This bean is then in turn injected into the MarshallingHttpMessageConverter as the marshaller and unmarshaller so Objects can be converted to and from an XML Stream. (Note that by default the MarshallingHttpMessageConverter supports text/xml and application/xml.) For this example, the message converter is the only entry in the list set on the RestTemplate bean. Finally, the RestTemplate bean is injected into the ExampleControllerClient bean.


<beans xmlns="http://www.springframework.org/schema/beans"
 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.xsd">

 <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
  <property name="classesToBeBound">
   <list>
    <value>com.city81.spring.mvc.rest.domain.Message</value>
   </list>
  </property>
 </bean>

 <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">    
  <property name="messageConverters">    
   <list>      
    <bean id="messageConverter"            
     class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">        
     <property name="marshaller" ref="jaxbMarshaller" />        
     <property name="unmarshaller" ref="jaxbMarshaller" />    
    </bean>    
   </list>    
  </property>  
 </bean>

 <bean id="exampleControllerClient" class="com.city81.spring.mvc.rest.ExampleControllerClient">
  <constructor-arg ref="restTemplate" />
 </bean>

</beans> 


The ExampleControllerClient class below shows how simple it is to make a RESTful web service call:

package com.city81.spring.mvc.rest;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.client.RestTemplate;
import com.city81.spring.mvc.rest.domain.Message;

public class ExampleControllerClient {

 private RestTemplate restTemplate;

 public ExampleControllerClient(RestTemplate restTemplate) {
  this.restTemplate = restTemplate;
 }

 public void getMessage() {

  Message message = restTemplate.getForObject(
   "http://localhost:8080/spring-rest-0.0.1-SNAPSHOT/example/controller/message", 
   Message.class); 
  System.out.println(message.getMessageString());
 }

 public static void main(String[] args) {

  ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
          new String[] {"applicationContext.xml"});
  BeanFactory factory = (BeanFactory) appContext;
  ExampleControllerClient client = (ExampleControllerClient) factory
    .getBean("exampleControllerClient");
  client.getMessage();

 }

}


The getForObject method takes a URL and the type of the response object and retrieves a representation by doing a GET on the URL arg. This method is overloaded and can be used for different URLs. For example, if there are URI templates in the URL, then these can be populated by a third arg of a Map containing a collection of name value pairs or by using varargs.


public  T getForObject(String url,
                          Class responseType,
                          Object... urlVariables)
               throws RestClientException

public  T getForObject(String url,
                          Class responseType,
                          Map urlVariables)
               throws RestClientException


Back to the example and when the getForObject call is invoked, the JAXB marshaller behind the scenes will convert the XML into a Message object. An alternative to using the Jaxb2Marshaller  is the XStreamMarshaller. To swap JAXB for XStream would just be a Spring XML change as shown below:


<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">    
   <property name="aliases">    
    <props>      
     <prop key="message">com.city81.spring.mvc.rest.domain.Message</prop>    
    </props>    
   </property>  
  </bean>

...
     <property name="marshaller" ref="xstreamMarshaller" />        
     <property name="unmarshaller" ref="xstreamMarshaller" /> 
...


There are many different marshallers to achieve the same goal, and indeed many different media types with different marshallers. This post barely scratches the surface but just shows how simple it is to create client side code for calling a RESTful web service.