[hibernate-dev] [Bean Validation] Type-safe Validator and resolution algorithm

Emmanuel Bernard emmanuel at hibernate.org
Fri Jan 23 15:13:37 EST 2009


Today, ConstraintValidator accepts Object and the implementation is  
responsible for handling the casting and raise an exception if the  
type is not supported.

The idea is to get type-safe validator and a discovery mechanism to  
associate a validator to a given runtime type being validated. The  
resolution is not 100% complete, you might end up with:
  - no valid validator
  - no way to decide between two or more validators
and get exceptions at runtime.

I would really like feedback on it as we could arrange some of these  
rules to not fail (at least in the latter case):
  - do we want this type-safe + auto resolution algorithm strategy or  
should we stick with the untyped solution
  - do we want to fail in case of ambiguity or rather choose the first  
compatible provider?

Personally I find the feature quite elegant and the metadata can be  
used by tools to warn a user if a constraint does not match the static  
type it is applied on.

API and declaration

A more typesafe proposal would be:

public interface ConstraintValidator<A extends Annotation, T> {
     void initialize(A annotation);
     boolean isValid(T object, ConstraintValidationContext context);
}

public class StringSizeValidator implements ConstraintValidator<Size,  
String> {
    ...
}

public class CollectionSizeValidator implements  
ConstraintValidator<Size, Collection> {
    ...
}

public class MapSizeValidator implements ConstraintValidator<Size,  
Map> {
    ...
}

public class ArraySizeValidator implements ConstraintValidator<Size,  
Object[]> {
    ...
}


@Constraint(validatedBy={
     StringSizeValidator.class, CollectionSizeValidator.class,
     MapSizeValidator.class, ArraySizeValidator.class} )
public @interface Size { ... }

We then need to decide at runtime, which validator needs to be executed.
Here is a proposed algorithm heavily based on the Java Language  
Specification (boy it's hard to read it).

Resolution algorithm
The type T of a ConstraintValidator must not make direct use of  
generics itself.

This is because the algorithm compare the actual type at runtime and  
such notion would be lost. So you can do ConstraintValidator<Size,  
Collection> but not ConstraintValidator<Size, Collection<String>>.

For a given runtime object t of type T about to be validated for a  
given constraint:
if t is null the first validator in the array of available validators  
is used.
otherwise

A validator accepting U is said to be compliant with the type T if T  
is a subtype of U according to the JLS chapter 4.10.

If no compliant validator is found for T, a  
UnexpectedTypeForConstraint exception is raised.
If a validator is taking the responsibility to dispatch types (ie  
ConstraintValidator<Size,Object>), it must use the same exception in  
the same circumstances.

If one compliant validator is found, it is used.

If more than one compliant validator is found, the one with the most  
specific parameter is used. The informal intuition is that one  
parameter is more specific than another if any assignment handled by  
the first parameter could be passed on to the other one without a  
compile-time type error.

Of a given type T, a compliant validator accepting U is considered  
maximally specific if no other T compliant validator accepting V is  
such as V is a strict subtype of U. String subtype is defined by JSL  
chapter 4.10.

If more than one maximally specific validator is found, a  
AmbiguousValidatorException is raised.

WDYT?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/hibernate-dev/attachments/20090123/f70741f6/attachment.html 


More information about the hibernate-dev mailing list