I am using spring mvc 4 and trying to return a simple map
to ajax - from my controller to jsp file.
The controller:
@RequestMapping(value = "/ajaxtest", method = RequestMethod.GET)
public @ResponseBody
Map<String, String> myTest() {
System.out.println("------------------------------------test");
Map<String,String> myMap = new HashMap<String, String>();
myMap.put("a", "1");
myMap.put("b", "2");
return myMap;
}
Ajax from the jsp file:
function testAjax() {
$.ajax({
url : '../../ajaxtest.html',
dataType: "json",
contentType: "application/json;charset=utf-8",
success : function(data) {
alert("1");
alert(data);
}
});
}
But I am not getting any alert but just the error HTTP/1.1 406 Not Acceptable
.
However, changing the code to return a simple string works fine. Controller:
@RequestMapping(value = "/ajaxtest", method = RequestMethod.GET)
public @ResponseBody
String myTest() {
System.out.println("------------------------------------test");
return "hello";
}
Ajax:
function testAjax() {
$.ajax({
url : '../../ajaxtest.html',
success : function(data) {
alert("1");
alert(data);
}
});
}
Alerting 1
and hello
from ajax as expected.
I added the jackson jar files as expected (by pom.xml):
dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.5.1</version>
</dependency>
Am I missing something? I just want to return a simple mapping structure (or other class structure in the future).
Update:
From spring console (Don't sure it's related):
Resolving exception from handler [null]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
Thanks in advance! Mike
I don't know if it the correct way but I solved it as following.
In the controller, I converted the map to json:
@RequestMapping(value = "/ajaxtest", method = RequestMethod.GET)
public @ResponseBody
String myTest() {
System.out.println("------------------------------------random");
Map<String,String> myMap = new HashMap<String, String>();
myMap.put("a", "1");
myMap.put("b", "2");
ObjectMapper mapper = new ObjectMapper();
String json = "";
try {
json = mapper.writeValueAsString(myMap);
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return json;
}
and in the jsp:
function testAjax() {
$.ajax({
url : '../../ajaxtest.html',
type:"GET",
contentType: "application/json;charset=utf-8",
success : function(data) {
alert("1");
alert(data);
var obj = jQuery.parseJSON( data );
alert(obj.a);
alert(obj.b);
}
});
Thanks you all! Mike }
Your "problem" is due to your request ending in .html
. You need to add the following configuration to make it work as you expect
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="defaultContentType" value="application/json" />
</bean>
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
and than do as @StanislavL suggested add the produces={ "application/json"}
don't add the consumes cause your not posting any JSON
an explanation
When spring determines the representation to which it converts it first looks at the path part of the request (e.g. .html, .json, .xml), than it looks for a parameter explicitly setting the conversion representation, finally goes for an Accept header (the so call PPA strategy)
that is why your example works
function testAjax() {
$.ajax({
url : '../../ajaxtest.html',
success : function(data) {
alert("1");
alert(data);
}
});
}
you're getting HTML back. However with the request
function testAjax() {
$.ajax({
url : '../../ajaxtest.html',
dataType: "json",
contentType: "application/json;charset=utf-8",
success : function(data) {
alert("1");
alert(data);
}
});
}
you're explicitly saying that you expect JSON
back from the server, however, .html is hinting that it should be HTML
instead, and you end up in problems
To learn the details of the content negotiation strategy you should read this blog, its almost famous by now :) It will also show you the pure java config version
Try to add consumes="application/json"
and produces={ "application/json"}
to the @RequestMapping to let spring process your json
UPDATE 406 error description
HTTP Error 406 Not acceptable
Introduction
A client (e.g. your Web browser or our CheckUpDown robot) can indicate to the Web server (running the Web site) the characteristics of the data it will accept back from the Web server. This is done using 'accept headers' of the following types:
Accept: The MIME types accepted by the client. For example, a browser may only accept back types of data (HTML files, GIF files etc.) it knows how to process. Accept-Charset: The character sets accepted by the client. Accept-Encoding: The data encoding accepted by the client e.g. the file formats it understands. Accept-Language: The natural languages (English, German etc.) accepted by the client. Accept-Ranges: Whether the client accepts ranges of bytes from the resource i.e. a portion of the resource. If the Web server detects that the data it wants to return is not acceptable to the client, it returns a header containing the 406 error code.
It means you somehow should change your server logic to accept MIME/Charset/Encoding etc. of the request you sent from client. Can't say exactly what's wrong but try to play with headers and consumes of the RequestMapping.
Your Ajax call should something similar to:
$("#someId" ).click(function(){
$.ajax({
url:"getDetails",
type:"GET",
contentType: "application/json; charset=utf-8",
success: function(responseData){
console.log(JSON.stringify(responseData));
// Success Message Handler
},error:function(data,status,er) {
console.log(data)
alert("error: "+data+" status: "+status+" er:"+er);
}
});
});
Spring Controller Code should be as below :
@RequestMapping(value="/getDetails",method=RequestMethod.GET)
public @ResponseBody Map<String,String> showExecutiveSummar(){
Map<String,String> userDetails = new HashMap<String,String>();
userDetails .put("ID","a" );
userDetails .put("FirstName","b" );
userDetails .put("MiddleName","c" );
userDetails .put("LastName","d" );
userDetails .put("Gender","e" );
userDetails .put("DOB","f" );
return userDetails
}
You can also refer to this link for understanding the library which support this functionality.
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