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 Annotations (as of Hibernate 3.5.x).
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
s describing each
failure.
If Hibernate Validator is present in the classpath, Hibernate
Annotations (or Hibernate EntityManager) 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
Core, 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 seperated 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.
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:
Configure the executable types globally via the XML
descriptor META-INF/validation.xml
; see Section 7.1, “Configuring the validator factory in
validation.xml” for an
example
Use the @ValidateOnExecution
annotation on the executable or type level
If several sources of configuration are specified for a given
executable, @ValidateOnExecution
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
WildFly, 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.
Copyright © 2009 - 2013 Red Hat, Inc. & Gunnar Morling