About this article, most of the people find it on a basic level, but the impact of this is more useful when it comes to dealing with input fields. So let’s see what we can learn in this article.
Generally, when we need to validate user input or form fields, Spring offers standard predefined validators and those we are using already. However, when we need to validate a more particular type of input, we have the possibility of creating our own, custom validation logic.
In this article, we’ll do just that – we’ll create a custom validator to validate a form with an email, password, name, and phone number field.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
Creating a custom validator entails us rolling out our annotation and using it in our model to enforce the validation rules.
So we are going to create four validation listed below,
We need to create a new @interface to define our annotation
@Documented @Retention(RUNTIME) @Target({ FIELD, ANNOTATION_TYPE, TYPE_USE }) @Constraint(validatedBy = EmailValidator.class) public @interface ValidEmail { String message() default "{email.invalid}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
With the use of @Constraint annotation, we can define our class that is going to validate our field, the message() is the error message that is going to be shown in the response and the rest code is the most boilerplate code of spring standards.
Let’s create a validator - We will call it as an EmailValidator
public class EmailValidator implements ConstraintValidator<ValidEmail, String> {
private String regex = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
+ "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
@Override
public boolean isValid(String email, ConstraintValidatorContext context) {
if (StringUtils.isBlank(email))
return true;
Pattern pat = Pattern.compile(regex);
return pat.matcher(email).matches();
}
}
Now if you see, we have used the same regex which we usually use on the frontend side.
The validation class implements the ConstraintValidator interface and must implement the isValid method; it’s in this method that we defined our validation rules.ConstraintValidator defines the logic to validate a given constraint for a given object.
Applying validation annotation
We have looked for EmailValidator so let’s use email validator annotation to email field
@NotBlank @ValidEmail private String email;
@NotBlank – This is provided by spring only to check whether the field is blank or not.
@ValidEmail – If you look in the above code we have ConstraintValidator as ValidEmail, So ultimately the ValidEmail will be our custom annotation.
Now we are going to create one controller to test our annotation, we will create a user controller in that the rest endpoint will be /user/validate
@RestController @RequestMapping("user") public class UserController { @Autowired private ResponseMaker responseMaker; @PostMapping("/validate") public ResponseEntity<SuccessResponse<String>> validateObject(@RequestBody @Valid UserModel userModel) { return responseMaker.successResponse("User validated successfully", HttpStatus.OK); } }
Now in the controller one thing we need to make sure that we have used @Valid annotation to our Model class (In which we have added our validation annotation)
We have added a few exception handlers so that we can format our success and error responses, these are generic exception handlers which can be easily available on the internet.
Let’s check a few scenarios to check our validations
Request: { } Response: { "message": "Please enter valid data", "code": 400, "error": true, "validationErros": [ { "fieldName": "contactNo", "message": "must not be blank" }, { "fieldName": "name", "message": "must not be blank" }, { "fieldName": "email", "message": "must not be blank" }, { "fieldName": "password", "message": "must not be blank" } ] }
2. Invalid user input request,
Request:
{ "email":"asdlj", "password":"hasd", "name":"asdas343", "contactNo":"asdlsdlkj" }
Response:
{ "message": "Please enter valid data", "code": 400, "error": true, "validationErros": [ { "fieldName": "password", "message": "Password should contain at least one number, one special symbol,one upper case, one lower case letter and length of 5 to 20 char" }, { "fieldName": "email", "message": "Email is invalid." }, { "fieldName": "contactNo", "message": "Mobile number is invalid." }, { "fieldName": "name", "message": "Numbers & Special Characters are not allowed." } ] }
3. Success request,
Request:
{ "email":"dg12kumbhar@gmail.com", "password":"Password@123", "name":"Deepak", "contactNo":"9876543210" } Response: { "code": 200, "data": "User validated successfully" }
Note: The first validation is handled by @NotBlank annotation, which is provided by Spring only.
Yes, that’s it. We have successfully created our custom annotation and integrated it with an application.
You can find this complete repository here GitHub Link.
Thank you for reading this article, If you have any doubts, the comment section is always open.