Clean • Professional
Spring Boot REST APIs allow clients (web apps, mobile apps) to communicate with your server. Three fundamental concepts in this communication are Request Body, Response, and ResponseEntity. This guide covers everything you need to understand these concepts, including validation, status codes, headers, and advanced tips.
The Request Body is the part of an HTTP request where the client sends data to the server. It is used to create or update resources in your system.
Key Points:
@Valid with Bean Validation annotations.Example – Creating a User (POST Request):
@PostMapping("/users")
public UsercreateUser(@RequestBody User user) {
return userService.saveUser(user);
}
Explanation:
@RequestBody User user → Spring converts the request JSON into a Java User object.@Valid.Sample JSON Request:
{
"name":"Alice",
"email":"[email protected]",
"age":25
}
@RequestBody.@RequestBody per method is allowed.@Valid to enforce field validation automatically.The Response is the data the server sends back to the client after processing a request. It contains:
Content-Type, Cache-Control, or custom headers.Using @ResponseBody
The @ResponseBody annotation tells Spring Boot to convert the Java object returned by a controller method into JSON (or XML) and send it as the HTTP response body. It is commonly used in REST APIs for simple responses, without needing full control over HTTP status codes or headers.
@GetMapping("/users/{id}")
@ResponseBody
public UsergetUser(@PathVariable Long id) {
return userService.findUserById(id);
}
Explanation:
@ResponseBody automatically serializes the User Java object to JSON.Output (JSON):
{
"id":1,
"name":"Alice",
"email":"[email protected]"
}
Mapping Explanation:
"id" → Unique user identifier"name" → User’s name"email" → User’s email addressSpring Boot REST APIs use @RequestBody and @ResponseBody to handle incoming requests and outgoing responses. Understanding the difference is essential for building robust APIs.
| Feature | @RequestBody | @ResponseBody |
|---|---|---|
| Purpose | Map client request to Java object | Map Java object to response |
| Direction | Client → Server | Server → Client |
| Applied To | Method parameter | Method return type (or class) |
| Action | Deserialize HTTP body to Java | Serialize Java to JSON |
| HTTP Methods | POST, PUT, PATCH (rarely DELETE) | GET, POST, PUT, DELETE, PATCH |
| Example | @RequestBody User user | @ResponseBody User getUser() |
Tip: Using @RestController automatically applies @ResponseBody to all methods.
ResponseEntity<T> represents the entire HTTP response, including:
Content-Type, Authorization, or custom headersWhy Use ResponseEntity?
Example – Create & Get User
@PostMapping("/users")
public ResponseEntity<User>createUser(@Valid@RequestBody UserDTO userDTO) {
Usersaved= userService.saveUser(userDTO);
return ResponseEntity.status(HttpStatus.CREATED).body(saved);// 201 Created
}
@GetMapping("/users/{id}")
public ResponseEntity<User>getUser(@PathVariable Long id) {
return userService.findById(id)
.map(user -> ResponseEntity.ok(user))// 200 OK
.orElse(ResponseEntity.notFound().build());// 404 Not Found
}
Explanation:
@RequestBody UserDTO userDTO → Maps JSON from client to a Java object.@Valid → Automatically validates the input using Bean Validation annotations.ResponseEntity.status(HttpStatus.CREATED).body(saved) → Returns 201 Created with the saved user data..map(user -> ResponseEntity.ok(user)) → Returns 200 OK if the user exists..orElse(ResponseEntity.notFound().build()) → Returns 404 Not Found if the user does not exist.Adding Custom Headers Example:
@GetMapping("/{id}/download")
public ResponseEntity<byte[]> downloadFile(@PathVariable Long id) {
byte[] fileData = getFileData(id);
return ResponseEntity.ok()
.header("Content-Disposition","attachment; filename=file.txt")
.body(fileData);
}
Explanation:
Content-Disposition) to instruct the browser to download a file.Spring Boot allows automatic validation of incoming request data using @Valid along with Bean Validation annotations (from jakarta.validation or javax.validation). This ensures that the data sent by the client meets the required rules before processing it in your controller.
DTO Example:
publicclassUserDTO {
@NotBlank(message = "Name is mandatory")
private String name;
@Email(message = "Invalid email")
private String email;
// getters and setters
}
Explanation:
@NotBlank → Ensures the field is not empty or null.@Email → Ensures the field contains a valid email format.@Min → Ensures numeric values meet the minimum requirement.Controller Example:
@PostMapping("/users")
public ResponseEntity<User>createUser(@Valid@RequestBody UserDTO userDTO) {
Usersaved= userService.saveUser(userDTO);
return ResponseEntity.status(HttpStatus.CREATED).body(saved);
}
Explanation:
@RequestBody → Maps incoming JSON to UserDTO.@Valid → Triggers automatic validation based on the annotations in UserDTO.ResponseEntity → Sends the response with 201 Created if validation passes.Example Invalid Request JSON:
{
"name":"",
"email":"invalid-email",
"age":16
}
Example 400 Bad Request Response:
{
"timestamp":"2026-01-01T12:00:00.000+00:00",
"status":400,
"errors":[
"Name is mandatory",
"Invalid email format",
"Age must be at least 18"
]
}
1. POST Request – Sending Data to the Server
Endpoint: POST /emp
Request Body (JSON):
{
"name":"Durgesh",
"salary":50000,
"department":"IT"
}
Explanation:
"name", "salary", and "department" represent the employee details to be created or saved.@RequestBody to automatically map this JSON into a Java Employee object.@Valid), Spring checks the data and returns 400 Bad Request if any field is invalid.2. GET Request – Receiving Data from the Server
Endpoint: GET /emp/1
Response Body (JSON):
{
"id":1,
"name":"Durgesh",
"salary":50000,
"department":"IT"
}
Explanation:
"id" generated by the database along with the employee details.@ResponseBody or ResponseEntity to convert the Java Employee object into JSON automatically.200 OK → Successfully fetched data201 Created → Successfully created resource@RestController
@RequestMapping("/emp")
publicclassEmployeeController {
@Autowired
private EmployeeRepository employeeRepository;
// Create employee
@PostMapping
public ResponseEntity<Employee>addEmployee(@Valid@RequestBody Employee employee) {
Employeesaved= employeeRepository.save(employee);
return ResponseEntity.status(HttpStatus.CREATED).body(saved);// 201 Created
}
// Get all employees
@GetMapping
public ResponseEntity<List<Employee>>getAllEmployees() {
List<Employee> employees = employeeRepository.findAll();
return ResponseEntity.ok(employees);// 200 OK
}
// Get employee by ID
@GetMapping("/{id}")
public ResponseEntity<Employee>getEmployeeById(@PathVariable Long id) {
return employeeRepository.findById(id)
.map(emp -> ResponseEntity.ok(emp))// 200 OK
.orElse(ResponseEntity.notFound().build());// 404 Not Found
}
}
Explanation:
@RestController → Returns JSON automatically@RequestBody → Maps request JSON to Java object@Valid → Validates dataResponseEntity → Custom status codes and headers@PathVariable → Reads dynamic URL parameters1. DELETE with Request Body
POST, PUT, or PATCH.DELETE is rare but technically allowed in HTTP.@DeleteMapping("/users")
public ResponseEntity<Void>deleteUsers(@RequestBody List<Long> ids) {
userService.deleteUsersByIds(ids);
return ResponseEntity.noContent().build();// 204 No Content
}
Explanation:
List<Long> using @RequestBody.2. HttpMessageConverter
HttpMessageConverter to convert HTTP requests and responses between Java objects and formats like JSON, XML, or plain text.3. Reactive APIs with WebFlux
@RequestBody can support reactive types:@PostMapping("/accounts")
public Mono<Account>createAccount(@RequestBody Mono<Account> accountMono) {
return accountService.saveAccount(accountMono);
}
Explanation:
Mono<T> → 0 or 1 element; Flux<T> → 0..N elements.4. Custom Headers in Response
Example – File Download:
@GetMapping("/users/{id}/download")
public ResponseEntity<byte[]> downloadFile(@PathVariable Long id) {
byte[] fileData = fileService.getFile(id);
return ResponseEntity.ok()
.header("Content-Disposition","attachment; filename=user-data.txt")
.header("Custom-Header","value")
.body(fileData);
}
Explanation:
Content-Disposition tells the browser to download the file.@Valid.@RequestBody) → Maps client JSON to Java object.@ResponseBody) → Maps Java object to JSON response.@Valid) → Ensures data integrity and handles errors automatically.