JSON response from SpringMVC controller is not working - java

I want to response JSON object or array from Spring MVC controller. From these two beingjavaguys and mkyoung tutorial, i tried.
I could success only in when the response is string. But when the response is in object or in list, it doesn't work for me.
//It works
#RequestMapping(value = "/angular", method = RequestMethod.GET)
public #ResponseBody String getAllProfiles( ModelMap model ) {
String jsonData = "[{\"firstname\":\"ajitesh\",\"lastname\":\"kumar\",\"address\":\"211/20-B,mgstreet\",\"city\":\"hyderabad\",\"phone\":\"999-888-6666\"},{\"firstname\":\"nidhi\",\"lastname\":\"rai\",\"address\":\"201,mgstreet\",\"city\":\"hyderabad\",\"phone\":\"999-876-5432\"}]";
return jsonData;
}
Output is:
But the problem is in it,
#RequestMapping(value = "mkyoung", method = RequestMethod.GET)
public #ResponseBody Shop getShopInJSON() {
Shop shop = new Shop();
shop.setName("G");
shop.setStaffName(new String[] { "mkyong1", "mkyong2" });
return shop;
}
It shows,
HTTP ERROR 406
Problem accessing /mkyoung.html. Reason:
Not Acceptable
But if i change it toString() ,
It works but not with right output
#RequestMapping(value = "mkyoung", method = RequestMethod.GET)
public #ResponseBody String getShopInJSON() {
Shop shop = new Shop();
shop.setName("G");
shop.setStaffName(new String[] { "mkyong1", "mkyong2" });
return shop.toString();
}
But i need JSON object or array of object as response. What is the probelm ? I have added jsckson dependency in my pom.xml
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.10</version>
</dependency>
UPDATE:
Now i am sending request from angular js by adding
headers: {
"Content-Type": "application/json"
}
My dispatcher-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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.sublime.np.controller" />
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/defs/general.xml</value>
</list>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.tiles3.TilesView" />
</bean>
</beans>
As Sotirios Delimanolis's Answer suggesion.
$http({
url: '/mkyoung.html',
method: 'GET',
data: id,
headers: {
"Content-Type": "application/json"
}
}).success(function(response){
$scope.response = response;
console.log($scope.response);
/* $scope.hideTable = false;
$scope.hideButton = false ; */
}).error(function(error){
$scope.response = error;
console.log("Failed");
});
But it shows same error.

Also add jackson core
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>2.5.1</version>
</dependency>
For List use method return type Object
#RequestMapping(value = "mkyoung", method = RequestMethod.GET)
public #ResponseBody Object getShopInJSON() {
Shop shop = new Shop();
shop.setName("G");
shop.setStaffName(new String[] { "mkyong1", "mkyong2" });
Shop shop1 = new Shop();
shop1.setName("G1");
shop1.setStaffName(new String[] { "mkyong1", "mkyong2" });
List<Shop> shops = new ArrayList<Shop>();
shops.add(shop1);
shops.add(shop);
return shops;
}

Given #ResponseBody with a POJO type return type, a default MVC configuration with #EnableWebMvc or <mvc:annotation-driven />, and Jackson on the classpath, Spring will try to serialize the POJO to JSON and write it to the response body.
Since it's writing JSON, it's going to attempt to write application/json as the Content-type header. The HTTP specification requires that the server only responds with content types that are part of the Accept header in the request.
It seems you're sending your request with an inappropriate Accept header that doesn't contain application/json. Fix that.
Note that you are sending your request to
/mkyoung.html
Spring, by default, uses content negotiation based on some extensions. For example, with .html, Spring will think the request should produces text/html content, which is contrary to the application/json you want to send.
Since your handler is already mapped to
#RequestMapping(value = "/mkyoung", method = RequestMethod.GET)
just send the request to the corresponding URL, ending in /mkyoung. (Get rid of the .html extension.)

Related

Springboot: redirect and reverse-proxy

