View video tutorial

SPRING BOOT @RequestBody

SPRING BOOT

The @RequestBody annotation maps the body of the HttpRequest to a DTO or domain object, which enables the body of the incoming HttpRequest to be automatically deserialized into a Java object.

Spring Boot @RequestBody Annotation


➔ The @RequestBody annotation is used to bind the body of an HTTP request (mainly in JSON/XML format) to a parameter of a handlermethod of a RestController.

➔ This process is known as deserialization and is handled automatically by Spring Boot.

Key characteristics of the @RequestBody annotation:


➔ @RequestBody is commonly used with POST, PUT, and PATCH requests.

➔ Spring Boot automatically maps JSON fields to Java object properties. For this to work, the field name in the JSON must match the property name in the Java class.

Sample code
// Define Data Transfer Object (DTO)
public class Customer{
    private int id;
    private String name;
    // Getters, Setters, constructors.
}

// Use @RequestBody in your Controller
@RestController
public class CustomerController {
    @PostMapping("/customers")
    public String createCustomer(@RequestBody Customer c) {
        return "Customer: " + c.getName();
    }
}
//JSON object data in @RequestBody
{
    "id": 100,
    "name": "Amelia"
}

➔ JSON objects can have additional fields, but all properties of the Java class must match the JSON fields to create a Java object.

Sample code
// Define Data Transfer Object (DTO)
public class Customer{
    private int id;
    private String name;
    // Getters, Setters, constructors.
}
//JSON object data in @RequestBody
{
    "id": 100,
    "name": "Amelia",
    "age": 22
}

➔ The @RequestBody annotation can only be used once within a method. @RequestBody is designed to bind the entire body of a request to a single Java object, and its properties can be of simple type or object type.

➔ By default, the request body is required when used in a RESTful controller method, but it can be made optional using @RequestBody(required = false).

Common errors and issues:


400 Bad Request: This occurs when the structure of the JSON (field) does not match the Java object (property) or validation fails.

415 Unsupported Media Type: This error occurs when the Content-type header (such as application/json) does not match the type the server accept.

GET requests with @RequestBody: It is not recommended to use @RequestBody with GET requests, although technically it is possible and there is no problem with it

Comparison of similar annotations:


@PathVariable: This is used to extract values ​​from URL paths using URI template variables, such as /customer/{id}

@RequestParam: It is used to bind simple values ​​like string, int etc. from query parameters or form data, e.g. query params, /custormer?id=100

@RequestBody: This is commonly used to bind complex objects/lists to the HTTP request body for POST, PUT, and PATCH requests.

Access all fields from @RequestBody for DTO or domain model:


Sample code
public class Customer {
	int id;
	String name;
        // getters, setters, constructors.
}

PostMan:  JSON data as HTTP request in @RequestBody
{
    "id": 100,
    "name": "Amelia",
    "email": "amelia@gmail.co"
}

@PostMapping({"/api/customersdto"})
public String customerDtoHandler(@RequestBody Map<String, Object> requestData) {
	int id = (int) requestData.get("id");
	String name = (String) requestData.get("name");
	//create DTO, or Domain Model
	Customer c= new Customer();
	c.setId(id);
	c.setName(name);
	// Access fields that are not in the DTO
	String email =(String) requestData.get("email");
	return "Customer: " + c.getName() +"\nEmail: "+email;	
}
//Output
Customer: Amelia
Email: amelia@gmail.co

Spring Boot @ResponseBody Annotation


➔ The @Response annotation is used to bind the return value of a method to the HTTP response body, which enables Java objects to be automatically serialized to formats such as JSON or XML using HttpMessageConverters.

➔ It is typically used to generate RESTful API responses and is included within @RestController in Spring Boot.

➔ Although not required, this can be implemented at the individual method level or on the entire controller class, affecting all methods.

➔ The @RestController annotation is a meta-annotation that combines @Controller and @ResponseBody and simplifies the creation of RESTful web services by combining the functionality of these two annotations.

➔ When using @RestController in the controller class, there is no need to annotate each method separately with @ResponseBody.

➔ @ResponseBody is used when creating RESTful web services that return JSON, XML, or raw data/text, rather than returning and rendering a server-side HTML view.

Setting the content type for @ResponseBody:


➔ Even when using the @ResponseBody annotation, it is possible to explicitly set the content type for the data that the method will return.

➔ The most common types are application/json or application/xml.

@GetMapping(value = "/customers", produces = MediaType.APPLICATION_JSON_VALUE)
@GetMapping(value = "/customers", produces="application/json")  
@GetMapping(value = "/customers", produces = MediaType.APPLICATION_XML_VALUE)  
@GetMapping(value = "/customers", produces="application/xml")

Sample code (String/Text response)
//DTO or Momain Model
public class Customer {
	int id;
	String name;
       // setters, getters, constructors.
}

//RestController class
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UsersController {
	@PostMapping(value={ "/api/customers" })
	@ResponseBody //It is not necessary to use @ResponseBody explicitly for @RestController.
	public String customerHandler(@RequestBody Customer c) {
		return "Hello Customer: " + c.getName();
	}
}
//JSON data
{
    "id": 100,
    "name": "Amelia"
}
//Output
Hello Customer: Amelia

