Content Negotiation in Spring MVC — Accept and Content-Type Headers
Fast recall
Quick revision
Core answer
Understanding of HTTP content negotiation mechanism and how Spring MVC implements it
Confusing Content-Type (request body format) with Accept (desired response format) or thinking Spring always returns JSON automatically
Explain both directions: Accept controls response format, Content-Type describes request body format, and show how Spring uses HttpMessageConverter to bridge them
Interview-ready guide
Interview answer
A client can send JSON and request XML in the same call: Content-Type: application/json describes the incoming body, while Accept: application/xml describes the preferred response. Spring first selects a matching handler, then chooses an HttpMessageConverter that can write the return value in an acceptable type. If the application has a JSON converter only, an XML-only Accept header cannot be satisfied. Calling this an agreement about all data exchanged hides the important request/response distinction.
Content Negotiation in Spring MVC — Accept and Content-Type Headers
Direct Answer
In Spring MVC, content negotiation selects a representation for the response, usually from the request's Accept header, the mapping's produces condition, and available HttpMessageConverters. Request Content-Type is a separate concern: it describes the body the client sent and is matched by consumes. The server does not have to support every format requested by the client.
Code Example
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@GetMapping("/{id}")
public Order getOrder(@PathVariable Long id) {
// Client sends Accept: application/json → Jackson converts Order to JSON
// Client sends Accept: application/xml → JAXB converts Order to XML
return new Order(id, "Laptop", 1299.99);
}
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Order> createOrder(@RequestBody Order order) {
// Content-Type: application/json tells Spring to use Jackson to parse body
var saved = orderService.save(order);
return ResponseEntity.status(HttpStatus.CREATED).body(saved);
}
}
record Order(Long id, String item, Double price) {}
Common Mistakes & Pitfalls
- Mixing up Accept and Content-Type: Freshers often think Content-Type controls both request and response. Accept is what the client wants back; Content-Type describes what the client is sending. Sending Accept: application/xml but reading Content-Type in code leads to bugs.
- Assuming JSON is always default: If Jackson isn't on the classpath or no converter is registered, Spring won't return JSON. You'll get 406 errors. Always check spring-boot-starter-web includes Jackson.
- Ignoring 406 responses: When you see 406 Not Acceptable in Postman, it means the Accept header doesn't match any produces value. Freshers debug the controller logic instead of checking the HTTP headers first.
Check your understanding
Answer these without looking back at the article.
- What is the difference between Accept and Content-Type headers?
- What status code does Spring return if it can't produce the requested Accept type?
- How do you add XML support to a Spring Boot REST API?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.