I'm having a SpringBoot and SpringMVC internal application (internal meaning hidden from the internet by a firewall) and a public authentication (OAuth2) service in the DMZ.
I'm accessing the landing page from the from a client in the internal area.
This page has a login button. When I press it, I'm forwarding the client to the auth server (in the DMZ), that I can access only going through a proxy.
I tried setting the VM env variables:
-Dhttp.proxyHost=xx -Dhttp.proxyPort=yy -Dhttp.proxySet=true
and setting them in the System.properties
System.setProperty("http.proxyHost", "http://xx");
System.setProperty("http.proxyPort", "xx");
System.setProperty("http.nonProxyHosts", "localhost|127.0.0.1");
but both with no effect.
I also tried to define a SimpleClientHttpRequestFactory bean :
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="requestFactory"
class="org.springframework.http.client.SimpleClientHttpRequestFactory">
<property name="proxy">
<bean id="proxy" class="java.net.Proxy">
<constructor-arg>
<util:constant static-field="java.net.Proxy.Type.HTTP" />
</constructor-arg>
<constructor-arg>
<bean class="java.net.InetSocketAddress">
<constructor-arg value="xx" />
<constructor-arg value="yy" />
</bean>
</constructor-arg>
</bean>
</property>
</bean>
</beans>
without anymore success.
Question
How can I configure Spring to proxify my redirect ?
Thanks!
Got it work as follow (see restTemplateProxy)
private final String server = "xx";
private final int port = yy;
private final SimpleClientHttpRequestFactory clientHttpReq = new SimpleClientHttpRequestFactory();
private final Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(server, port));
private RestTemplate restTemplateProxy = null;
{
clientHttpReq.setProxy(proxy);
restTemplateProxy = new RestTemplate(clientHttpReq);
}
#RequestMapping(value = "getLightToken", method = RequestMethod.GET)
private String getLightToken(Model model) throws JsonProcessingException, IOException {
/* Header */
headers.clear();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
/* Body */
MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();
body.add(CLIENT_ID.key, CLIENT_ID.val);
body.add(CLIENT_SECRET.key, CLIENT_SECRET.val);
body.add(GRANT_TYPE.key, GRANT_TYPE.val);
body.add(SCOPE.key, SCOPE.val);
/* Set the body and header of the request */
HttpEntity<?> request = new HttpEntity<>(body, headers);
/* Request Authorisation */
ResponseEntity<String> response = restTemplateProxy.exchange(BASE_URL + TOKEN_URI, HttpMethod.POST, request, String.class);
return response.getBody();
}

Spring MVC request with null response in Json to Java object conversion

