I want to send JSON from my controller. I have the following configuration.
spring-servlet.xml :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven/>
<mvc:resources mapping="/resources/**" location="/resources/"/>
<context:component-scan base-package="com.castle.controllers"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
.js :
function testAjax() {
var data = {userName: "MyUsername", password:"Password"};
$.ajax({
url: 'ajax/test.htm',
dataType : 'json',
type : 'POST',
contentType: "application/json",
data: JSON.stringify(data),
success: function(response){
alert('Load was performed.');
}
});
}
UserTest.java:
public class UserTest {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
TestAjaxController.java :
@Controller
@RequestMapping("/ajax")
public class TestAjaxController {
@RequestMapping(method = RequestMethod.POST, value = "/test.htm")
public @ResponseBody
UserTest testAjaxRequest(@RequestBody UserTest user) {
return user;
}
}
pom.xml :
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
When i do this request, i get in my Controller JSON represented as UserTest object. But on return :
HTTP Status 406 - The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.
What i'm doing wrong? I know, there is a lot of questions about such cases, but i can't fix it for 2 days...
UPDATE
I Have found the solution!!
It's only need to return an Object. Not a User object or something.
But
return Object;
public @ResponseBody Object testAjaxRequest(@RequestBody UserTest user) {
List<UserTest> list = new ArrayList<>();
list.add(user);
list.add(user);
list.add(user);
return list;
The main issue here is that the path "/test.htm"
is going to use content negotiation first before checking the value of an Accept
header. With an extension like *.htm
, Spring will use a org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategy
and resolve that the acceptable media type to return is text/html
which does not match what MappingJacksonHttpMessageConverter
produces, ie. application/json
and therefore a 406 is returned.
The simple solution is to change the path to something like /test
, in which content negotiation based on the path won't resolve any content type for the response. Instead, a different ContentNegotiationStrategy
based on headers will resolve the value of the Accept
header.
The complicated solution is to change the order of the ContentNegotiationStrategy
objects registered with the RequestResponseBodyMethodProcessor
which handles your @ResponseBody
.
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