javabean-validationvalidationgroup

How to set default group in bean validation context


I'm working with bean validations and I'm searching for a possibility to set a default group of my own bean validation annotation.

I have something (working) like this:

Application.class (calling validate on MyBean)

public class Application {
    public static void main(String[] args) {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<MyBean>> violations =
            validator.validate(new MyBean(), SecondStep.class);
    }
}

MyBean.class (the bean itself; here is what I want to prevent)

public class MyBean {
    // I don't want to write this "groups" attribute every time, because it's very clear,
    // that this should only be validated for the second step, isn't it?
    @RequiredBySecondStep(groups=SecondStep.class)
    private Object myField;
}

RequiredBySecondStep.class (the bean validation annotation)

@Documented
@Target(FIELD)
@Retention(RUNTIME)
@Constraint(validatedBy = RequiredBySecondStepValidator.class)
public @interface RequiredBySecondStep {
    String message() default "may not be null on the second step";
    Class<?>[] groups() default {};   // <-- here I want to set SecondStep.class
    Class<? extends Payload>[] payload() default {};
}

RequiredBySecondStepValidator.class (an implemented constraint validator)

public class RequiredBySecondStepValidator implements ConstraintValidator<RequiredBySecondStep, Object> {
    public void initialize(RequiredBySecondStep constraintAnnotation) {
    }

    public boolean isValid(Object object, ConstraintValidatorContext constraintContext) {
        return object != null;
    }
}

SecondStep.class (the bean validation group)

public interface SecondStep {
}

Unfortunately, it's not possible by specification, to set the default group in the RequiredBySecondStep annotation like this:

Class<?>[] groups() default SecondStep.class;
// and using just the following in the bean:
@RequiredBySecondStep
private Object myField;

This will result in a RuntimeException:

javax.validation.ConstraintDefinitionException: Default value for groups() must be an empty array

Furthermore, there is not only a SecondStep. There are probably 5 different groups which I want to annotate directly with a @RequiredByFirstStep or @RequiredByFifthStep.

Is there a good way to implement this?


Solution

  • I think you got it all a bit wrong. There is indeed to way to do what you want and that's because the aspect of constraints and their validation via a ConstraintValidator is orthogonal to groups and groups sequences. Per design a constraint (annotation and its validator) should be independent of the group getting validated. Even if you would get this to work, it would not be portable constraints. Personally, I would re-think what you want to achieve. @RequiredByFirstStep does not tell you what the requirement is. You should develop constraints which imply what they are valiating (a string length, not null, etc), when or better in which condition they are executed is a then controlled by group interfaces.