简体   繁体   中英

Different validations on same field based on active validation group

I am trying to validate a request object using Hibernate Validator .

As a simple example assume that the class of the object I am trying to validate has a B bObj field where B is another class that has a String name field .

For that reason, I have implemented my own custom Constraint Annotations linked to custom MyValidator implements ConstraintValidator classes.

DTO class

@AclassValidate(groups = {Operations.Insert.class, Operations.Update.class javax.validation.groups.Default.class})
public class A {

    @BclassValidate(groups = {Operations.Insert.class, Operations.Update.class})
    private B bObj;

    // setters, getters
}

My endpoint method signature (where validator gets invoked, and the active group is set):

@PostMapping("/test")
public A createA(
        @Validated(value = Operations.Insert.class) 
        // @Validated(value = Operations.Update.class) 
        @RequestBody A a
)

My validator class

public class BclassValidator implements ConstraintValidator<BclassValidate, B> {

    public void initialize(BclassValidate constraintAnnotation) {
    }

    public boolean isValid(B b, ConstraintValidatorContext constraintContext) {

        boolean valid = true;

        // Get active group here
        activeGroup = ..?
        if (activeGroup == Operations.Insert.class) {
            // check if b.getName() equals to "John"
        }
        else if (activeGroup == Operations.Update.class) {
            // check if b.getName() equals to "Doe"
        }

        return valid;
    }
}

What I want to achieve is to apply different validations for the same field based on the active group. The active group is the group, set at @Validated annotation. The question is how can I retrieve the active group in order to apply different validations based on its value?

You cannot get hold of the currently validated group(s) from within a constraint validator.

Instead you should split up your constraint into several ones, in your case one for inserts and one for updates. Then you can assign these individual constraints to one validation group each.

You should get the active validation groups like this:

public class BclassValidator implements ConstraintValidator<BclassValidate, B> {

    public void initialize(BclassValidate constraintAnnotation) {
    }

    public boolean isValid(B b, ConstraintValidatorContext constraintContext) {

        boolean valid = true;

        // Get active group here
        Set<Class<?>> activeGroups = null;
        if (context instanceof ConstraintValidatorContextImpl) {
            activeGroups = ((ConstraintValidatorContextImpl) context).getConstraintDescriptor().getGroups();
        } else {
            activeGroups = Collections.emptySet();
        }

        if (activeGroups.contains(Operations.Insert.class)) {
            // check if b.getName() equals to "John"
        }
        else if (activeGroups.contains(Operations.Update.class)) {
            // check if b.getName() equals to "Doe"
        }

        return valid;
    }
}

Hibernate validator validating the currently active groups with the configured groups for custom constraints, so we no need to write logic to validate it. But there is no way to find the currently active groups.

Reason : 'valueContext' is holding the currently active group, but not passing to 'isValid' method.

https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM