views:

105

answers:

2

I've read through all of the Spring 3 Web docs: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/spring-web.html but have been completely unable to find any interesting documentation on binding more complicated request data, for example, let's say I use jQuery to post to a controller like so:

$.ajax({
    url: 'controllerMethod',
    type: "POST",
    data : {
        people : [
        {
            name:"dave", 
            age:"15"
        } ,
{
            name:"pete", 
            age:"12"
        } ,
{
            name:"steve", 
            age:"24"
        } ]
    },
    success: function(data) {
        alert('done');
    }
});

How can I accept that through the controller? Preferably without having to create a custom object, I'd rather just be able to use simple data-types, however if I need custom objects to make things simpler, I'm fine with that too.

To get you started:

@RequestMapping("/controllerMethod", method=RequestMethod.POST)
public String doSomething() {
    System.out.println( wantToSeeListOfPeople );
}

Don't worry about the response for this question, all I care about is handling the request, I know how to deal with the responses.

EDIT:

I've got more sample code, but I can't get it to work, what am I missing here?

select javascript:

var person = new Object();
    person.name = "john smith";
    person.age = 27;

    var jsonPerson = JSON.stringify(person);

    $.ajax({
        url: "test/serialize",
        type : "POST",
        processData: false,
        contentType : 'application/json',
        data: jsonPerson,
        success: function(data) {
            alert('success with data : ' + data);
        },
        error : function(data) {
            alert('an error occurred : ' + data);
        }
    });

controller method:

public static class Person {

        public Person() {
        }

        public Person(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
        String name;
        Integer age;

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    @RequestMapping(value = "/serialize")
        @ResponseBody
        public String doSerialize(@RequestBody Person body) {
            System.out.println("body : " + body);
            return body.toString();
        }

this renders the following exception:

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json' not supported

If the doSerialize() method takes a String as opposed to a Person, the request is successful, but the String is empty

+1  A: 

if you have <mvc:annotation-driven> enabled then:

@RequestMapping("/controllerMethod", method=RequestMethod.POST)
public String doSomething(@RequestBody List<Person> people) {
    System.out.println( wantToSeeListOfPeople );
}

(List<Person> might not be the structure you would like to obtain, it's just an example here)

You can try setting the Content-Type of $.ajax to be application/json, if it doesn't work immediately.

Bozho
I like this answer, unfortunately I get an exception "org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded' not supported" this is the closest to what I'd like, but the code doesn't work as is
walnutmon
@walnutmon see muy update.
Bozho
@Bozho: jQuery doesn't serialize to JSON anyway. Manual serialization needed, for example, `JSON.stringify` from http://json.org
axtavt
@axtavt - he is sending JSON as `data` of his request. Or I'm missing something..
Bozho
@Bozho: If he sends an object as `data`, jQuery uses the following serialization: http://api.jquery.com/jQuery.param/. To use JSON he need to convert object to JSON string representation manually and pass the string as `data`.
axtavt
@Bozho: I added the "application/json" as a test, it still says "unsupported media type", do I need to have a JSON parser configured in Spring to do this? I would really like to get things working this way, whether or not I send as JSON or as a serialized form
walnutmon
+2  A: 

Your jQuery ajax call produces the following application/x-www-form-urlencoded request body (in %-decoded form):

people[0][name]=dave&people[0][age]=15&people[1][name]=pete&people[1][age]=12&people[2][name]=steve&people[2][age]=24

Spring MVC can bind properties indexed with numbers to Lists and properties indexed with strings to Maps. You need the custom object here because @RequestParam doesn't support complex types. So, you have:

public class People {
    private List<HashMap<String, String>> people;

    ... getters, setters ...
}

@RequestMapping("/controllerMethod", method=RequestMethod.POST)        
public String doSomething(People people) {        
    ...
} 

You can also serialize data into JSON before sending them and then use a @RequestBody, as Bozho suggests. You may find an example of this approach in the mvc-showcase sample.

axtavt
this works, it seems that if Spring can handle this, it should be able to go straight to the HashMap, skip that middle man, but your code works exactly as printed
walnutmon
@axtavt: I added an edit to the top that is attempting the JSON solution, it doesn't work though, any insight?
walnutmon
@walnutmon: To make it work you need to have Jackson JSON Mapper library (http://jackson.codehaus.org/) on the classpath (as well as `<mvc:annotation-driven/>` in Spring's XML).
axtavt
@axtavt: I added jackson-rs and the asl-mapper and core, also added <mvc:annotation-driven/>, I still see the exact same thing, I have no clue why this is completely undocumented (the spring example I've seen has always had the same problem when I try to run it)
walnutmon
@walnutmon: Then I don't know. For me it works fine.
axtavt