My ajax request in spring mvc
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/json2/20150503/json2.js"></script>
<script>
$(document).ready(function(){
var producer = "producer";
var model = "model";
var price = "1";
var ResponseModel = {};
ResponseModel.producer=producer;
ResponseModel.model=model;
ResponseModel.price=price;
$.ajax({
url : '/ajaxtest',
data: JSON.stringify({"editUserRequest":ResponseModel}),
type: "POST",
async: true,
beforeSend: function(xhr) {
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
},
success : function(data) {
alert("success");
console.log(data);
},
error:function(data) {
alert("errorxxx");
console.log(data);
}
});
});
</script>
Model
#JsonSerialize
public class ResponseModel implements Serializable {
public ResponseModel(){}
public String getProducer() {
return producer;
}
public void setProducer(String producer) {
this.producer = producer;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
private String producer;
private String model;
private String price;
}
and spring MVC controller
#Controller
#RequestMapping("/")
public class HelloController {
#RequestMapping(method = RequestMethod.GET)
public String printWelcome(ModelMap model) {
model.addAttribute("message", "Hello world!");
return "hello";
}
//#ModelAttribute(value="editUserRequest")
#RequestMapping(value = "/ajaxtest", method = RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
String getTime(#ModelAttribute(value="editUserRequest") ResponseModel editUserRequest,HttpServletRequest request,HttpServletResponse response) {
String result = editUserRequest.getModel()+editUserRequest.getPrice()+editUserRequest.getProducer();
//String result = "editUserRequest";
//System.out.println("Debug Message from CrunchifySpringAjaxJQuery Controller.." + new Date().toString());
return result;
}
}
web.xml is
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring MVC Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
and dispatcher servlets is
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.springapp.mvc"/>
<context:annotation-config />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
after sending ajax request in firebug it shows null result by post is done successfully by lands in ajax error .
I have pom.xml with <jackson.version>2.6.3</jackson.version>
<!-- Need this for json to/from object -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
But can not use it map in Spring MVC 4 json to java object. How to solve it??
Ok I have replicated your issue in my machine. To send the data from ajax call to spring mvc in the form of an object, you need to make few changes to the ajax call and you need to change the #ModelAttribute to #RequestBody. See below the updated code
$(document).ready(function(){
var producer = "producer";
var model = "model";
var price = "1";
var editUserRequest = new Object();
editUserRequest.producer=producer;
editUserRequest.model=model;
editUserRequest.price=price;
$.ajax({
url : 'ajaxtest',
data: JSON.stringify(editUserRequest),
type: "POST",
contentType : 'application/json; charset=utf-8',
dataType : 'json',
success : function(data) {
alert("success");
console.log(data);
},
error:function(data) {
alert("errorxxx");
console.log(data);
}
});
});
The Spring Controller method
#RequestMapping(value = "ajaxtest", method = RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
ResponseModel getTime(#RequestBody ResponseModel editUserRequest) {
String result = editUserRequest.getModel()+editUserRequest.getPrice()+editUserRequest.getProducer();
//String result = "editUserRequest";
//System.out.println("Debug Message from CrunchifySpringAjaxJQuery Controller.." + new Date().toString());
return editUserRequest;
}
Since in the ajax call you are expecting a JSON response and you are returning a plain String from spring controller. It goes to error handler in ajax call. I have changed the response type of spring controller method to ResponseModel so that the response will be in JSON format and in the ajax call the control goes to success handler.

SpringMVC 3.2.4 Request method 'PUT' not supported

Just started working with Java and Spring, coming from a C# background and I am having trouble getting a 'PUT' request to work.
I am on Spring 3.2.4 running on Jetty 9.0.6.
I have a simple controller with the following method
#RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public ResponseEntity<String> update(#PathVariable Integer id, #RequestBody Employee employee) {
HttpHeaders headers = new HttpHeaders();
headers.set("content-location", "/api/employees/" + id);
return new ResponseEntity<>("", headers, HttpStatus.OK);
}
When this request is executed, I get the following error:
Oct 31, 2013 10:16:16 AM org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver handleHttpRequestMethodNotSupported
WARNING: Request method 'PUT' not supported
If I change the RequestMethod to 'POST' it works fine.
Does Spring support 'PUT' requests? How do I get it to recognize the 'PUT'
Joe
EDIT
Turns out I was being stupid. Affe clued me in when he mentioned the url.
I was accessing it like 'api/employees?id=32' when it should have been 'api/employees/32'
In the hopes this helps someone else, here is the web descriptor, the servlet and the controller.
Web Descriptor
<web-app xmlns='http://java.sun.com/xml/ns/javaee'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:schemaLocation='http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd'
version='3.0'>
<display-name>timesheet-app</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
MVC-Dispatcher-Servlet
<?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:context='http://www.springframework.org/schema/context'
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation='http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd'>
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package='org.timesheets.web' />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
<bean class='org.springframework.web.servlet.view.InternalResourceViewResolver'>
<property name='prefix' value='/WEB-INF/views/' />
<property name='suffix' value='.jsp' />
</bean>
</beans>
Controller
#Controller
#RequestMapping("/api/employees")
public class EmployeeController {
#RequestMapping(method = RequestMethod.GET)
public #ResponseBody List<Employee> get() {
List<Employee> employees = new ArrayList<>();
for(int i = 1; i <= 10; i++){
employees.add(new Employee(i, "Test " + i, "Department " + i));
}
return employees;
}
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public #ResponseBody Employee get(#PathVariable Integer id) {
return new Employee(1, "Test", "IT");
}
#RequestMapping(method = RequestMethod.POST)
public ResponseEntity<String> create(#RequestBody Employee employee) {
HttpHeaders headers = new HttpHeaders();
headers.set("content-location", "/api/employees/32");
return new ResponseEntity<>("", headers, HttpStatus.CREATED);
}
#RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public ResponseEntity<String> update(#PathVariable Integer id, #RequestBody Employee employee) {
HttpHeaders headers = new HttpHeaders();
headers.set("content-location", "/api/employees/" + id);
return new ResponseEntity<>("", headers, HttpStatus.OK);
}
}
The problem was as #Affe pointed out that it could not find the url in the mapping because I was requesting the wrong url!
I was accessing the url like '/api/employees?id=32' instead of '/api/employees/32', though I would have thought the parameter binding would still pick it up.

