Building Dynamic Spring Boot Validators

Anh Trần Tuấn - Feb 27 - - Dev Community

1. Understanding Dynamic Validators

Dynamic validators are designed to handle validation logic that cannot be predetermined or is subject to change based on various conditions. Unlike static validators which are predefined, dynamic validators adapt their behavior at runtime.

Image

1.1 Why Use Dynamic Validators?

Dynamic validators offer several benefits:

  • Flexibility : They allow validation rules to be altered based on user inputs or external conditions.
  • Reusability : These validators can be reused across different parts of the application with varying rules.
  • Maintainability : Changes to validation rules can be made without modifying the core validation logic.

1.2 Use Cases

Dynamic validators are useful in scenarios where:

  • Validation rules are not fixed and may vary based on user roles or configurations.
  • Different entities require similar but slightly different validation logic.
  • Business rules change frequently and need to be reflected immediately without code changes.

2. Implementing Dynamic Validators in Spring Boot

To illustrate dynamic validators, we'll use a practical example. Let’s consider an application that requires user data validation, where the validation rules can change based on user roles or other dynamic conditions.

2.1 Setting Up the Project

First, ensure you have a Spring Boot project set up. Add the necessary dependencies for validation in your pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Enter fullscreen mode Exit fullscreen mode

2.2 Creating a Dynamic Validator

We'll create a custom dynamic validator using Validator interface. Here’s a step-by-step approach:

Define the Validator Interface

Create an interface for the dynamic validator:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public interface DynamicValidator<T> extends ConstraintValidator<DynamicConstraint, T> {
    void setValidationCriteria(String criteria);
}
Enter fullscreen mode Exit fullscreen mode

Implement the Validator

Implement the DynamicValidator interface. For this example, let’s build a validator that checks if a string contains a specific keyword based on dynamic criteria:

import javax.validation.ConstraintValidatorContext;

public class KeywordValidator implements DynamicValidator<String> {

    private String criteria;

    @Override
    public void initialize(DynamicConstraint constraintAnnotation) {
        // No initialization needed
    }

    @Override
    public void setValidationCriteria(String criteria) {
        this.criteria = criteria;
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && value.contains(criteria);
    }
}
Enter fullscreen mode Exit fullscreen mode

Create a Custom Annotation

Create a custom annotation to use the validator:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Constraint(validatedBy = KeywordValidator.class)
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DynamicConstraint {
    String message() default "Invalid value";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
Enter fullscreen mode Exit fullscreen mode

2.3 Configuring the Validator at Runtime

Now, let’s configure the validator to use dynamic criteria:

import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

import javax.validation.ConstraintValidatorContext;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

public class ValidatorConfig {

    private Validator validator;

    public ValidatorConfig() {
        ValidatorFactory factory = new LocalValidatorFactoryBean();
        this.validator = factory.getValidator();
    }

    public void validate(String value, String criteria) {
        KeywordValidator keywordValidator = (KeywordValidator) validator.getConstraintsForClass(String.class)
                .getConstraintValidators().iterator().next();
        keywordValidator.setValidationCriteria(criteria);
        boolean isValid = keywordValidator.isValid(value, null);
        System.out.println("Validation result: " + isValid);
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Testing the Dynamic Validator

To ensure our dynamic validator works as expected, let’s test it with different criteria.

3.1 Example Test Case

public class DynamicValidatorTest {

    public static void main(String[] args) {
        ValidatorConfig validatorConfig = new ValidatorConfig();

        // Test with different criteria
        validatorConfig.validate("Hello World", "World"); // Expected output: true
        validatorConfig.validate("Hello World", "Java"); // Expected output: false
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Conclusion

Dynamic validators offer a flexible approach to validation, enabling your Spring Boot application to adapt to changing requirements effortlessly. By implementing dynamic validators, you can ensure that your application remains robust and maintainable even as validation needs evolve.

Feel free to ask any questions or share your thoughts in the comments below!

Read posts more at : Building Dynamic Spring Boot Validators

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .