Keywords: Spring Framework | JSON Serialization | HTTP 406 Error | Content Negotiation | Jackson Libraries
Abstract: This article provides a comprehensive analysis of the root causes behind 406 errors in Spring JSON requests, explaining the HTTP Accept header negotiation mechanism and Spring's HTTPMessageConverter workflow. Through complete code examples and configuration instructions, it demonstrates how to properly configure Jackson libraries and <mvc:annotation-driven> to resolve content negotiation issues and ensure correct JSON responses to clients.
Problem Background and Phenomenon Analysis
During Spring Web application development, it's common to encounter situations where clients request JSON data but the server returns a 406 error. This error indicates that the server cannot generate responses that meet the client's Accept header requirements. From the provided case, although Hibernate queries execute normally and return data, the Spring framework encounters issues during the content negotiation phase.
HTTP 406 Error Mechanism Analysis
HTTP status code 406 represents "Not Acceptable," which is an important component of the HTTP protocol's content negotiation mechanism. When a client specifies the Accept field in the request header, the server needs to check whether it can generate responses conforming to these media types. If the server cannot provide any of the media types specified in the Accept header, it must return a 406 error.
In the case study, the request header shows:
Accept: application/json, text/javascript, */*; q=0.01
This indicates that the client primarily expects to receive JSON-formatted responses, but the server cannot fulfill this requirement.
Spring Content Negotiation Mechanism
The Spring framework handles request and response content conversion through the HTTPMessageConverter system. When controller methods use the @ResponseBody annotation, Spring selects the appropriate MessageConverter based on the request's Accept header to serialize the return object.
Analysis of missing critical configuration:
<context:annotation-config />
<tx:annotation-driven />
This configuration enables annotation-driven context and transaction management but lacks the crucial <mvc:annotation-driven> configuration, which is responsible for registering default HTTPMessageConverters.
Solution Implementation
To resolve the 406 error, it's essential to ensure that Spring can properly handle JSON serialization. Here's the complete solution:
First, add to the Spring configuration file:
<mvc:annotation-driven />
This configuration automatically registers HTTPMessageConverters based on classpath detection, including JSON converters.
Second, ensure the project contains the correct Jackson library dependencies. For different Jackson versions:
Traditional Jackson libraries (org.codehaus.jackson):
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
New Jackson libraries (com.fasterxml.jackson):
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.1.1</version>
</dependency>
Controller Optimization Recommendations
Original controller code:
@RequestMapping(value="/getTemperature/{id}", headers="Accept=*/*", method = RequestMethod.GET)
@ResponseBody
public Weather getTemparature(@PathVariable("id") Integer id){
Weather weather = weatherService.getCurrentWeather(id);
return weather;
}
The headers="Accept=*/*" parameter can be removed since Spring's content negotiation mechanism automatically handles Accept headers:
@RequestMapping(value="/getTemperature/{id}", method = RequestMethod.GET)
@ResponseBody
public Weather getTemperature(@PathVariable("id") Integer id){
return weatherService.getCurrentWeather(id);
}
Verification and Testing
After configuration, verify the solution through the following steps:
1. Restart the application server to ensure configuration takes effect
2. Use browser developer tools to inspect network requests
3. Confirm the response header contains: Content-Type: application/json
4. Verify the response body contains correct JSON data
Summary and Best Practices
406 errors in the Spring framework typically stem from content negotiation configuration issues. By properly configuring <mvc:annotation-driven> and ensuring Jackson libraries are in the classpath, most JSON serialization problems can be resolved. It's recommended to configure these foundational components early in the project to avoid encountering similar issues during later development stages.
Additionally, maintaining compatibility between dependency library versions is crucial, especially when upgrading Spring versions, requiring corresponding adjustments to Jackson library versions to ensure proper functionality.