Registered converters
When accessing to Restful services,
the Spring class RestTemplate maintains a list of message converters that will
use to marshal objects into the request body, or unmarshalling them from the
response. When instantiating the RestTemplate class, it automatically fills a
list with several converters:
- ByteArrayHttpMessageConverter
- StringHttpMessageConverter
- ResourceHttpMessageConverter
- SourceHttpMessageConverter
- AllEncompassingFormHttpMessageConverter
The RestTemplate class may register
additional converters if it finds the required classes on the classpath:
- JAXB
converter: Converts xml using JAXB2. The Binder class must be found on the
classpath. If you are using Java 6, it is no longer necessary as it already
comes with the JDK. If you are using Java 5, add the following dependencies:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2</version>
</dependency>
- Jackson
converter: Converts Objects from/to JSON. ObjectMapper and JsonGenerator must
exist on the classpath.
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.4.2</version>
</dependency>
- Atom
and RSS feeds converters. The WireFeed class must be present on the classpath.
Serving different content
The following controller will
execute three different operations that will generate xml, String and json
content:
@RequestMapping(value="/users/{userId}",
method=RequestMethod.GET)
public @ResponseBody User getUser(@PathVariable("userId") long id) {
return userRepository.getUser(id);
}
Result: JSON. The User class can be serialized/deserialized by the Jackson object mapper.
@RequestMapping(value="/usernames/{userId}",
method=RequestMethod.GET)
public @ResponseBody String getUsername(@PathVariable("userId") long id) {
StringBuilder
result = new StringBuilder();
User
user = userRepository.getUser(id);
return
result.append(user.getName()).append(" ").append(user.getSurname()).toString();
}
Result: String. The returned object is a String.
@RequestMapping(value="/cars/{carId}",
method=RequestMethod.GET)
public @ResponseBody Car getCar(@PathVariable("carId") long id) {
return carRepository.getCar(id);
}
Result: XML. The Car class is annotated with @XmlRootElement
You can also specify the converters
that will be used by the RestTemplate. You could, for example, only instantiate
the needed converters or register your own message converter:
private RestTemplate restTemplate = new RestTemplate();
@Before
public void setup() {
List<HttpMessageConverter<?>>
converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(new
StringHttpMessageConverter());
converters.add(new
Jaxb2RootElementHttpMessageConverter());
converters.add(new
MappingJacksonHttpMessageConverter());
restTemplate.setMessageConverters(converters);
}
Just take into account that if you
serve both json and xml content, you must add the jaxb2 converter before the
json converter. Otherwise, regardless of the presence of xml annotations, the
xml method response will be handled by the jackson converter and be converted
to json. That happens because the HttpEntityRequestCallback inner class of the
RestTemplate will use the first converter that can write/read the content.
You can get the source code from
Github.
Labels: MVC, REST, Spring