On Wed, Aug 29, 2012 at 4:03 AM, Emmanuel Bernard
<emmanuel(a)hibernate.org> wrote:
I would like to bring home cross parameter validation which is one of
the main open issues in method validation.
We have been discussing it for literally 11 months, it's time to converge. If you
could give your feedback quickly, Gunnar
might be able to add it to the spec in the next few days. I am already pushing him harder
than I should to
move BV forward so give him some help :)
The following is a less readable copy of what you can find at
http://beanvalidation.org/proposals/BVAL-232/
### Cross parameter validation and return value
Do we agree that validating both the parameters and the return value in a single
constraint validator is not a use case we want to cover?
To me that would be awkward to support it as we would need to execute the method
to validate it.
+1, yet nothing should be done to preclude adding this in a later
version of the spec.
### Where to host cross-parameter constraints
We use the method as host to the return value constraints and possibly `@Valid`.
That is unfortunately also the natural place for cross parameter constraints.
I cannot think of another place to put them. There is also no easy way to add a
visual cue and differentiate a regular constraint from a cross param constraint
except by its meta annotation. We would rely on the user adding a visual cue in
the constraint name. Which kind of cue? Put `param` in the constraint name?
In the end this is not something that should be enforced anyway, so I
suspect far too much thought has been given to it already. ;) Using
the CheckRetypedPasswordParameter example, I would personally prefer
CheckRetypedPasswordParams and extrapolate that to "ends with
'Params'". Find an example or two everyone is comfortable with,
extrapolate a *recommendation* as in the example of .@List for
multiple constraints and move on. :)
Any one can think of a better approach?
Nothing from me.
#### Bean Validation class
@interface CrossParameterConstraint {
public Class<? extends CrossParameterConstraintValidator<?, ?>>[]
validatedBy();
}
Why <?, ?> on the CPCV signature? I assume this is an error as it's
not consistent with the CheckRetypedPasswordValidator example below.
interface CrossParameterConstraintValidator<A extends Annotation> {
void initialize(A constraintAnnotation);
[...]
}
> Question: does these different annotations/interfaces affect the metadata API?
I haven't looked at the metadata API in depth where it applies to
method validation, but it might be nice to differentiate
cross-parameter constraints from return value constraints at the
metadata level to save users the trouble.
>
> Question: can the same constraint annotation be annotated by both
> `@Constraint` and `@CrossParameterConstraint`: `@ScriptAssert` is a good candidate
> Note: how does composition plays into this?
#### Constraint coder class
@CrossParameterConstraint(validatedBy=CheckRetypedPasswordValidator.class)
@interface CheckRetypedPasswordParameter {
String message() default "...";
Class<?>[] groups() default {};
class<? extends Payload>[] payload();
}
class CheckRetypedPasswordValidator implements
CrossParameterConstraintValidator<CheckRetypedPasswordParameter> {
...
}
#### User code
class AccountService {
//cross param constraints
@CheckRetypedPasswordParameter
//return value constraints
@Valid @NotNull
User createUser(@NotEmpty String username, @Email String email, String password,
String retypedPassword);
}
### What is the cross parameter constraint validator contract?
There has been two leading proposals. the others are described in the
[previous proposal][previous proposal].
#### Generic approach
interface CrossParameterConstraintValidator<A extends Annotations> {
void initialize(...) { ... }
boolean isValid(Object[] parameterValues, ConstraintValidatorContext context);
}
#### Type-safe approach (with annotation processors)
A more type-safe approach is to reuse the parameters signature of the method to match.
While the Java compiler cannot discover problems, both an annotation processor and the
bean validation provider at runtime
can detect inconsistent contracts and raise respectively compilation errors and
deployment time exception.
class CheckRetypedPasswordValidator implements
CrossParameterConstraintValidator<CheckRetypedPasswordParameter> {
void initialize(...) { ... }
boolean isValid(String username, String email, String password, String
retypedPassword,
ConstraintValidatorContext context) {
...
}
}
#### Discussions
I think we must put the generic approach in because that's the only way to write non
method specific cross parameter constraints. Two examples of such constraints are
- script based constraints
- generic password retype checks based on the parameter indexes
`@AreEqual(indexes={2,3}, message="Passwords must be identical")`
So the remaining question is do we also support the type-safe approach in parallel?
I am inclined to think yes. We can do it on the same `CrossParameterConstraintValidator`
implementation:
class CheckRetypedPasswordValidator implements
CrossParameterConstraintValidator<CheckRetypedPasswordParameter> {
void initialize(...) { ... }
boolean isValid(Object[] parameterValues, ConstraintValidatorContext context);
boolean isValid(String username, String email, String password, String
retypedPassword,
ConstraintValidatorContext context) {
...
}
}
If the method validated has a matching signature, we use it, otherwise we use the
generic
method.
I am inclined to think this can be done as an implementation detail of
a given CPCV. However, is it intended that multiple CPCV impls might
be enabled for a given CPC type, each presumably handling a different
method signature? It might actually be simpler in the long run to
promote the type-safe approach such that at most one CPCV with no
typesafe declarations could be enabled. Perhaps the spec should
provide an abstract TypesafeCrossParameterConstraintValidator that
makes the correct typesafe call. Perhaps this class could provide a
method to check whether a given signature is supported, or this method
could be specified on the CPCV interface.
Do we keep the generic `isValid` method on the interface, thus
forcing people to implement
it? Or is that an optional non constrained contract?
I am tempted to think that forcing is a better approach (the implementation can raise an
exception). Thoughts?
+1
Matt
[jira]:
https://hibernate.onjira.com/browse/BVAL-232
[previous proposal]: /proposals/BVAL-241/#cross_parameter
_______________________________________________
beanvalidation-dev mailing list
beanvalidation-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/beanvalidation-dev