Spring Request Body Validation For List
Posted By : Bobby Sharma | 23-Sep-2018
In Spring MVC the @RequestBody annotation indicates a method parameter should be bound to a body of the request. The @RequestBody parameter can be treated as any other parameter in a @RequestMapping method and therefore it can also be validated by a standard validation mechanism.
Simple validation
Spring offers the simplest form of validation. we can specify if a particular parameter( PathVariable or RequestParameter) is required or not. By Default, Both are Required but we can easily change it to optional:
@GetMapping("/person/{name}")
public ResponseEntity hello(@PathVariable(value = "name", required = true) String name){
//...
}
@GetMapping("/person")
public ResponseEntity queryPerson(@RequestParam(value = "query", required = false) String query) {
// ...
}
Request body Validation
Validating Request body with some complex objects that represent a parsed JSON we have to do a bit more. First, we have to interpret our object with all the constraints and requirements. Spring has support for JSR 303 Bean Validation which makes it really easy. We just annotate our fields, with @NotBlank, @NotEmpty, @Pattern, @Max, @Min annotations with desired parameters. If there is some nested objects, then we have to add Valid annotation on a field with this objects, so that it will be validated. We can Use @Valid Or @validate for request body Validation. Spring supports 2 validation methods: Spring validation and JSR-303 bean validation.
@valid: Spring 3 provides support for declarative validation with JSR-303. If a JSR-303 provider, such as Hibernate Validator, is present on your classpath then This support enabled automatically. When enabled, you can trigger validation simply by annotating a Controller method parameter with the @Valid annotation:
@validated: @Validated
was added to support "validation groups", That is a group of fields in the validated bean. It can be used in multi-step forms where you may validate name, email, etc. I will post a blog on Validation Groups sooner.
Request body Validation For List
@Valid And @Validated both Annotation validate Java beans only, But @valid And @Validated Not Work For List<T> of Java Class, So To Validate JSON of List what we have to do is We have To Modify Our Request Body For Validation. What We Are Going To Do in This Article is, First We create a generic class which validates Request Body.
Lets Create Class With Name Product :
@Entity
public class Product{
@Id
private Integer id;
@NotBlank(message="Product name Can not be empty")
private String name;
// getter setter
}
Let us Create JSON for Product And Save Products List :
[
{
"name":""
}
,{
"name":"Titan G45"
}
,{
"name":"IPhone 6s"
}
]
@PostMapping("/product/savelist")
public ResponseEntity<product> saveProducList(@Valid @RequestBody List<product> products)
{
productService.saveProducts(products);
}
Response :
"message" : "Data Save Successfuly"
"success" : true
So Validation didn't work for List of Product, But if Our Request Body is Simple java Bean or a single Product then validation work for JSON. To validate List What we Have to Do is :
1. Create Class with name ValidateRequestBodyList
As We know using @Valid with @RequestBody not going to validate Request Body of List<Product> in Controller so To Validate List what we have to do is create Simple class With Type Parameter " T " So that we use this class to validate all request where our request body is a list.
public class ValidateRequestBodyList<T> {
@Valid
private List<T> requestBody;
public List<T> getRequestBody() {
return requestBody;
}
public void setRequestBody(List<T> requestBody) {
this.requestBody = requestBody;
}
public ValidateRequestBodyList(List<T> requestBody) {
this.requestBody = requestBody;
}
public ValidateRequestBodyList() {
}
}
2.Use Of ValidateRequestBodyList
ValidateRequestBodyList Class is Generic Class which validate List Of Request Body, Now What we have to do is Just Pass Class Name as Type Parameter And Validate Request Body Using @Valid. Now @Valid Is Going To Work And Validate Request Body.
@PostMapping("/product/savelist")
public ResponseEntity<product> saveProducList(@Valid @RequestBody ValidateRequestBodyList<product> products){
List<Product> productList= products.getRequestBody();
productService.saveProducts(productList); or // productService.saveProducts(products.getRequestBody());
}
Let us Create JSON for Product Again And Save Products List :
{
"requestBody":[
{
"name":""
}
, {
"name":"Titan G45"
}
,{
"name":"IPhone 6s"
}]
}
Response :
"message" : null
"success" : false
"errors": [
{
"fieldName": "requestBody[0].title",
"fieldError": "Product name Can not be empty"
}
]
Suppose we have Class Person Which Contain List of Products Then to validate List Of Product What We Have To Do Is Simply Put @Valid On List Of Product :
public class Person{
@Id
private Integer id;
@NotBlank(message="Email Id cant'be empty")
private String email;
@Valid //to validate Product list annotate @valid for list
private List products;
}
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Bobby Sharma
Bobby is a Java Developer experienced in spring boot , Hibernate ,JPA , MYSQL , MongoDB , Servlets ,Java server pages ,Collections Framework.