Validating user input is an important part of any application. In this article, we'll take a look at how to use the Bean Validation API to validate user input in a Spring Boot application.
Bean Validation is a Java specification for validating the constraints of Java Bean properties. It is part of the Java Enterprise Edition (Java EE) and is available as a standalone library for use in Java SE applications.
The Bean Validation API is a set of interfaces and classes that define the contracts for implementing a Bean Validation provider. A Bean Validation provider is an implementation of these contracts that can be plugged into a Java EE or Java SE application to provide validation services.
Bean Validation defines a set of annotations that can be used to annotate Java Bean properties. These annotations can be used to specify the constraints that should be applied to the property.
When a property is annotated with a constraint annotation, the Bean Validation provider will validate the property against the constraint. If the property is valid, the provider will do nothing. If the property is invalid, the provider will throw a ConstraintViolationException.
To use Bean Validation in a Spring Boot application, we need to add the Hibernate Validator dependency to our project. Hibernate Validator is the reference implementation of the Bean Validation API.
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.17.Final</version>
</dependency>
Once we have added the dependency, we can start using Bean Validation in our application.
Let's say we have a user registration form with the following fields:
We can validate the form using the following annotations:
We can annotate the form fields with these annotations:
public class RegistrationForm {
@NotNull
@Size(min = 3, max = 20)
private String username;
@NotNull
@Size(min = 6, max = 40)
private String password;
@NotNull
@Size(min = 6, max = 40)
private String confirmPassword;
@NotNull
@Email
private String email;
//Getters and setters
}
Now, let's say we have a controller with a method that handles the form submission:
@PostMapping("/register")
public String register(@Valid RegistrationForm form, BindingResult bindingResult) {
//Validate form
if (bindingResult.hasErrors()) {
return "register";
}
//Register user
return "redirect:/login";
}
The @Valid annotation tells Spring to validate the form. The BindingResult contains the result of the validation. If the form is invalid, the hasErrors() method will return true and we can return the form to the user with the error messages.
In addition to the built-in constraints, we can define our own custom constraints. To do this, we need to create a annotation and a validator class.
Let's say we want to create a custom constraint to check if the password and confirm password fields match. We can create a custom annotation like this:
@Documented
@Constraint(validatedBy = PasswordMatchesValidator.class)
@Target({ TYPE, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface PasswordMatches {
String message() default "Passwords do not match";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
And a validator class like this:
public class PasswordMatchesValidator implements ConstraintValidator<PasswordMatches, Object> {
@Override
public void initialize(PasswordMatches constraintAnnotation) {
}
@Override
public boolean isValid(Object obj, ConstraintValidatorContext context){
User user = (User) obj;
return user.getPassword().equals(user.getConfirmPassword());
}
}
We can then annotate the confirm password field with the @PasswordMatches annotation:
public class RegistrationForm {
//...
@NotNull
@Size(min = 6, max = 40)
@PasswordMatches
private String confirmPassword;
//...
}
In this article, we've seen how to use the Bean Validation API to validate user input in a Spring Boot application. We've also seen how to create custom constraints.