Hibernate.orgCommunity Documentation
Hibernate Validator is intended to be used to implement multi-layered data validation, where constraints are expressed in a single place (the annotated domain model) and checked in various different layers of the application. For this reason there are multiple integration points with other technologies.
Hibernate Validator integrates with both Hibernate and all pure Java Persistence providers.
When lazy loaded associations are supposed to be validated it is recommended to place the constraint on the getter of the association. Hibernate replaces lazy loaded associations with proxy instances which get initialized/loaded when requested via the getter. If, in such a case, the constraint is placed on field level the actual proxy instance is used which will lead to validation errors.
Out of the box, Hibernate (as of version 3.5.x) will translate the constraints you have defined for
your entities into mapping metadata. For example, if a property of your entity is annotated
@NotNull
, its columns will be declared as not null
in the DDL schema generated by Hibernate.
If, for some reason, the feature needs to be disabled, set hibernate.validator.apply_to_ddl
to
false
. See also Table 2.2, “Bean Validation constraints” and Table 2.3, “Custom constraints”.
You can also limit the DDL constraint generation to a subset of the defined constraints by setting
the property org.hibernate.validator.group.ddl
. The property specifies the comma-separated, fully
specified class names of the groups a constraint has to be part of in order to be considered for DDL
schema generation.
Hibernate Validator has a built-in Hibernate event listener -
org.hibernate.cfg.beanvalidation.BeanValidationEventListener
-
which is part of Hibernate ORM. Whenever a PreInsertEvent
,
PreUpdateEvent
or PreDeleteEvent
occurs, the listener will verify all constraints of the entity
instance and throw an exception if any constraint is violated. Per default objects will be checked
before any inserts or updates are made by Hibernate. Pre deletion events will per default not
trigger a validation. You can configure the groups to be validated per event type using the
properties javax.persistence.validation.group.pre-persist
,
javax.persistence.validation.group.pre-update
and javax.persistence.validation.group.pre-remove
.
The values of these properties are the comma-separated, fully specified class names of the groups
to validate. Example 10.1, “Manual configuration of BeanValidationEvenListener
” shows the default values for these
properties. In this case they could also be omitted.
On constraint violation, the event will raise a runtime ConstraintViolationException
which contains
a set of ConstraintViolation
instances describing each failure.
If Hibernate Validator is present in the classpath, Hibernate ORM will use it transparently.
To avoid validation even though Hibernate Validator is in the classpath set
javax.persistence.validation.mode
to none.
If the beans are not annotated with validation annotations, there is no runtime performance cost.
In case you need to manually set the event listeners for Hibernate ORM, use the following configuration in hibernate.cfg.xml:
Example 10.1. Manual configuration of BeanValidationEvenListener
<hibernate-configuration>
<session-factory>
...
<property name="javax.persistence.validation.group.pre-persist">
javax.validation.groups.Default
</property>
<property name="javax.persistence.validation.group.pre-update">
javax.validation.groups.Default
</property>
<property name="javax.persistence.validation.group.pre-remove"></property>
...
<event type="pre-update">
<listener class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener"/>
</event>
<event type="pre-insert">
<listener class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener"/>
</event>
<event type="pre-delete">
<listener class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener"/>
</event>
</session-factory>
</hibernate-configuration>
If you are using JPA 2 and Hibernate Validator is in the classpath the JPA2 specification requires
that Bean Validation gets enabled. The properties javax.persistence.validation.group.pre-persist
,
javax.persistence.validation.group.pre-update
and javax.persistence.validation.group.pre-remove
as
described in Section 10.1.2, “Hibernate event-based validation” can in this case be configured in
persistence.xml. persistence.xml also defines a node validation-mode which can be set to AUTO
,
CALLBACK
, NONE
. The default is AUTO
.
In a JPA 1 you will have to create and register Hibernate Validator yourself. In case you are using
Hibernate EntityManager you can add a customized version of the BeanValidationEventListener
described in Section 10.1.2, “Hibernate event-based validation” to your project and register it
manually.
When working with JSF2 or JBoss Seam and Hibernate Validator (Bean Validation) is present in the
runtime environment, validation is triggered for every field in the application. Example 10.2, “Usage of Bean Validation within JSF2”
shows an example of the f:validateBean
tag in a JSF page. The validationGroups
attribute is optional
and can be used to specify a comma separated list of validation groups. The default is
javax.validation.groups.Default
. For more information refer to the Seam documentation or the JSF 2
specification.
Example 10.2. Usage of Bean Validation within JSF2
<h:form>
<f:validateBean validationGroups="javax.validation.groups.Default">
<h:inputText value=#{model.property}/>
<h:selectOneRadio value=#{model.radioProperty}> ... </h:selectOneRadio>
<!-- other input components here -->
</f:validateBean>
</h:form>
The integration between JSF 2 and Bean Validation is described in the "Bean Validation Integration"
chapter of JSR-314. It is interesting to know that JSF
2 implements a custom MessageInterpolator
to ensure ensure proper localization. To encourage the use
of the Bean Validation message facility, JSF 2 will per default only display the generated Bean
Validation message. This can, however, be configured via the application resource bundle by
providing the following configuration ({0}
is replaced with the Bean Validation message and {1}
is
replaced with the JSF component label):
javax.faces.validator.BeanValidator.MESSAGE={1}: {0}
The default is:
javax.faces.validator.BeanValidator.MESSAGE={0}
As of version 1.1, Bean Validation is integrated with CDI (Contexts and Dependency Injection for JavaTM EE).
This integration provides CDI managed beans for Validator
and ValidatorFactory
and enables
dependency injection in constraint validators as well as custom message interpolators, traversable
resolvers, constraint validator factories and parameter name providers.
Furthermore, parameter and return value constraints on the methods and constructors of CDI managed beans will automatically be validated upon invocation.
When your application runs on a Jave EE container, this integration is enabled by default. When working with CDI in a Servlet container or in a pure Java SE environment, you can use the CDI portable extension provided by Hibernate Validator. To do so, add the portable extension to your class path as described in Section 1.1.2, “CDI”.
CDI’s dependency injection mechanism makes it very easy to retrieve ValidatorFactory
and Validator
instances and use them in your managed beans. Just annotate instance fields of your bean with
@javax.inject.Inject
as shown in Example 10.3, “Retrieving validator factory and validator via @Inject
”.
Example 10.3. Retrieving validator factory and validator via @Inject
package org.hibernate.validator.referenceguide.chapter10.cdi.validator;
@ApplicationScoped
public class RentalStation {
@Inject
private ValidatorFactory validatorFactory;
@Inject
private Validator validator;
//...
}
The injected beans are the default validator factory and validator instances. In order to configure them - e.g. to use a custom message interpolator - you can use the Bean Validation XML descriptors as discussed in Chapter 7, Configuring via XML.
If you are working with several Bean Validation providers you can make sure that factory and
validator from Hibernate Validator are injected by annotating the injection points with the
@HibernateValidator
qualifier which is demonstrated in Example 10.4, “Using the @HibernateValidator
qualifier annotation”.
Example 10.4. Using the @HibernateValidator
qualifier annotation
package org.hibernate.validator.referenceguide.chapter10.cdi.validator.qualifier;
@ApplicationScoped
public class RentalStation {
@Inject
@HibernateValidator
private ValidatorFactory validatorFactory;
@Inject
@HibernateValidator
private Validator validator;
//...
}
The fully-qualified name of the qualifier annotation is
org.hibernate.validator.cdi.HibernateValidator
. Be sure to not import
org.hibernate.validator.HibernateValidator
instead which is the ValidationProvider
implementation
used for selecting Hibernate Validator when working with the bootstrapping API (see
Section 8.1, “Retrieving ValidatorFactory
and Validator
”).
Via @Inject
you also can inject dependencies into constraint validators and other Bean Validation
objects such as MessageInterpolator
implementations etc.
Example 10.5, “Constraint validator with injected bean”
demonstrates how an injected CDI bean is used in a ConstraintValidator
implementation to determine
whether the given constraint is valid or not. As the example shows, you also can work with the
@PostConstruct
and @PreDestroy
callbacks to implement any required construction and destruction
logic.
Example 10.5. Constraint validator with injected bean
package org.hibernate.validator.referenceguide.chapter10.cdi.injection;
public class ValidLicensePlateValidator
implements ConstraintValidator<ValidLicensePlate, String> {
@Inject
private VehicleRegistry vehicleRegistry;
@PostConstruct
public void postConstruct() {
//do initialization logic...
}
@PreDestroy
public void preDestroy() {
//do destruction logic...
}
@Override
public void initialize(ValidLicensePlate constraintAnnotation) {
}
@Override
public boolean isValid(String licensePlate, ConstraintValidatorContext constraintContext) {
return vehicleRegistry.isValidLicensePlate( licensePlate );
}
}
The method interception facilities of CDI allow for a very tight integration with Bean Validation’s method validation functionality. Just put constraint annotations to the parameters and return values of the executables of your CDI beans and they will be validated automatically before (parameter constraints) and after (return value constraints) a method or constructor is invoked.
Note that no explicit interceptor binding is required, instead the required method validation interceptor will automatically be registered for all managed beans with constrained methods and constructors.
The interceptor org.hibernate.validator.internal.cdi.interceptor.ValidationInterceptor
is
registered by org.hibernate.validator.internal.cdi.ValidationExtension
. This happens implicitly
within a Java EE 7 runtime environment or explicitly by adding the hibernate-validator-cdi artifact
- see Section 1.1.2, “CDI”
You can see an example in Example 10.6, “CDI managed beans with method-level constraints”.
Example 10.6. CDI managed beans with method-level constraints
package org.hibernate.validator.referenceguide.chapter10.cdi.methodvalidation;
@ApplicationScoped
public class RentalStation {
@Valid
public RentalStation() {
//...
}
@NotNull
@Valid
public Car rentCar(
@NotNull Customer customer,
@NotNull @Future Date startDate,
@Min(1) int durationInDays) {
//...
}
@NotNull
List<Car> getAvailableCars() {
//...
}
}
package org.hibernate.validator.referenceguide.chapter10.cdi.methodvalidation;
@RequestScoped
public class RentCarRequest {
@Inject
private RentalStation rentalStation;
public void rentCar(String customerId, Date startDate, int duration) {
//causes ConstraintViolationException
rentalStation.rentCar( null, null, -1 );
}
}
Here the RentalStation
bean hosts several method constraints. When invoking one of the RentalStation
methods from another bean such as RentCarRequest
, the constraints of the invoked method are
automatically validated. If any illegal parameter values are passed as in the example, a
ConstraintViolationException
will be thrown by the method interceptor, providing detailed
information on the violated constraints. The same is the case if the method’s return value violates
any return value constraints.
Similarly, constructor constraints are validated automatically upon invocation. In the example the
RentalStation
object returned by the constructor will be validated since the constructor return
value is marked with @Valid
.
Bean Validation allows for a fine-grained control of the executable types which are automatically
validated. By default, constraints on constructors and non-getter methods are validated. Therefore
the @NotNull
constraint on the method RentalStation#getAvailableCars()
in
Example 10.6, “CDI managed beans with method-level constraints” gets not validated when the method is invoked.
You have the following options to configure which types of executables are validated upon invocation:
@ValidateOnExecution
annotation on the executable or type levelIf several sources of configuration are specified for a given executable, @ValidateOnExecutionn on
the executable level takes precedence over `@ValidateOnExecution
on the type level and
@ValidateOnExecution
generally takes precedence over the globally configured types in META-
INF/validation.xml.
Example 10.7, “Using @ValidateOnExecution
” shows how to use the @ValidateOnExecution
annotation:
Example 10.7. Using @ValidateOnExecution
package org.hibernate.validator.referenceguide.chapter10.cdi.methodvalidation.configuration;
@ApplicationScoped
@ValidateOnExecution(type = ExecutableType.ALL)
public class RentalStation {
@Valid
public RentalStation() {
//...
}
@NotNull
@Valid
@ValidateOnExecution(type = ExecutableType.NONE)
public Car rentCar(
@NotNull Customer customer,
@NotNull @Future Date startDate,
@Min(1) int durationInDays) {
//...
}
@NotNull
public List<Car> getAvailableCars() {
//...
}
}
Here the method rentCar()
won’t be validated upon invocation because it is annotated with
@ValidateOnExecution(type = ExecutableType.NONE)
. In contrast, the constructor and the
method getAvailableCars()
will be validated due to @ValidateOnExecution(type =
ExecutableType.ALL)
being given on the type level. ExecutableType.ALL
is a more compact form for
explicitly specifying all the types CONSTRUCTORS
, GETTER_METHODS
and NON_GETTER_METHODS
.
Executable validation can be turned off globally by specifying
<executable-validation enabled="false"/>
in META-INF/validation.xml. In this case, any
@ValidateOnExecution
annotations are ignored.
Note that when a method overrides or implements a super-type method the configuration will be taken
from that overridden or implemented method (as given via @ValidateOnExecution
on the method itself
or on the super-type). This protects a client of the super-type method from an unexpected alteration
of the configuration, e.g. disabling validation of an overridden executable in a sub-type.
In case a CDI managed bean overrides or implements a super-type method and this super-type method
hosts any constraints, it can happen that the validation interceptor is not properly registered with
the bean, resulting in the bean’s methods not being validated upon invocation. In this case you can
specify the executable type IMPLICIT
on the sub-class as shown in
Example 10.8, “Using ExecutableType.IMPLICIT
”, which makes sure that all required metadata is discovered
an the validation interceptor kicks in when the methods on ExpressRentalStation
are invoked.
Example 10.8. Using ExecutableType.IMPLICIT
package org.hibernate.validator.referenceguide.chapter10.cdi.methodvalidation.implicit;
@ValidateOnExecution(type = ExecutableType.ALL)
public interface RentalStation {
@NotNull
@Valid
Car rentCar(
@NotNull Customer customer,
@NotNull @Future Date startDate,
@Min(1) int durationInDays);
}
package org.hibernate.validator.referenceguide.chapter10.cdi.methodvalidation.implicit;
@ApplicationScoped
@ValidateOnExecution(type = ExecutableType.IMPLICIT)
public class ExpressRentalStation implements RentalStation {
@Override
public Car rentCar(Customer customer, Date startDate, @Min(1) int durationInDays) {
//...
}
}
When your application runs on a Java EE application server such as http://wildfly.org/,
you also can obtain Validator
and ValidatorFactory
instances via @Resource
injection in
managed objects such as EJBs etc., as shown in Example 10.9, “Retrieving Validator
and ValidatorFactory
via @Resource
injection”.
Example 10.9. Retrieving Validator
and ValidatorFactory
via @Resource
injection
package org.hibernate.validator.referenceguide.chapter10.javaee;
@Stateless
public class RentalStationBean {
@Resource
private ValidatorFactory validatorFactory;
@Resource
private Validator validator;
//...
}
Alternatively you can obtain a validator and a validator factory from JNDI under the names "java:comp/Validator" and "java:comp/ValidatorFactory", respectively.
Similar to CDI-based injection via @Inject
, these objects represent default validator and validator
factory and thus can be configured using the XML descriptor META-INF/validation.xml (see
Chapter 7, Configuring via XML).
When your application is CDI-enabled, the injected objects are CDI-aware as well and e.g. support dependency injection in constraint validators.
Hibernate Validator also provides support for the unwrapping of JavaFX properties. If JavaFX is present
on the classpath a ValidatedValueUnwrapper
for JavaFX properties is automatically registered. In some
cases, however, it is also necessary to explicitly use @UnwrapValidatedValue
. This is required if
the constraint validator resolution is not unique and there is a potential constraint validator for
the actual JavaFX property as well as the contained property value itself.
See Section 11.11.2, “JavaFX unwrapper” for examples and further discussion.