Hibernate Validator FAQ
Hibernate Validator FAQ
You’ve got burning question? We might have the answer for you.
- How do I check that two fields of my bean have the same value?
- How can I access the Hibernate Session or EntityManager within a ConstraintValidator?
- Can I declare constraints dynamically at runtime?
- How can I find out which constraints are declared for a given class or property?
- Is it possible to determine whether a given constraint is specified at field or property level using the metadata API?
- When using the HV annotation processor, I’m getting a compilation error like "Incompatible types, found: XY, required XY" - what’s wrong?
- How can I avoid the error "HV000150: The constraint 'javax.validation.constraints.DecimalMin' defines multiple validators for the type 'interface javax.money.MonetaryAmount'. Only one is allowed."
Hibernate Validator 3.x and 4.x/5.x are different codebases.
Hibernate Validator is the original validation framework from the Hibernate team and is now referred to as "Legacy Hibernate Validator". Hibernate Validator 4.x is the reference implementation of Bean Validation 1.0 (JSR 303), while Hibernate Validator 5.x is the reference implementation of Bean Validation 1.1 (JSR 349). Active development happens on the 5.x codebase.
The short answer is call
EntityManager#flush() if you want the validation to be triggered.
Hibernate ORM and a few other ORMs try to batch as many operations as possible when accessing the database. It is likely that the actual entity "persist" operation only happens when you call
flush() or when the transaction commits.
Also, knowing which entity is about to be persisted depends on your cascading strategy and the state of your object graph. Flush is when Hibernate ORM identifies all the entities that have been changed and require database actions (see also HHH-8028).
It does, if you update Tomcat’s EL libraries.
Hibernate Validator 5 requires the Unified Expression Language (EL) in version 2.2 or later. While Tomcat 7 provides EL 2.2 out of the box, Tomcat 6 only comes with an EL 2.1 implementation which does not work with Hibernate Validator. You will get:
You can therefore either upgrade to Tomcat 7 or update the EL libs in your Tomcat 6 installation. To do the latter, replace the JAR files el-api.jar and and jasper-el.jar in $CATALINE_HOME/lib with an EL 2.2 implementation, e.g. from Tomcat 7.
Note that it is not sufficient to add an EL 2.2 implementation to your WAR and keep Tomcat’s own EL 2.1 implementation. In this case both versions will be in conflict, typically indicated by a LinkageError saying that the ExpressionFactory class has been loaded twice by different class loaders.
By implementing a class-level constraint.
See this example.
Yes, using the API for programmatic constraint declaration.
This Hibernate Validator specific API is useful, if for instance you need to adapt constraint parameters based on some runtime configuration or when dealing with multi-tenancy, where different constraints should be applied to given types based on a specific tenant.
To use the API, obtain a ConstraintMapping from HibernateValidatorConfiguration, configure it as needed and pass it back to the configuration:
HibernateValidatorConfiguration configuration = Validation .byProvider( HibernateValidator.class ) .configure(); ConstraintMapping constraintMapping = configuration.createConstraintMapping(); constraintMapping .type( Address.class ) .property( "street1", FIELD ) .constraint( new NotNullDef() ) .property( "zipCode", FIELD ) .ignoreAnnotations() .constraint( new NotNullDef() ) .constraint( new SizeDef().min( 2 ).max( 6 ) ); Validator validator = configuration.addMapping( constraintMapping ) .buildValidatorFactory() .getValidator();
You can do so using the constraint metadata API.
Is it possible to determine whether a given constraint is specified at field or property level using the metadata API?
PropertyDescriptor property = validator.getConstraintsForClass(Address.class) .getConstraintsForProperty("street1"); Set<ConstraintDescriptor<?>> fieldConstraints = property .findConstraints() .lookingAt(Scope.LOCAL_ELEMENT) .declaredOn(ElementType.FIELD) .getConstraintDescriptors(); Set<ConstraintDescriptor<?>> propertyConstraints = property .findConstraints() .lookingAt(Scope.LOCAL_ELEMENT) .declaredOn(ElementType.METHOD) .getConstraintDescriptors();
The key is the use of the +findConstraints()+ fluent API. You have three ways to restrict the metadata:
declaredOn(ElementType... types): defines where to look the constraints (METHOD, FIELD etc)
lookingAt(Scope scope): defines whether to look for constraints hosted on superclass/interfaces or not
unorderedAndMatchingGroups(Class<?>... groups): restrict to the constraints matching a given set of groups for this element
When using the HV annotation processor, I’m getting a compilation error like "Incompatible types, found: XY, required XY" - what’s wrong?
This is caused by a bug in the javac compiler and occurs when the compiled project contains an annotation type with an enum-typed member which has a default value. As workaround either specify the default value using its fully qualified name or add this annotation processor to your project. See also HV-498 for more details.
How can I avoid the error "HV000150: The constraint 'javax.validation.constraints.DecimalMin' defines multiple validators for the type 'interface javax.money.MonetaryAmount'. Only one is allowed."
You’ll get this error with Hibernate Validator 5.4 and later if you have the dependency org.zalando:money-validation on your classpath. The money-validation project has been contributed to the Hibernate Validator code base, i.e. Hibernate Validator allows to validate
MonetaryAmount out of the box. Remove the money-validation dependency from your classpath to avoid the conflict with the constraint validators now built into Hibernate Validator.