Spring’s RequestBody and ResponseBody Annotations

1. Introduction

In this quick tutorial, we provide a concise overview of the Spring @RequestBody and @ResponseBody annotations.

2. @RequestBody

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.

First, let’s have a look at a Spring controller method:

@PostMapping("/request")
public ResponseEntity postController(
  @RequestBody LoginForm loginForm) {
 
    exampleService.fakeAuthenticate(loginForm);
    return ResponseEntity.ok(HttpStatus.OK);
}

Spring automatically deserializes the JSON into a Java type, assuming an appropriate one is specified.

By default, the type we annotate with the @RequestBody annotation must correspond to the JSON sent from our client-side controller:

public class LoginForm {
    private String username;
    private String password;
    // ...
}

Here, the object we use to represent the HttpRequest body maps to our LoginForm object.

Let’s test this using CURL:

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data 
  '{"username": "johnny", "password": "password"}' "https://localhost:8080/.../request"

This is all we need for a Spring REST API and an Angular client using the @RequestBody annotation.

3. @ResponseBody

The @ResponseBody annotation tells a controller that the object returned is automatically serialized into JSON and passed back into the HttpResponse object.

Suppose we have a custom Response object:

public class ResponseTransfer {
    private String text; 
    
    // standard getters/setters
}

Next, the associated controller can be implemented:

@Controller
@RequestMapping("/post")
public class ExamplePostController {

    @Autowired
    ExampleService exampleService;

    @PostMapping("/response")
    @ResponseBody
    public ResponseTransfer postResponseController(
      @RequestBody LoginForm loginForm) {
        return new ResponseTransfer("Thanks For Posting!!!");
     }
}

In the developer console of our browser or using a tool like Postman, we can see the following response:

{"text":"Thanks For Posting!!!"}

Remember, we don’t need to annotate the @RestController-annotated controllers with the @ResponseBody annotation since Spring does it by default.

3.1. Setting the Content Type

When we use the @ResponseBody annotation, we’re still able to explicitly set the content type that our method returns.

For that, we can use the @RequestMapping‘s produces attribute. Note that annotations like @PostMapping@GetMapping, etc. define aliases for that parameter.

Let’s now add a new endpoint that sends a JSON response:

@PostMapping(value = "/content", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseTransfer postResponseJsonContent(
  @RequestBody LoginForm loginForm) {
    return new ResponseTransfer("JSON Content!");
}

In the example, we used the MediaType.APPLICATION_JSON_VALUE constant. Alternatively, we can use application/json directly.

Next, let’s implement a new method, mapped to the same /content path, but returning XML content instead:

@PostMapping(value = "/content", produces = MediaType.APPLICATION_XML_VALUE)
@ResponseBody
public ResponseTransfer postResponseXmlContent(
  @RequestBody LoginForm loginForm) {
    return new ResponseTransfer("XML Content!");
}

Now, depending on the value of an Accept parameter sent in the request’s header, we’ll get different responses.

Let’s see this in action:

curl -i \ 
-H "Accept: application/json" \ 
-H "Content-Type:application/json" \ 
-X POST --data 
  '{"username": "johnny", "password": "password"}' "https://localhost:8080/.../content"

The CURL command returns a JSON response:

HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 20 Feb 2020 19:43:06 GMT

{"text":"JSON Content!"}

Now, let’s change the Accept parameter:

curl -i \
-H "Accept: application/xml" \
-H "Content-Type:application/json" \
-X POST --data
  '{"username": "johnny", "password": "password"}' "https://localhost:8080/.../content"

As anticipated, we get an XML content this time:

HTTP/1.1 200
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Thu, 20 Feb 2020 19:43:19 GMT

<ResponseTransfer><text>XML Content!</text></ResponseTransfer>

4. Conclusion

We’ve built a simple Angular client for the Spring app that demonstrates how to use the @RequestBody and @ResponseBody annotations.

Additionally, we showed how to set a content type when using @ResponseBody.

As always, code samples are available over on GitHub.

Related posts:

Java Program to Implement Circular Doubly Linked List
Using a Custom Spring MVC’s Handler Interceptor to Manage Sessions
Java Program to Implement ConcurrentSkipListMap API
Java Program to Solve Tower of Hanoi Problem using Stacks
Working with Kotlin and JPA
Java Program to Find the Shortest Path Between Two Vertices Using Dijkstra’s Algorithm
Understanding Memory Leaks in Java
OAuth 2.0 Resource Server With Spring Security 5
Java Program to Implement Min Heap
Java Program to Check the Connectivity of Graph Using BFS
Java Program to Implement Pairing Heap
Period and Duration in Java
How to Remove the Last Character of a String?
Spring Boot - Cloud Configuration Server
Java Program to Use Dynamic Programming to Solve Approximate String Matching
The Registration API becomes RESTful
Giới thiệu luồng vào ra (I/O) trong Java
HttpClient 4 – Send Custom Cookie
Finding Max/Min of a List or Collection
HashMap trong Java hoạt động như thế nào?
Java Program to implement Array Deque
LinkedHashSet trong Java hoạt động như thế nào?
Java Program to Perform the Sorting Using Counting Sort
Java Program to Find the Mode in a Data Set
Creating a Web Application with Spring 5
Java Program to find the maximum subarray sum O(n^2) time(naive method)
Spring Boot with Multiple SQL Import Files
Convert Hex to ASCII in Java
Lập trình mạng với java
How to Manually Authenticate User with Spring Security
How to Add a Single Element to a Stream
Java Program to Implement Slicker Algorithm that avoids Triangulation to Find Area of a Polygon