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.
Related
This question already has answers here:
Spring MVC 415 Unsupported Media Type
(8 answers)
Closed 5 years ago.
I am new to spring,I have tried with different ways to get the solution,
I have to use #RequestBody to get the json data which coming from jQuery.
I read the spring doc but i didn't find any thing clear.reg what jar need to add and how to map in xml file.
I tried
headers={"Accept=application/json"}
produces="application/json", consumes = "application/json"
consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE
application/x-www-form-urlencoded
MappingJacksonHttpMessageConverter(but i didn't want to used because i think its springBoot class)
#RequestMapping(method = RequestMethod.PUT) headers = "Accept=application/json"
UserController.java
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.evon.model.user.UserModel;
#Controller
public class UserController {
#RequestMapping(value = "/register",method = RequestMethod.POST)
public void handleXMLPostRequest (#RequestBody UserModel user) {
System.out.println(user);
System.out.println(user.getUserId());
System.out.println(user.getEmailId());
System.out.println(user.getPassword());
}
}
UserModel.java
public class UserModel implements Serializable
{
private Integer userId;
private String emailId;
private String password;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>withDiffServletName</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>demo</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>demo</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/demo-servlet.xml</param-value>
</context-param>
<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener </listener-class>
</listener>
</web-app>
demo-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:context = "http://www.springframework.org/schema/context"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation = "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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package = "com.evon.model.controller,com.evon.model.user" />
<context:annotation-config/>
<mvc:annotation-driven />
</beans>
index.jsp
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript">
//Ajax submit create user
function ajaxSubmitCreateUserForm() {
alert("==ajaxSubmitCreateUserForm");
try{
$.ajax({
beforeSend: function(xhrObj){
xhrObj.setRequestHeader("Content-Type","application/json");
xhrObj.setRequestHeader("Accept","application/json");
},
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
type: "POST",
url : 'register',
data: JSON.stringify({
userId : "101",
password : "password",
emailId : "ankit.bhimjiyani#gmail.com"
}),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(json){
console.log(json);
},
error : function() {
alert('System error occured, please try again ...');
}
});
}catch (e) {
alert(e)
}}
</script>
<div class="buttonBlock">
<button class="submitBTN" onclick="ajaxSubmitCreateUserForm();">Submit</button>
</div>
directory Structure
Can you try adding a return type for your controller and annotate your method as #ResponseBody. I think the issue is kainly because jquery is expecting a response back from the server and you are not sending it. Can you please try that.
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.5'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.7.5'
compile 'com.fasterxml.jackson.core:jackson-core:2.7.5' include this jars in classpath
you have to use produces and consumes into RequestMapping. you can refer bellow code:
#RestController
#RequestMapping("/city")
public class CityController {
private static final Logger logger = LoggerFactory.getLogger(CityController.class);
#Autowired(required = true)
private CityService cityService;
#RequestMapping(method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
public RestResponse save(#RequestBody CityView cityView) {
}
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.)
I am using spring mvc 3.2.4 and jquery 1.9.0 for long polling. My application is deployed on Tomcat 7.0.42. My spring configuration files are as below:
Application Web.xml
<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"
version="3.0">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/app-servlet.xml
</param-value>
</context-param>
</web-app>
Spring Configration xml as:-
<?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:p="http://www.springframework.org/schema/p"
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-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:annotation-config/>
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<context:component-scan base-package="com.webchat"/>
<bean id="defferedResult" class="com.exp.DeferredResultContainer"></bean>
</beans>
Controller for Posting data looks as
#RequestMapping(value = "/postComment", method = RequestMethod.POST)
public #ResponseBody String postComment(HttpServletRequest request) {
deferredResultContainer.updateAllResults(request.getParameter("comment"));
return "success";
}
Deferred Result container class
public class DeferredResultContainer {
private final Set<DeferredResult<String>> deferredResults = Collections.synchronizedSet(new HashSet<DeferredResult<String>>() );
public void put(DeferredResult<String> deferredResult){
deferredResults.add(deferredResult);
}
public void updateAllResults(String value){
for (DeferredResult<String> deferredResult : deferredResults){
deferredResult.setResult(value);
}
}
public void remove(DeferredResult<String> deferredResult){
deferredResults.remove(deferredResult);
}
public int determineSize(){
return deferredResults.size();
}
}
Controller for Deferred Result looks as
#RequestMapping(value = "/getComments", method = RequestMethod.GET)
#ResponseBody
public DeferredResult<String> getComments() throws Exception{
final DeferredResult<String> deferredResult= new DeferredResult<String>();
deferredResultContainer.put(deferredResult);
deferredResult.onTimeout(new Runnable() {
#Override public void run() {
deferredResultContainer.remove(deferredResult);
}
});
deferredResult.onCompletion(new Runnable() {
#Override public void run() {
deferredResultContainer.remove(deferredResult);
}
});
return deferredResult;
}
When I am trying to long poll it through ajax i am getting following response :-
{"setOrExpired":false}
And onCompletion method is also not getting executed.
To Simply things below controller gives perfect response as
{"1":"2"}
#RequestMapping(value = "/test1", method = RequestMethod.GET)
#ResponseBody
public Map test1() throws Exception{
Map m1 = new HashMap<String, Object>();
m1.put("1", "2");
return m1;
}
Once i change it to below and add Deferred result i get response as
{"setOrExpired":true}
#RequestMapping(value = "/test", method = RequestMethod.GET)
#ResponseBody
public DeferredResult<Map> test() throws Exception{
DeferredResult<Map> result = new DeferredResult<Map>();
Map m1 = new HashMap<String, Object>();
m1.put("1", "2");
result.setResult(m1);
return result;
}
Polling code
$(document).ready(function() {
longPoll();
function longPoll(){
$.support.cors = true;
var path = "http://localhost:8080/WebChatExp/rest";
$.ajax({
url: path + "/getComments",
cache:false,
success: function(data){
//To Do
alert("Data" + JSON.stringify(data));
},
error: function(err, status, errorThrown ) {
},
type: "GET",
dataType: "json",
complete: longPoll,
timeout: 60000 // timeout every one minute
});
}
I have searched various examples but cannot figure out if any extra configuration is required for deferred result. Please advise.
The response body you are getting
{"setOrExpired":true}
indicates that Spring serialized your DeferredResult (which has various properties including setOrExpired) to JSON instead of handling it with a DeferredResultMethodReturnValueHandler. In other words, it used another HandlerMethodReturnValueHandler, most likely RequestResponseBodyMethodProcessor (which handles #ResponseBody), to handle the value returned from your #RequestMapping annotated handler method. (The simplest way to test this is to see what happens when you remove the #ResponseBody annotation.)
Looking at the 3.2.x source code of RequestMappingHandlerAdapter, which registers the default HandlerMethodReturnValueHandler instances, the DeferredResultMethodReturnValueHandler is registered before RequestResponseBodyMethodProcessor and therefore will handle the DeferredResult return value first.
Since you're seeing different behavior, we must assume your configuration is not what you've shown here. (Note that <mvc:annotation-driven/> registers a RequestMappingHandlerAdapter.)
Also note that you are currently loading the configuration in /WEB-INF/app-servlet.xml twice, once by the ContextLoaderListener and once by the DispatcherServlet.
Get rid of your ContextLoaderListener and the corresponding context-param entirely. They are not needed in your example.
I know is impossible to be the problem in this case (spring mvc 3.2.4) but just for future references:
I get the same issue with spring boot 2.2.0.BUILD-SNAPSHOT (spring 5.1.5).
This error happens when you try to return DeferredResult using webflux instead of the traditional spring mvc app. Remember, in the new webflux api you should use mono/flux, not DeferredResult.
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.
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>