Get HTTP POST Body in Spring Boot with @RequestBody

Introduction

With Spring, we map requests to request handlers via the @RequestMapping annotation. Spring Boot introduced us to derived types of this annotation - @GetMapping, @PostMapping, @DeleteMapping, etc.

These requests contain different types of information and data - and depending on what our endpoint does with the request, we may want to retrieve the body of a POST request either for logging or further processing.

The @RequestBody annotation allows us to retrieve the request's body. We can then return it as a String or deserialize it into a Plain Old Java Object (POJO).

Spring has built-in mechanisms for deserializing JSON and XML objects into POJOs, which makes this task a lot easier as well.

In this article, we'll get the body of a POST HTTP request and pack it into a String, as well as deserialize it into a POJO.

Getting HTTP POST Body as a String

Let's start out with a @Controller class to handle an incoming request:

@ResponseBody
@Controller
@RequestMapping("/response")
public class HomeController {}

What's worth noting here is that we've added the @ResponseBody annotation to the @Controller. This way, it won't render a template as the response body, but rather, will return a response body. Specifically, we'll pack it in a String and return that.

Spring Boot introduced us to another derived type - @RestController which is just a combination of the previous two annotations. Let's use that instead for brevity:

@RestController
@RequestMapping("/response")
public class HomeController {}

Now, let's go ahead and define a request handler. Since we're handling a POST request, we'll use the @PostMapping annotation for it:

@RestController
@RequestMapping("/response")
public class HomeController {

    @PostMapping("/postbody")
    public String postBody(@RequestBody String fullName) {
        return "Hello " + fullName;
    }
}

To retrieve the body of the POST request sent to the handler, we'll use the @RequestBody annotation, and assign its value to a String. This takes the body of the request and neatly packs it into our fullName String. We've then returned this name back, with a greeting message.

Let's test this controller out via curl:

curl -X POST -H "Content-type: application/json" -d "John Smith" "http://localhost:8080/response/postbody"

This results in:

Hello John Smith

Deserialize HTTP POST into POJO

Now, typically, we won't be working with Strings, although they serve as a good example for learning. In most cases, we'll want to do some processing, or at the least, serialize the request into a POJO. Let's define a Person POJO with a firstName and lastName:

public class Person {
    private String firstName;
    private String lastName;
    
    // Constructor, getters and setters
}

We'll perform the same process as in the previous example - with the same controller. However, this time, we'll specify that the controller is accepting JSON and XML values and that it produces JSON or XML responses back.

We'll retrieve a POST request body in JSON format, deserialize it into a POJO for further processing (saving into a database, for example) and return a JSON response.

Although Spring Boot can automatically match the JSON body to our POJO, given the variable names match, we'll explicitly set this option. We'll set the input and output formats using the consumes and produces flags in the @PostMapping:

@RestController
@RequestMapping("/response")
public class HomeController {

     @PostMapping(
        value = "/postbody",
        consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE},
        produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
    public ResponseEntity<Person> postBody(@RequestBody Person person) {
        Person persistedPerson = personService.save(person);
        return ResponseEntity
            .created(URI
                     .create(String.format("/persons/%s", person.getFirstName())))
            .body(persistedPerson);
    }
}

Here, we're accepting JSON and XML, as well as producing it back. We've annotated the Person instance as the @RequestBody, which we'll also be expecting from the request. Then, we've used a PersonService instance to save the person to a database, which also returns the persisted object for further processing.

For brevity's sake, we've omitted the PersonService implementation as it's a standard service-layer implementation.

Finally, we've returned a ResponseEntity object. It's just an extension of the HttpEntity class that also has a status code. We've set the status code as CREATED with a URI location where the new created resource is located. Then, we've set the body of the ResponseEntity as the persistentPerson instance and built the response.

Let's test this controller out via curl again:

curl -X POST -H "Content-type: application/json" -d "{\"firstName\" : \"John\", \"lastName\" : \"Smith\"}" "http://localhost:8080/response/postbody"

Here, we've made a POST request with a JSON body, containing the first and last name of a person and sent it to our endpoint.

The endpoint responds with:

{"firstName":"John","lastName":"Smith"}

Conclusion

In this tutorial, we've covered two ways to capture a POST HTTP request's body in a Spring Boot controller.

Using the @RequestBody annotation, we've mapped the body to a String and returned it. Afterwards, we've defined a POJO to deserialize incoming JSON contents into, processed it and finally returned a ResponseEntity.