I have a simple REST controller written in a Spring-boot application but I am not sure how to implement the content negotiation to make it return JSON or XML based on the Content-Type parameter in the request header. Could someone explain to me, what am I doing wrong?
Controller method:
@RequestMapping(value = "/message", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE }) public Message getMessageXML(@RequestParam("text") String text) throws Exception { Message message = new Message(); message.setDate(new Date()); message.setName("Test"); message.setAge(99); message.setMessage(text); return message; }
I always get JSON when calling this method (even if I specify the Content-Type
to be application/xml
or text/xml
).
When I implement two methods each with different mapping and different content type, I am able to get XML from the xml one but it does not work if I specify two mediaTypes in a single method (like the provided example).
What I would like is to call the \message
endpoint and receive
Any help is appreciated.
EDIT: I updated my controller to accept all media types
@RequestMapping(value = "/message", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE }, consumes = MediaType.ALL_VALUE) public Message getMessageXML(@RequestParam("text") String text) throws Exception { Message message = new Message(); message.setDate(new Date()); message.setName("Vladimir"); message.setAge(35); message.setMessage(text); return message; }
Content Negotiation helps the Consumer and Provider interact about the data exchange format. In this article, we will expose both XML and JSON representations.
Spring soon introduced the Content Negotiation strategy, where we can use the traditional RESTful @ResponseBody approach and HTTP message converters, to return desired outputs in JSON or XML, along with some flexibility and dynamicity it provides with the configuration.
Web API uses the best of the ASP.NET MVC architecture and improves it in two main areas. First, it introduces a new logical layer known as content negotiation with a standard set of rules to request data in a given format, whether JSON, XML or some other format.
In Spring REST APIs, Spring uses 'application/json' as a default media type. That is why, a REST controller can consume or produce JSON format payloads without having to specify the media types explicitly. Thus, in order to consume or produce data in a different form, the controller needs to specify that explicitly.
You can use ContentNegotiationConfigurer
Firstly, you should override the configureContentNegotiation
method in your configuration class:
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false). favorParameter(true). defaultContentType(MediaType.APPLICATION_JSON). mediaType("xml", MediaType.APPLICATION_XML); } }
favorParameter(true)
- enabling favoring path expressions over parameter or accept headers.
defaultContentType(MediaType.APPLICATION_JSON)
- sets the default content type. this means that if you don't pass a path expression then Spring will generate JSON as response.
mediaType("xml", MediaType.APPLICATION_XML)
- sets the path expression key for XML.
Now if you declare your Controller like:
@Controller class AccountController { @RequestMapping(value="/accounts", method=RequestMethod.GET) @ResponseStatus(HttpStatus.OK) public @ResponseBody List<Account> list(Model model, Principal principal) { return accountManager.getAccounts(principal) ); } }
and call it something like localhost:8080/app/accounts.json
, then Spring will generate JSON as response. So if you call localhost:8080/app/accounts.xml
you will receive XML response
You can find more info about this here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With