Spring boot controller content negotiation

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.


You can find some hints in the blog post @RequestMapping with Produces and Consumes at point 6.

Pay attention to the section about Content-Type and Accept headers:

@RequestMapping with Produces and Consumes: We can use header Content-Type and Accept to find out request contents and what is the mime message it wants in response. For clarity, @RequestMapping provides produces and consumes variables where we can specify the request content-type for which method will be invoked and the response content type. For example:

@RequestMapping(value="/method6", produces={"application/json","application/xml"}, consumes="text/html")
@ResponseBody
public String method6(){
    return "method6";
}

Above method can consume message only with Content-Type as text/html and is able to produce messages of type application/json and application/xml.

You can also try this different approach (using ResponseEntity object) that allows you to find out the incoming message type and produce the corresponding message (also exploiting the @ResponseBody annotation)