A Beginner's Guide to Creating Custom Validators in Spring

·

3 min read

In this example, we're creating a custom validator that checks if the age is greater than or equal to a specified minimum age.

First, create a custom validator by implementing the javax.validation.ConstraintValidator interface:

public class AgeValidator implements ConstraintValidator<ValidAge, Integer> {

    private int minAge;

    @Override
    public void initialize(ValidAge validAge) {
        minAge = validAge.min();
    }

    @Override
    public boolean isValid(Integer age, ConstraintValidatorContext constraintValidatorContext) {
        return age != null && age >= minAge;
    }
}

Next, create the custom annotation @ValidAge:

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AgeValidator.class)
public @interface ValidAge {
    String message() default "Invalid age";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    int min() default 18;
}

This annotation specifies that the AgeValidator class should be used to validate fields and methods annotated with @ValidAge. The message() method specifies the default error message if validation fails, and the min() method specifies the minimum age allowed (default is 18).

Now, you can use the @ValidAge annotation to validate age fields in your request objects:

public class UserRequest {
    @NotNull
    @Size(min = 5, max = 20)
    private String username;

    @NotNull
    @Email
    private String email;

    @ValidAge
    private Integer age;
    // getters and setters
}

In this example, the age field is annotated with @ValidAge, which will trigger the custom validation logic when the request is received. If the age is less than 18, the validation will fail and an error message will be returned.

That's how you can use custom validators in Spring Boot to implement more complex validation logic.

Let me explain the annotations used in the custom annotation @ValidAge:

  1. @Target({ElementType.FIELD, ElementType.METHOD}): This annotation specifies where the custom annotation can be used. In this case, the @ValidAge annotation can be applied to fields and methods.

  2. @Retention(RetentionPolicy.RUNTIME): This annotation specifies the retention policy for the custom annotation. In this case, the @ValidAge annotation will be retained at runtime, which is required for Spring Boot to use it for validation.

  3. @Constraint(validatedBy = AgeValidator.class): This annotation specifies the validator class that should be used to validate the annotated element. In this case, the AgeValidator class is used.

  4. public @interface ValidAge: This declares the custom annotation and specifies its name.

  5. String message() default "Invalid age";: This defines the default error message if validation fails.

  6. Class<?>[] groups() default {};: This specifies the validation groups that the custom annotation belongs to. Groups allow you to define different sets of validation rules for different use cases.

  7. Class<? extends Payload>[] payload() default {};: This allows you to add additional data to the validation error message. For example, you could use the payload to include the HTTP status code in the error message.

  8. int min() default 18;: This defines a default value for the minimum age allowed. This value can be overridden when the annotation is used.