I also need this Non-intrusive constraint declaration - I have a domain model annotated with JPA annotations and I'm not permitted to add constraint annotations on it or change it in any other way.
I think the xml is ok, but first there should be a way to do it programatically. The problem is with this
message per constraint annotation instance. I think we can live only with the default one also. The same goes for the groups - so I will just skip them.
Further
the constraint annotation is linked statically (compile-time) to the constraint validator via @ConstraintValidator annotation on it.
This is nice for the default approach.
But in a more dynamic world one can workaround this in runtime via bytecode modification - inject @ConstraintValidator in a @Column (JPA) annotation (not sure if it is possible :)?
What about inventing a ConstraintRepository and ConstraintDescriptor :
Code:
public interface ConstraintRepository {
ConstraintDescriptor getConstraintDescriptor(Annotation constraintAnnotation);
}
public interface ConstraintDescriptor {
Constraint getConstraint();
String getDefaultMessage();
String[] getDefaultGroups();
}
I haven't played with the model above, but I think it will be a nice option. As I see the way the ClassValidator in hibernate obtains the validator (Constraint in the JSR) :
Code:
private Validator createValidator(Annotation annotation) {
try {
ValidatorClass validatorClass = annotation.annotationType().getAnnotation( ValidatorClass.class );
if ( validatorClass == null ) {
return null;
}
// ...
This can be configured to be optional or enforced depending on the intent, but something like this:
Code:
if ( validatorClass == null ) {
ConstraintDescriptor cd = contraintRepository.getConstraintDescriptor(annotation);
if (cd != null) {
validatorClass = cd.getConstraint();
} else {
return null;
}
}
Ok, I have mixed the JSR API and the Hibernate APIs, but I hope you get the idea.
Even if you don't like to complicate the API it will be at least nice if there is a way to extend it like this, so that the base is reusable somehow..