Spring MVC: XML Responses in your Rest API

Sometimes you still need to return XML in your Rest API for various reasons. When you build your API with Spring Boot and Spring MVC, it is a simple, easy task.

You have two options. Both have in common that we must declare in a first step that our REST service shall return XML. So, let's start with that.

Common Controller Setup

Your controller class must either be annotated with @RestController or with @Controller and @ResponseBody on the method returning the XML.

Next, we must declare on the @RequestMapping annotation that out endpoint response will be in XML. It is done by setting the mime type aka media type of the produces parameter. The MediaType class contains a list of common types.

@RequestMapping(value = "/{id}", produces = { MediaType.APPLICATION_XML_VALUE })
public CommentDTO getComment(@PathVariable(value = "id") String commentId) throws IOException {
    return service.get(commentId);
}

Now our Controller is ready, and we can configure Spring MVC how to transform our return object to XML.

1. Using Jackson

Spring MVC uses the Jackson library by default for JSON responses. When we add the Jackson Extension jackson-dataformat-xml to the classpath, Spring MVC will automatically pick this up and use for XML responses.

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

You can customize the response with the standard Jackson annotations and a few specific ones.

Also, if you are worried about performance, you can add a faster StAX implementation like woodstox.

<dependency>
    <groupId>org.codehaus.woodstox</groupId>
    <artifactId>woodstox-core-asl</artifactId>
</dependency>

2. Using JAXB

If the Jackson XML extension is not available in the classpath Spring MVC will use JAXB for the transformation. However, to make this working, we must annotate our response object with the @XmlRootElement annotation.

@XmlRootElement
public class CommentDTO {
    private String id;
}

Returning JSON and XML

Sometimes we want to support JSON and XML responses on the same endpoint and method implementations. For that, we only need to add a second MediaType to the produces parameter like:

@RequestMapping(value = "/{id}", produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE  })
public CommentDTO getComment(@PathVariable(value = "id") String commentId) throws IOException {
    return service.get(commentId);
}

Now the client must send in the Accept header the content type it wants to receive.

Accept: application/xml

If the client does not send a Accept header, Spring MVC will fall back to the configured default content type. You can change it like:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
  @Override
  public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.defaultContentType(MediaType.APPLICATION_XML);
  }
}

For more information on content negotiation in Sping MVC, check out this article.