Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring boot controller content negotiation

Tags:

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

  • XML when the Content-Type of the GET request is set to application/xml
  • JSON when the Content-Type is application/json

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;   } 
like image 411
Smajl Avatar asked Oct 08 '15 07:10

Smajl


People also ask

What is Content Negotiation in spring boot?

Content Negotiation helps the Consumer and Provider interact about the data exchange format. In this article, we will expose both XML and JSON representations.

What is Content Negotiation strategy?

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.

Does MVC support Content Negotiation?

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.

How do I use MediaType in spring boot?

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.


1 Answers

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.

like image 197
Artur Boruński Avatar answered Jan 17 '23 17:01

Artur Boruński