[bv-dev] Method validation: cross-parameter constraints

Gunnar Morling gunnar.morling at googlemail.com
Sun Feb 26 06:21:11 EST 2012


Hi all,

one of the larger open points related to method validation is how to
support cross-parameter constraints.

The BVAL-241 proposal discusses pro's and con's of several variants
[1]. The different options are:

#1 - Don't support cross-parameter constraints in BV 1.1

#2 - New interface MethodConstraintValidator

public interface MethodConstraintValidator<A extends Annotation> {

    void initialize(A constraintAnnotation);

    boolean isValid(Object[] parameterValues,
ConstraintValidatorContext context);
}

#3 - Invoke validator methods by signature matching

public class DateParameterCheckValidator implements
Initializable<DateParameterCheck> {

    //defined in Initializable
    public void initialize(DateParameterCheck constraint) {}

    //invoked by convention for methods annotated with
@DataParameterCheck and the argument types Customer, Date, Date
    public boolean isValid(Customer customer, Date from, Date to,
ConstraintValidatorContext context) { ... }

    //invoked by convention for methods annotated with
@DataParameterCheck and the argument types Customer, Date, Date, Date
    public boolean isValid(Customer customer, Date from, Date to, Date
alternativeTo, ConstraintValidatorContext context) { ... }
}

#4 - Script based approach

public class ReservationService {

    @ParameterAssert(script="arg1.before(arg2)", lang="javascript")
    void bookHotel(@NotNull Customer customer, @NotNull Date from,
@NotNull Date to) { ... }
}

#5 Parametrized interfaces MethodConstraintValidatorN for N method parameters

public interface MethodConstraintValidator3<A extends Annotation, T1, T2, T3> {

    void initialize(A constraintAnnotation);

    boolean isValid(T1 parameter1, T2 parameter2, T3 parameter3,
ConstraintValidatorContext context);
}

public class DateParameterCheckValidator implements
MethodConstraintValidator3<DateParameterCheck, Customer, Date, Date> {

    public void initialize(DateParameterCheck constraint) {}

    public boolean isValid(Customer customer, Date from, Date to,
ConstraintValidatorContext context) { ... }
}

Please refer to the proposal document [1] for the individual pro's and
con's. Emmanuel, Hardy and I also discussed this on GitHub [2]:

* our preference is generally for something around #2 and #3
* we might offer a mixed approach, both supporting #2 *and* #3

While #2 would define a more strict MethodConstraintValidator contract
it would require implementors to do some ugly casts. #3 has a less
strict MethodConstraintValidator contract (it works by convention) but
would provide implementors a more typed experience.

Personally I think both approaches actually aren't that much
different. Both are inherently type-unsafe, but #3 would move the
efforts for dealing with that away from the constraint implementor
towards the BV provider. Note that #3 could also be checked by an
annotation processor, while #2 couldn't.

Note also that all approaches are somewhat inconsistent compared to
"normal" parameter and return value constraints, as they are based on
a method-level annotation (opposed to parameter-level). But I don't
see really a way around that.

What do you other folks think about that? Which approach would you
prefer, and why? Do you have another idea altogether?

@Emmanuel: For the first BV 1.1 draft I suggest to leave out
cross-parameter constraints. This shouldn't change the general scheme
of method validation, so we could add that in a later draft revision.

--Gunnar


[1] http://beanvalidation.org/proposals/BVAL-241/#cross_parameter
[2] https://github.com/beanvalidation/beanvalidation.org/commit/bc37cfec514b79f7695ccb35f9990115c5fdeab8#commitcomment-968467


More information about the beanvalidation-dev mailing list