Sample code (JSON response)
//DTO or Momain Model
public class Customer {
	int id;
	String name;
       // setters, getters, constructors.
}

//RestController class
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UsersController {
	@PostMapping(value="/api/customers")
	public Customer customerHandler(@RequestBody Customer c) {
		return  c;
	}
}

//JSON data HTTP request
{
    "id": 100,
    "name": "Amelia"
}
//JSON response output
{
    "id": 100,
    "name": "Amelia"
}

Produce XML response by @ResponseBody:


➔ add jackson-dataformat-xml dependency in pom.xml

//pom.xml dependency
<dependency>
	<groupId>com.fasterxml.jackson.dataformat</groupId>
	<artifactId>jackson-dataformat-xml</artifactId>
</dependency>

➔ Add the @JacksonXmlRootElement annotation to the DTO or domain model.

//DTO or Momain Model
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JacksonXmlRootElement
public class Customer {
	int id;
	String name;
       // setters, getters, constructors.
}

➔ Use the produces attribute to generate an XML response.

@PostMapping(value="/api/customers", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_XML_VALUE)
OR
@PostMapping(value="/api/customers", consumes = MediaType.APPLICATION_JSON_VALUE, produces="application/xml")
//pom.xml dependency
		<dependency>
			<groupId>com.fasterxml.jackson.dataformat</groupId>
			<artifactId>jackson-dataformat-xml</artifactId>
		</dependency>

//DTO or Momain Model
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JacksonXmlRootElement
public class Customer {
	int id;
	String name;
       // setters, getters, constructors.
}

//RestController class
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UsersController {
	@PostMapping(value="/api/customers", produces = MediaType.APPLICATION_XML_VALUE)
	@ResponseBody //It is not necessary to use @ResponseBody explicitly for @RestController.
	public Customer customerHandler(@RequestBody Customer c) {
		return  c;
	}
}
//JSON data
{
    "id": 100,
    "name": "Amelia"
}
//HTTP Headers
Accept:application/xml
Content-Type:application/json

//Output
<Customer>
    <id>100</id>
    <name>Amelia</name>
</Customer>

Accept, Content-Type, consumes, produces


Accept: application/xml: The Accept: application/xml HTTP request header is used by a client (such as a web browser, API client, or API consumer) to inform the server that the client prefers to receive data in XML format.

Content-Type: application/json: The Content-Type: application/json HTTP request header is used by a client to tell the server to parse the request body as a JSON object.

consumes = MediaType.APPLICATION_JSON_VALUE: The consumes attribute in the Spring Boot server is used to specify that a controller method will only accept a specific media type (such as application/json) in the request body from the client.

produces="application/xml": The produces attribute is used in Spring Boot servers to specify that a controller method will produce a specific media type (such as `application/xml`) as a response to API clients. By default, Spring Boot generates `application/json` responses without any explicit configuration.

Difference between @RequestBody and @ResponseBody

Features @RequestParam @PathVariable
Objective This is applied to the data in incoming HTTP requests. @ResponseBody is implemented as the return data of the outgoing response.
HTTP method. FTypically used with POST, PUT and PATCH http methods. Typically used with the HTTP GET method.
Method type Typically used to extract data as DTOs or domain models and send it to the service layer for further business logic processing. Return type void or simple type. Typically, complex objects are returned as RESTful API responses. In most cases, the return type is in JSON or XML format.
Object format The deserialized object is passed as a parameter to a method and mapped to a Java object. The serialized object from the method is returned as a response, usually in JSON or XML format.

Now practice this chapter in your learning environment.

02 Create a Controller class

Create controller

Name it anything, for example UsersController.

Create UsersController

Controller Code
package com.exam.helloworld;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UsersController {
	@PostMapping(value="/api/customers", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_XML_VALUE)
	@ResponseBody //It is not necessary to use @ResponseBody explicitly for @RestController.
	public Customer customerHandler(@RequestBody Customer c) {
		return  c;
	}
}

pom.xml add dependency for jackson-dataformat-xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>4.0.3</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.exam</groupId>
	<artifactId>helloworld</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Helloworld</name>
	<description>Demo project for Spring Boot</description>
	<url />
	<licenses>
		<license />
	</licenses>
	<developers>
		<developer />
	</developers>
	<scm>
		<connection />
		<developerConnection />
		<tag />
		<url />
	</scm>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-webmvc</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-webmvc-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.dataformat</groupId>
			<artifactId>jackson-dataformat-xml</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
                    

Customer.java code (DTO or Domain Model)
package com.exam.helloworld;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement
public class Customer {
	int id;
	String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Customer(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public Customer() {
		super();
	}

}
                    

03 Run HelloworldApplication.java

spring boot application run

After successfully run the application.

restapi server run

Now set Accept and Content-Type HTTP header in Postman (an API testing tool).

Set HTTP request header.

PutMapping  text

XML response, output
RequestParam PutMapping output