Creating Custom validation using spring
The method validation feature supported by Bean Validation 1.1 is automatically enabled as long as a JSR-303 implementation (such as Hibernate validator) is on the classpath.
This lets bean methods be annotated with javax.validation constraints on their parameters and/or on their return value.
Target classes with such annotated methods need to be annotated with the @Validated annotation at the type level for their methods to be searched for inline constraint annotations.
Create custom annotation (CommunicationType.java)
The below code shows you how to create a custom annotation to use with spring boot validation.
package com.candidjava.springboot.validators; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; @Target({ ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = CommunicationTypeValidator.class) @Documented public @interface CommunicationType { String message() default "Communication preference must be email or mobile."; Class<?>[] groups() default {}; Class<?extends Payload> [] payload() default {}; }
Custom logic using ConstraintValidator (CommunicationTypeValidator.java)
Defines the logic to validate a given constraint A for a given object type T.
Implementations must comply with the following restriction:
- T must resolve to a non parameterized type
- or generic parameters of T must be unbounded wildcard types
package com.candidjava.springboot.validators; import java.util.Arrays; import java.util.List; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; public class CommunicationTypeValidator implements ConstraintValidator< CommunicationType,String> { @Override public boolean isValid(String value, ConstraintValidatorContext context) { final List<String> commType = Arrays.asList("email", "mobile"); return commType.contains(value); } }
Using annotation with Entity class (Student.java)
Annotate the variable with created @CommunicationType annotation
package com.candidjava.springboot.models; import javax.validation.constraints.NotEmpty; import com.candidjava.springboot.validators.CommunicationType; public class Student { private String id; @NotEmpty(message = "First name is required") private String name; private String age; @NotEmpty(message = "email is required") private String email; @NotEmpty(message = "mobile number is required") private String mobile; @NotEmpty(message = "Communication Type preference is required") @CommunicationType private String communicationType; public Student(String id, String name, String age, String email, String mobile, String communicationType) { this.id = id; this.name = name; this.age = age; this.email = email; this.mobile = mobile; this.communicationType = communicationType; } public String getCommunicationType() { return communicationType; } public void setCommunicationType(String communicationType) { this.communicationType = communicationType; } public String getName() { return name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }
Enabling Validation (StudentController.java)
Now use @Valid Annotation in method arguments to validate request object.
package com.candidjava.springboot.controller; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import com.candidjava.springboot.models.Student; import com.candidjava.springboot.service.StudentService; @RestController @RequestMapping(value = "/student") public class StudentController { @Autowired StudentService service; @PostMapping("/create") public void create(@Valid @RequestBody Student student) { service.createStudent(student); } @GetMapping("/getAll") public List<Student> get() { return service.getAllStudents(); } @GetMapping("/get/{id}") public Student getById(@PathVariable("id") String id) { return service.getStudentById(id); } @PutMapping("/update/{id}") public void update(@PathVariable("id") String id, @Valid @RequestBody Student student) { service.updateStudent(id, student); } @DeleteMapping("/delete/{id}") public void deleteById(@PathVariable("id") String id) { this.service.deleteStudentById(id); } @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MethodArgumentNotValidException.class) public Map<String,String> handleMethodArgumentNotValid(MethodArgumentNotValidException ex) { Map<String,String> errors = new HashMap<>(); ex.getBindingResult().getFieldErrors() .forEach(error -> errors.put(error.getField(), error.getDefaultMessage())); return errors; } }
Configure dependency (pom.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>2.2.6.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <groupId>com.candidjava.spring.boot</groupId> <artifactId>validation</artifactId> <version>0.0.1-SNAPSHOT</version> <name>validation</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Launch as Spring boot (Application.java)
package com.candidjava; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Download
Download source code from my github account Click here