Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using @RequestBody and @ModelAttribute together?

I'm trying to get at the body of a POST, and I'd like the parameters of my method to bind to an object.

Is this possible?

My current declaration doesn't ever get hit:

 @RequestMapping(method = RequestMethod.POST)
public void doStuff(@RequestBody byte[] bodyData, @ModelAttribute Form form, Model model ) {

Looks like I'm getting this exception:

- 2011-02-25 16:57:30,354 - ERROR - http-8080-3 - org.springframework.web.portle
t.DispatcherPortlet - Could not complete request
java.lang.UnsupportedOperationException: @RequestBody not supported
like image 534
Stefan Kendall Avatar asked Feb 25 '11 16:02

Stefan Kendall


1 Answers

For this to work correctly, you have to be sure you're using AnnotationMethodHandlerAdapter. This overrides HandlerMethodInvoker's createHttpInputMessage (which is throwing the exception you're seeing). (It does this in a private class.)

I believe you can just include the following in your *-servlet.xml

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

WARNING: The below answer is for the case of needing @RequestBody and @RequestParam in the same handler method. It does not answer this question, but could be of use to someone.

I've tested this out using Spring 3.0.1. This is possible, but it's somewhat precarious. You MUST have your @RequestBody method argument before your @RequestParam argument. I'm guessing this is because HandlerMethodInvoker reads the request body (along with the GET parameters) when retrieving parameters (and the request body can only be read once).

Here's an example (WARNING: I code in Scala, so I've not compiled this Java code)

@RequestMapping(value = "/test", method = RequestMethod.POST)
public String test(
        @RequestBody String body,
        @RequestParam("param1") String parma1,
        Map<Object, Object> model: Map[AnyRef, AnyRef])
{
    model.put("test", test)
    model.put("body", body)

    return "Layout"
}

An alternative is to use @PathVariable. I've confirmed that this works.

like image 149
three-cups Avatar answered Oct 24 '22 12:10

three-cups