2

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?

pirox22
  • 892
  • 1
  • 14
  • 30

3 Answers3

1

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.

Gunnar
  • 18,095
  • 1
  • 53
  • 73
0

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;
    }
}
fluminis
  • 3,575
  • 4
  • 34
  • 47
  • 1
    This is not what the OP asked for. In your implementation, `activeGroups` will contain all the groups passed within the annotation, not the currently active validating group set by `@Validated` annotation – antonis Sep 26 '20 at 15:09
0

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

enter image description here

Kishor K
  • 1,435
  • 12
  • 16