Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@RequestBody Sent Through Spring MVC JSON Jackson Processor

I have read some many similiar problems inlcluding: JQuery, Spring MVC @RequestBody and JSON - making it work together JSON request with JQuery/Ajax with Spring

The requirement is that the server will only accept application/json types. I am using a Spring MVC Controller. The code sends a response back as JSON through @ResponseBody. I want to get information through the @RequestBody in my Spring MVC Controller. I am using JSP to send JSON to Spring MVC Controller. My code and Spring MVC can be seen below:

I am new to JSON and Javascript.

JSP - index.jsp

<%@page language="java" contentType="text/html"%> 
<html> 
<head> 
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>   
<script type="text/javascript"> 
$('#myForm').on('submit', function(e) {  
var frm = $("#myForm"); 
var dat = JSON.stringify(frm.serializeArray());  

 $.ajax({  
 type: 'POST',  
 url: $('#myForm').attr('action'),  
 data: dat, 
 contentType: 'application/json', 
 dataType: 'json', 
 error: function() { 
    alert('failure'); 
 } 
 success: function(hxr) {  
     alert("Success: " + xhr);  
 } 
  });  
);  
   };  
</script>  
</head> 
<body> 
<h2>Application</h2> 
<form id="myForm" action="/application/save" method="POST" accept="application/json" onclick="i()"> 
<input type="text" name="userId" value="User"> 
<input type="submit" value="Submit"> 
</form> 
</body> 
</html> 

When running this I am not getting any output. In the Chrome I get 404 Not found error and in Tomcat I get the following error:

org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver                        handleNoSuchRequestHandlingMethod 
WARNING: No matching handler method found for servlet request: path '/application/sa 
 ve', method 'POST', parameters map['userId' -> array<String>['User']] 

Is something wrong here in the JSP part?

web.xml

<?xml version="1.0" encoding="UTF-8"?>  
<web-app 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_5.xsd" 
 version="2.5"> 

 <display-name>WebApp</display-name> 

 <context-param> 
    <!-- Specifies the list of Spring Configuration files in comma separated format.--> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/spring/service.xml</param-value> 
 </context-param> 

 <listener> 
    <!-- Loads your Configuration Files--> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
 </listener> 

 <servlet> 
    <servlet-name>application</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
 </servlet> 

 <servlet-mapping> 
    <servlet-name>application</servlet-name> 
    <url-pattern>/</url-pattern> 
 </servlet-mapping> 

 <welcome-file-list> 
    <welcome-file>index.jsp</welcome-file> 
 </welcome-file-list>     
</web-app> 

service.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:util="http://www.springframework.org/schema/util" 
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 
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"> 

<context:component-scan base-package="com.web"/> 

<mvc:annotation-driven/> 

<context:annotation-config/> 

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/> 

<bean id="jacksonMessageChanger" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
    <property name="supportedMediaTypes" value="application/json"/> 
</bean> 

<!-- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="messageConverters"> 
        <list> 
            <ref bean="jacksonMessageChanger"/> 
        </list> 
    </property> 
</bean>--> 

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="messageConverters"> 
        <util:list id="beanList"> 
            <ref bean="jacksonMessageChanger"/> 
        </util:list> 
    </property> 
</bean> 

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="prefix" value="/WEB-INF/jsp/"/> 
    <property name="suffix" value=".jsp"/> 
</bean> 

<!-- <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> 
    <property name="mediaTypes"> 
        <map> 
            <entry key="json" value="application/json"/> 
        </map> 
    </property> 
</bean>-->   

Controller

package com.web; 

import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RequestBody; 
import com.webchannel.domain.User; 
import com.webchannel.domain.UserResponse; 

@Controller 
@RequestMapping("/application/*") 
public class SaveController { 

 @RequestMapping(value = "save", method = RequestMethod.POST, headers = {"content-type=application/json"}) 
 public @ResponseBody UserResponse save(@RequestBody User user) throws Exception { 
  UserResponse userResponse = new UserResponse(); 
 System.out.println("UserId :" + " " + user.getUserId()); 
 return userResponse; 
} 

@RequestMapping(value = "delete", method = RequestMethod.GET) 
public @ResponseBody UserResponse delete() { 
   System.out.println("Delete"); 
   UserResponse userResponse = new UserResponse(); 
   userResponse.setSuccess(true); 
   userResponse.setVersionNumber("1.0"); 
   return userResponse; 

} }

When invoking /application/delete I get JSON returned. So I know my JacksonProcessor is configured correctly. The problem is in @RequestBody.

Where am I going wrong?

If I remove the headers in the code below I get a 415 error.

@RequestMapping(value = "save", method = RequestMethod.POST) 
 public @ResponseBody UserResponse save(@RequestBody User user) throws Exception { 
  UserResponse userResponse = new UserResponse(); 
 System.out.println("UserId :" + " " + user.getUserId()); 
 return userResponse; 
} 

I am almost close but help would be appreciated.

like image 719
user1646481 Avatar asked Sep 18 '12 11:09

user1646481


1 Answers

I tried to play around a little more with your code however was unable to get the same error as you are getting. I've reworked the HTML:

<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>

<script type="text/javascript"> 

    $(function() { 
        $('#myForm').submit(function() {
            var form = $( this ),
                url = form.attr('action'),
                userId = form.find('input[name="userId"]').val(),
                dat = JSON.stringify({ "userId" : userId });

            $.ajax({
                url : url,
                type : "POST",
                traditional : true,
                contentType : "application/json",
                dataType : "json",
                data : dat,
                success : function (response) {
                    alert('success ' + response);
                },
                error : function (response) {
                    alert('error ' + response);
                },
            });

            return false;
        });
    });

</script>
</head>
<body>
    <h2>Application</h2>
    <form id="myForm" action="application/save">
        <input type="text" name="userId" value="User">
        <input type="submit" value="Submit">
    </form>
</body>
</html>

I had a very simple method similar to yours:

@RequestMapping(value = "save", method = RequestMethod.POST, headers = {"content-type=application/json"})
public @ResponseBody String save (@RequestBody User user) throws Exception
{
    return "save-test";
}

My User class looks like this:

public class User
{
    private String userId;

    public User()
    {
    }

    public String getUserId ()
    {
        return userId;
    }

    public void setUserId (String userId)
    {
        this.userId = userId;
    }
}

My spring config was stripped down to contain:

<context:component-scan base-package="com.web"/> 
<mvc:annotation-driven/> 
<context:annotation-config/> 

I'm using spring version 3.1.1 and jquery 1.8.1 (the latest I believe). I'm not getting the same error as you so perhaps you can try some of what I've done and see if that helps.

like image 109
ramsinb Avatar answered Oct 13 '22 01:10

ramsinb