Getting 415 Unsupported Media Type Error when trying to return a view from a spring controller using an Ajax Request

I have two controller methods
#RequestMapping(value = "/link", method = RequestMethod.GET)
public ModelAndView link(HttpServletRequest httpRequest, #RequestParam(value="name", required=false) String name, #RequestParam(value="id", required=false) String id, #RequestParam(value="type") String type) {
ModelAndView mav=new ModelAndView("ViewPage");
SearchRequest request = new SearchRequest();
request.setName(name);
request.setId(id);
request.setType(type);
mav.addObject("Request", request);
}
#RequestMapping(value="/find", headers="Accept=/", method=RequestMethod.POST)
public #ResponseBody List find(HttpServletRequest httpRequest, #RequestBody SearchRequest searchRequest) {
}
From the 1st controller method link, the control will be passed to ViewPage.jsp, we will pass a ModelView Object to ViewPage.jsp. And the control should again go to find method.
$(document).ready(function(){
var myJSON = {name:"test", id:"test", type:"test"};
myJSON = JSON.stringify(myJSON);
$.ajax({
type: "POST",
url: "../find",
dataType:'JSON',
data: myJSON,
cache: false,
success: function(data){
if(data!=""){
}
)}
}
I am getting below error
"NetworkError: 415 Unsupported Media Type - localhost:8080/myreport/find"
In your Spring XML config, you need to specify the media types that are supported like so...
<beans:property name="mediaTypes">
<beans:map>
<beans:entry key="html" value="text/html" />
<beans:entry key="json" value="application/json" />
</beans:map>
</beans:property>
In order to get JSON working in your Spring MVC application the first thing you need to do is to add these dependencies:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.1.2</version>
<scope>compile</scope>
</dependency>
These dependencies are needed for Spring to managed JSON requests and responses.
Next thing is to define media types by registering ContentNegotiationManagerFactoryBean:
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false"/>
<property name="favorParameter" value="true"/>
<property name="mediaTypes">
<value>
json=application/json
xml=application/xml
</value>
</property>
</bean>
Also you have to define this negotiation manager in your mvc:annotation-driven tag's attribute content-negotiation-manager:
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jsonObjectMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
And create your JSON object mapper or use default. I prefer creating my own so that I can managed the configuration I need. For e.g.:
public class JsonObjectMapper extends ObjectMapper {
public JsonObjectMapper() {
super();
this.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
this.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
}
Declare it in Spring context:
<bean id="jsonObjectMapper" class="somepackage.JsonObjectMapper"/>
And then your javascript should look something like this:
$(document).ready(function(){
var obj = {};
obj.name = "test";
obj.id = "test";
obj.type = "test";
var request = {};
request.SearchRequest = obj;
$.ajax({
url: "${pageContext.servletContext.contextPath}/find",
type: 'POST',
dataType: 'json',
data: JSON.stringify(request),
contentType: 'application/json'
}).success(
function (data) {
//do something with response
});
});
This should work if I haven't forgotten something else. Hope this helps.

Using ResponseBody annotation in Spring for returning a Json not working

I am working on a spring mvc web application, in which I am using Google Visualization API for generating some charts. I have a model class which contains 2 arraylists, which represent the data that I`m sending to the function that draws the chart (this is what i want to be converted to a JSON).
The model class:
#Component
public class JsonResponse {
private List<Integer> percentages = new ArrayList<Integer>();
private List<String> topics = new ArrayList<String>();
public JsonResponse(){
}
public List<Integer> getPercentages() {
return percentages;
}
public void setPercentages(List<Integer> percentages) {
this.percentages = percentages;
}
public List<String> getTopics() {
return topics;
}
public void setTopics(List<String> topics) {
this.topics = topics;
}
}
Then Ive got a#Component` annotated class which contains a method that returns a model object (of the class that I wrote above), with the 2 arraylists attributes populated.
#Component
public class ChartUtils {
#Autowired
public JsonResponse response;
public JsonResponse listPieChartData( ModelAndView model ,int waveId ){
//arraylists for chart generation
List<Integer> percentages = new ArrayList<Integer>();
List<String> topics = new ArrayList<String>();
{... code for accessing the DB and processing some data and then populating the 2
arraylists ... }
response.setTopics(topics);
response.setPercentages(percentages);
return response;}
}
So the Controller class, the one that has the mapping for the action that I am calling to gather data for the chart generation and in which I am calling listPieChartData method, from the class above, and in which I'm also using the #ResponseBody annotation is this:
#Controller
public class ChartController {
#Autowired
public ChartUtils utils;
#Autowired
public JsonResponse response;
#RequestMapping(value = "/drawPieChart", method = RequestMethod.GET )
#ResponseBody
public JsonResponse drawPieChart( ModelAndView model,
#RequestParam(value = "id", defaultValue = "-1") int waveId ) {
return utils.listPieChartData(model,waveId ); }
The JavaScript function that draws the chart :
function drawColumnChart(percentages, topics , div,width,height) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Wave');
for (var i=0; i < topics.length; i++){
data.addColumn( 'number', topics[i] );
}
data.addRow( percentages );
var wave=percentages[0];
var options = {
'title':'Generated Chart For '+wave,
'backgroundColor': { fill: "none" },
'is3D': true,
'width':width,
'height':height,
};
var chart = new google.visualization.ColumnChart(document.getElementById(div));
chart.draw(data, options);
}
And the AJAX call to the controller's mapped method (for gathering data) that finally calls the above JS function to obtain the chart (I'm also sending the request param int id for the controller method , I didn't wrote that)
$("#button").live("click", function(){
var arrayP, arrayT;
$.ajax({
url: "drawPieChart",
contentType: "application/json",
data: params,
success: function(data) {
$.each(data, function(messageIndex, message) {
if (messageIndex === 0) {
arrayP = message;
} else {
arrayT = message;
}
});
drawPieChart(arrayP, arrayT,'chart_div',600,400);
}
});
});
I know this is a lot of code :) but it's pretty simple code, to understand the flow better, here is how it`s working:
From a button input I'm calling, with AJAX, the mapped method to the drawPieChart action (which is in the ChartController class), this methods sends the response through invoking the listPieChart method (from the ChartUtils class), which returns a JsonResponse object, (which contains 2 arraylists). This JsonResponse should be converted to a JSON, because in the AJAX request, I'm telling that the request needs a JSON input (via contentType: "application/json"), and it should get it because I use #ResponseBody in the controller method mapped for this request.
I`m getting this response:
The resource identified by this request is only capable of generating
responses with characteristics not acceptable according to the request
"accept" headers ().
(HTTP Status 406)
Please correct me where I'm wrong, I just can't get this working and I can't figure out why...
And my servlet-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up
static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.bla.bla" />
<beans:import resource="classpath:springJDBC.xml" />
</beans:beans>
So the problem was that i didn'd have all the Jackson dependencies declared in pom.xml.
These are the dependencies for your maven project in case you want Spring 3 to automatically serialize an object for you , using the #ResponseBody annotation , as a response from a method.
Noob stuff , but I didn't saw this mentioned in the examples that I found .
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.9</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.9</version>
</dependency>
Also , I had to change some stuff in the ajax call for invoking the method that is returning the json object with data for the chart generation :
$("#buttonPieGenerate").live("click", function(){
$.ajax({
url: "drawPieChart", //method from controller
contentType: "application/json",
data: params,
success: function(data) {
drawPieChart(data.percentages, data.topics,'chart_div',600,400);
}
});
});
I'm accessing the data in the Json object that I`m getting as a response from the call with data.percentages , data.topics .
A small update for the world of 2015:
<dependency>
<!-- Just placing this on the classpath will enable JSON for #ResponseBody -->
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>

Categories

Resources