7

I want to make a POST request through AJAX, and I also want to bind the whole class object to the request, and I want to receive that request with @requestParam annotation. I know it can be done with @requestBody annotation, but I am curious to know: can we do it with @requestParam annotation?

An Ajax code:

var restDTO{
    id: 3,
    name: "hello"
}

 $.ajax({
          url: url, 
          type: 'POST',
          dataType: 'json',
          contentType: 'application/json',
          mimeType: 'application/json',
          data: JSON.stringify({RestDTO : restDTO}),          
          success: function(data) 
    {
    }

I do have RestDTO

Class RestDTO 
{

    int id;
    String name;

    //getter and setter

}

In controller

public String content(@RequestParam RestDTO restDTO){...}

What should I do the make this code run?

What should I change in sending data from ajax?

Do I need to change on server to receive an RestDto object with @requestParam annotation?

nbro
  • 15,395
  • 32
  • 113
  • 196
user3029929
  • 471
  • 2
  • 7
  • 20

3 Answers3

19

You can't, because @RequestParam just indicates, that one method's parameter should be bound to a one web request's parameter. It can't do mapping to objects. For use @RequestParam you should change ajax request:

var restDTO{
   id: 3,
   name: "hello"
}

 $.ajax({
          url: url, 
          type: 'POST',
          data: restDTO,          
          success: function(data){
             ....
          }
});

JQuery will send request as application/x-www-form-urlencoded and will process data to parameters automatically. You controller's method should look like following:

@RequestMapping("/url")
public String content(@RequestParam Long id, @RequestParam String name){...}

For automatically map parameters to object you can use @ModelAttribute annotation:

@RequestMapping("/url")
public String content(@ModelAttribute RestDTO restDTO){...}

In this case, names in javascript map should match to names of properties in RestDTO.

Generally, @ModelAttribute and @RequestBody created for same purposes: for binding data from request to method (whether objects of primitive type).

I consider, that @ModelAttribute is more convenient, when you working with html-forms and plain objects. There is ready to use Spring abilities like modelAttribute and path.

In its turn, @RequestBody more flexible, when you need manual control over data. Also, it is more convenient, when you're working with complex objects.

Personally me would prefer @RequestBody and json.

Ken Bekov
  • 13,696
  • 3
  • 36
  • 44
  • Thanks for your description, I tried it and i got to know: 1. RequestBody + json. 2. ModelAttribute + application/x-www-form-urlencoded but in the end, i could not found any difference from it... I mean where to use when ?? javascript map should match to names of properties in both case – user3029929 Mar 15 '16 at 07:27
  • @user3029929 You're right, this approaches need for same things. But, in my point of view, `ModelAttribute` very useful only when you working with web-forms, in other cases `RequestBody` more convenient. – Ken Bekov Mar 15 '16 at 09:03
  • 1
    `@ModelAttribute` takes an object from or adds an object to the model. It has nothing to do with binding whatsoever. – a better oliver Mar 15 '16 at 18:50
  • @zeroflagL, hmmm. Did you ever read this documentation: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-method-args ? Can you explain me, what does next phrase mean: `...Once present in the model, the argument’s fields should be populated from all request parameters that have matching names. This is known as data binding in Spring MVC...`? Don't you know why, according to this doc `BindingResult` should stay right after `@ModelAttribute` param? It would be curious to see your explanation. – Ken Bekov Mar 16 '16 at 03:13
  • 1
    Binding happens with or without `@ModelAttribute`. That's the default behavior for posted forms. You deliberately omitted the relevant part of the documentation, the two sentences before: _"An @ModelAttribute on a method argument indicates the argument should be retrieved from the model. If not present in the model, the argument should be instantiated first and then added to the model."_. This, and only this, is the purpose of `@ModelAttribute`. – a better oliver Mar 16 '16 at 08:45
10

If you're sending your data as classic request params, you can bind to object by simply omitting the @RequestParam, so

public String content(RestDTO restDTO){...}

If you're sending json, you have to use @RequestBody.

If whysoever you're insisting on the @RequestParam, note that you can bind multiple values against a map, so

public String content(@RequestParam Map<String, String> restDTO){...}

From the @RequestParam doc

If the method parameter is Map or MultiValueMap and a parameter name is not specified, then the map parameter is populated with all request parameter names and values.

Master Slave
  • 27,771
  • 4
  • 57
  • 55
5

In spring web you have these annotations:

RequestParam - used for get params (/path?name=)

PathVariable - used for path params (/path/{name})

RequestBody - used for post/put/patch etc. body

RequestHeader - for headers

So you can't use RequestParam for post params, doesn't matter if json or not

Alexandru Godri
  • 528
  • 3
  • 7