Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly receive urlencoded form body with Spring

I've just started using Spring, and I'm trying to receive a form-urlencoded POST body in a rest controller, but I can't for the life of me get it to work. Here's my "Hello World"-esque controller:

@RestController
public class MyController {
    @ResponseBody
    @RequestMapping(
        value = "/",
        method = RequestMethod.POST,
        consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
        produces = MediaType.TEXT_PLAIN_VALUE
    )
    public String index(@RequestBody String text) {
        return "Text: " + text;
    }
}

I've tried many different variations, all with differing errors. The particular configuration above produces the following error when receiving a POST request with a "text" parameter from Postman.

Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public java.lang.String com.mywebsite.controllers.MyController.index(java.lang.String)

I've looked at many other stackoverflow posts about this topic and tried to implement their various solutions to no avail. Here's a list of the most promising ones:

  1. Spring JSON request body not mapped to Java POJO
    • This is the ideal outcome for me, a POJO with all the parameters. However, when I tried this, all POJO fields were null no matter what I passed in.
  2. How to get Form data as a Map in Spring MVC controller?
    • Following the first solution on that post, using a MultiValueMap produces the same error as above.
    • In the second, the parameter map is empty every time.
  3. How to retrieve FORM/POST Parameters in Spring Controller?
    • Produces an empty map, similar to the one above.

There were a couple more that I can no longer find, and for most of these posts I've tried tweaking the annotations each time. I had great success when I tried GET and JSON POST requests, but for some reason these urlencoded requests refuse to work.

like image 420
Matthew Olsson Avatar asked Dec 17 '17 08:12

Matthew Olsson


People also ask

How do I request body data in spring?

Simply put, the @RequestBody annotation maps the HttpRequest body to a transfer or domain object, enabling automatic deserialization of the inbound HttpRequest body onto a Java object. Spring automatically deserializes the JSON into a Java type, assuming an appropriate one is specified.

Does spring @RequestBody support the GET method?

HTTP's GET method does not include a request body as part of the spec. Spring MVC respects the HTTP specs. Specifically, servers are allowed to discard the body.

How do I request a body in spring boot?

@RequestBody annotation binds request body to method parameters. The process of serialization/deserialization is performed by HttpMessageConverter . In addition, automatic validation can be applied by annotating the argument with @Valid .

What is @ResponseBody in Spring MVC?

The @ResponseBody annotation tells a controller that the object returned is automatically serialized into JSON and passed back into the HttpResponse object. When you use the @ResponseBody annotation on a method, Spring converts the return value and writes it to the HTTP response automatically.


1 Answers

If you want to qet individual post parameters, just use RequestParam:

public String index(@RequestParam("text") String text) {
    return "Text: " + text;
}

If you want to get several parameters at once, create a Command class, with JavaBean properties matching the parameters:

public class Command {
    private String text;
    private Integer number;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public Integer getNumber() {
        return number;
    }

    public void setNumber(Integer number) {
        this.number = number;
    }
}

and pass that as argument to your method:

public String index(Command command) {
    return "Text: " + command.getText();
}
like image 107
JB Nizet Avatar answered Oct 19 '22 17:10

JB Nizet