Preface

Validating data is a common task that occurs throughout all
application layers, from the presentation to the persistence layer. Often
the same validation logic is implemented in each layer which is time
consuming and error-prone. To avoid duplication of these validations,
developers often bundle validation logic directly into the domain model,
cluttering domain classes with validation code which is really metadata
about the class itself.

JSR 349 - Bean Validation 1.1 - defines a metadata model and API for
entity and method validation. The default metadata source are annotations,
with the ability to override and extend the meta-data through the use of
XML. The API is not tied to a specific application tier nor programming
model. It is specifically not tied to either web or persistence tier, and is
available for both server-side application programming, as well as rich
client Swing application developers.

Hibernate Validator is the reference implementation of this JSR 349.
The implementation itself as well as the Bean Validation API and TCK are all
provided and distributed under the Apache Software License
2.0.

This transitively pulls in the dependency to the Bean Validation API
(javax.validation:validation-api:1.1.0.Final).

1.1.1. Unified EL

Hibernate Validator requires an implementation of the Unified
Expression Language (JSR
341) for evaluating dynamic expressions in constraint violation
messages (seeSection 4.1, “Default message interpolation”). When
your application runs in a Java EE container such as JBoss AS, an EL
implementation is already provided by the container. In a Java SE
environment, however, you have to add an implementation as dependency to
your POM file. For instance you can add the following two dependencies
to use the JSR 341reference
implementation:

1.1.2. CDI

Bean Validation defines integration points with CDI (Contexts and
Dependency Injection for Java
TM
EE,JSR 346). If your
application runs in an environment which does not provide this
integration out of the box, you may use the Hibernate Validator CDI
portable extension by adding the following Maven dependency to your
POM:

Note that adding this dependency is usually not required for
applications running on a Java EE application server. You can learn more
about the integration of Bean Validation and CDI inSection 10.3, “CDI”.

In the
setUp()
method a
Validator
object is retrieved from the
ValidatorFactory. A
Validator
instance is thread-safe and may be reused
multiple times. It thus can safely be stored in a static field and be used
in the test methods to validate the different
Car
instances.

The
validate()
method returns a set of
ConstraintViolation
instances, which you can
iterate over in order to see which validation errors occurred. The first
three test methods show some expected constraint violations:

The
@NotNull
constraint on manufacturer
is violated in
manufacturerIsNull()

The
@Size
constraint on licensePlate is
violated in
licensePlateTooShort()

The
@Min
constraint on seatCount is
violated in
seatCountTooLow()

If the object validates successfully,
validate()
returns an empty set as you can see in
carIsValid().

Note that only classes from the package
javax.validation
are used. These are provided from the
Bean Validation API. No classes from Hibernate Validator are directly
referenced, resulting in portable code.

1.4. Where to go next?

That concludes the 5 minute tour through the world of Hibernate
Validator and Bean Validation. Continue exploring the code examples or
look at further examples referenced inChapter 13, Further reading.

2.1. Declaring bean constraints

Constraints in Bean Validation are expressed via Java annotations.
In this section you will learn how to enhance an object model with these
annotations. There are the following three types of bean
constraints:

field constraints

property constraints

class constraints

Note

Not all constraints can be placed on all of these levels. In fact,
none of the default constraints defined by Bean Validation can be placed
at class level. The java.lang.annotation.Target
annotation in the constraint annotation itself determines on which
elements a constraint can be placed. See Chapter 6, Creating custom constraints for more information.

When using field-level constraints field access strategy is used
to access the value to be validated. This means the validation engine
directly accesses the instance variable and does not invoke the property
accessor method even if such an accessor exists.

Constraints can be applied to fields of any access type (public,
private etc.). Constraints on static fields are not supported,
though.

Tip

When validating byte code enhanced objects property level
constraints should be used, because the byte code enhancing library
won't be able to determine a field access via reflection.

Note

The property's getter method has to be annotated, not its
setter. That way also read-only properties can be constrained which
have no setter method.

When using property level constraints property access strategy is
used to access the value to be validated, i.e. the validation engine
accesses the state via the property accessor method.

Tip

It is recommended to stick either to field
or property annotations within one class. It is
not recommended to annotate a field and the
accompanying getter method as this would cause the field to be
validated twice.

2.1.3. Class-level
constraints

Last but not least, a constraint can also be placed on the class
level. In this case not a single property is subject of the validation
but the complete object. Class-level constraints are useful if the
validation depends on a correlation between several properties of an
object.

The Car class in Example 2.3, “Class-level constraint” has the two attributes
seatCount and passengers and it
should be ensured that the list of passengers has not more entries than
seats are available. For that purpose the
@ValidPassengerCount constraint is added on the
class level. The validator of that constraint has access to the complete
Car object, allowing to compare the numbers of
seats and passengers.

2.1.4. Constraint inheritance

When a class implements an interface or extends another class, all
constraint annotations declared on the supertype apply in the same
manner as the constraints specified on the class itself. To make things
clearer let's have a look at the following example:

Here the class RentalCar is a subclass of
Car and adds the property
rentalStation. If an instance of
RentalCar is validated, not only the
@NotNull constraint on
rentalStation is evaluated, but also the constraint
on manufacturer from the parent class.

The same would be true, if Car was not a
superclass but an interface implemented by
RentalCar.

Constraint annotations are aggregated if methods are overridden.
So if RentalCar overrode the
getManufacturer() method from
Car, any constraints annotated at the overriding
method would be evaluated in addition to the
@NotNull constraint from the superclass.

2.1.5. Object graphs

The Bean Validation API does not only allow to validate single
class instances but also complete object graphs (cascaded validation).
To do so, just annotate a field or property representing a reference to
another object with @Valid as demonstrated in
Example 2.5, “Cascaded validation”.

If an instance of Car is validated, the
referenced Person object will be validated as
well, as the driver field is annotated with
@Valid. Therefore the validation of a
Car will fail if the name
field of the referenced Person instance is
null.

The validation of object graphs is recursive, i.e. if a reference
marked for cascaded validation points to an object which itself has
properties annotated with @Valid, these
references will be followed up by the validation engine as well. The
validation engine will ensure that no infinite loops occur during
cascaded validation, for example if two objects hold references to each
other.

Note that null values are getting ignored
during cascaded validation.

Object graph validation also works for collection-typed fields.
That means any attributes that

are arrays

implement java.lang.Iterable
(especially Collection,
List and Set)

implement java.util.Map

can be annotated with @Valid, which will
cause each contained element to be validated, when the parent object is
validated.

2.2. Validating bean constraints

The Validator interface is the most important
object in Bean Validation. The next section shows how to obtain an
Validator instance. Afterwards you'll learn how to
use the different methods of the Validator
interface.

2.2.1. Obtaining a Validator instance

The first step towards validating an entity instance is to get
hold of a Validator instance. The road to this
instance leads via the Validation class and a
ValidatorFactory. The easiest way is to use the
static method
Validation#buildDefaultValidatorFactory():

This bootstraps a validator in the default configuration. Refer to
Chapter 8, Bootstrapping to learn more about the
different bootstrapping methods and how to obtain a specifically
configured Validator instance.

2.2.2. Validator methods

The Validator interface contains three
methods that can be used to either validate entire entities or just
single properties of the entity.

All three methods return a
Set<ConstraintViolation>. The set is empty,
if the validation succeeds. Otherwise a
ConstraintViolation instance is added for each
violated constraint.

All the validation methods have a var-args parameter which can be
used to specify, which validation groups shall be considered when
performing the validation. If the parameter is not specified the default
validation group
(javax.validation.groups.Default) is used. The
topic of validation groups is discussed in detail in Chapter 5, Grouping constraints.

Note

@Valid is not honored by
validateProperty() or
validateValue().

Validator#validateProperty() is for
example used in the integration of Bean Validation into JSF 2 (see
Section 10.2, “JSF & Seam”) to perform a validation
of the values entered into a form before they are propagated to the
model.

2.3.1. Bean Validation constraints

Table 2.2, “Bean Validation constraints” shows purpose and
supported data types of all constraints specified in the Bean Validation
API. All these constraints apply to the field/property level, there are
no class-level constraints defined in the Bean Validation specification.
If you are using the Hibernate object-relational mapper, some of the
constraints are taken into account when creating the DDL for your model
(see column "Hibernate metadata impact").

Note

Hibernate Validator allows some constraints to be applied to
more data types than required by the Bean Validation specification
(e.g. @Max can be applied to
Strings). Relying on this feature can impact
portability of your application between Bean Validation
providers.

Table 2.2. Bean Validation constraints

Annotation

Supported data types

Use

Hibernate metadata impact

@AssertFalse

Boolean,
boolean

Checks that the annotated element is
false

None

@AssertTrue

Boolean,
boolean

Checks that the annotated element is
true

None

@DecimalMax(value=,inclusive=)

BigDecimal,
BigInteger,
CharSequence,
byte, short,
int, long and the
respective wrappers of the primitive types; Additionally
supported by HV: any sub-type of
Number

Checks whether the annotated value is less than the
specified maximum, when inclusive=false.
Otherwise whether the value is less than or equal to the
specified maximum. The parameter value is
the string representation of the max value according to the
BigDecimal string representation.

None

@DecimalMin(value=,inclusive=)

BigDecimal,
BigInteger,
CharSequence,
byte, short,
int, long and the
respective wrappers of the primitive types; Additionally
supported by HV: any sub-type of
Number

Checks whether the annotated value is larger than the
specified minimum, when inclusive=false.
Otherwise whether the value is larger than or equal to the
specified minimum. The parameter value is
the string representation of the min value according to the
BigDecimal string representation.

None

@Digits(integer=,fraction=)

BigDecimal,
BigInteger,
CharSequence,
byte, short,
int, long and the
respective wrappers of the primitive types; Additionally
supported by HV: any sub-type of
Number

Checks whether the annoted value is a number having up to
integer digits and
fraction fractional digits

Defines column precision and scale

@Future

java.util.Date,
java.util.Calendar; Additionally
supported by HV, if the Joda Time
date/time API is on the class path: any implementations of
ReadablePartial and
ReadableInstant

Checks whether the annotated date is in the
future

None

@Max(value=)

BigDecimal,
BigInteger, byte,
short, int,
long and the respective wrappers of the
primitive types; Additionally supported by HV: any sub-type of
CharSequence (the numeric value
represented by the character sequence is evaluated), any
sub-type of Number

Checks whether the annotated value is less than or equal
to the specified maximum

Adds a check constraint on the column

@Min(value=)

BigDecimal,
BigInteger, byte,
short, int,
long and the respective wrappers of the
primitive types; Additionally supported by HV: any sub-type of
CharSequence (the numeric value
represented by the char sequence is evaluated), any sub-type of
Number

Checks whether the annotated value is higher than or
equal to the specified minimum

Adds a check constraint on the column

@NotNull

Any type

Checks that the annotated value is not
null.

Column(s) are not nullable

@Null

Any type

Checks that the annotated value is
null

None

@Past

java.util.Date,
java.util.Calendar; Additionally
supported by HV, if the Joda Time
date/time API is on the class path: any implementations of
ReadablePartial and
ReadableInstant

Checks whether the annotated date is in the past

None

@Pattern(regex=,flag=)

CharSequence

Checks if the annotated string matches the regular
expression regex considering the given
flag match

None

@Size(min=, max=)

CharSequence,
Collection, Map
and arrays

Checks if the annotated element's size is between min and
max (inclusive)

Column length will be set to
max

@Valid

Any non-primitive type

Performs validation recursively on the associated object.
If the object is a collection or an array, the elements are
validated recursively. If the object is a map, the value
elements are validated recursively.

None

Note

On top of the parameters indicated in Table 2.2, “Bean Validation constraints” each constraint has the parameters
message, groups and
payload. This is a requirement of the Bean
Validation specification.

2.3.2. Additional constraints

In addition to the constraints defined by the Bean Validation API
Hibernate Validator provides several useful custom constraints which are
listed in Table 2.3, “Custom constraints”. With one exception
also these constraints apply to the field/property level, only
@ScriptAssert is a class-level constraint.

Table 2.3. Custom constraints

Annotation

Supported data types

Use

Hibernate metadata impact

@CreditCardNumber(ignoreNonDigitCharacters=)

CharSequence

Checks that the annotated character sequence passes the
Luhn checksum test. Note, this validation aims to check for user
mistakes, not credit card validity! See also Anatomy of Credit
Card Numbers. ignoreNonDigitCharacters allows to ignore
non digit characters. The default is false.

None

@EAN

CharSequence

Checks that the annotated character sequence is a valid
EAN
barcode. type determines the type of
barcode. The default is EAN-13.

None

@Email

CharSequence

Checks whether the specified character sequence is a
valid email address. The optional parameters
regexp and flags
allow to specify an additional regular expression (including
regular expression flags) which the email must match.

None

@Length(min=, max=)

CharSequence

Validates that the annotated character sequence is
between min and
max included

Checks that the digits within the annotated character
sequence pass the Luhn checksum algorithm (see also Luhn
algorithm). startIndex and
endIndex allow to only run the algorithm on
the specified sub-string. checkDigitIndex
allows to use an arbitrary digit within the character sequence
as the check digit. If not specified it is assumed that the
check digit is part of the specified range. Last but not least,
ignoreNonDigitCharacters allows to ignore
non digit characters.

Checks that the digits within the annotated character
sequence pass the generic mod 10 checksum algorithm.
multiplier determines the multiplier for
odd numbers (defaults to 3), weight the
weight for even numbers (defaults to 1).
startIndex and
endIndex allow to only run the algorithm on
the specified sub-string. checkDigitIndex
allows to use an arbitrary digit within the character sequence
as the check digit. If not specified it is assumed that the
check digit is part of the specified range. Last but not least,
ignoreNonDigitCharacters allows to ignore
non digit characters.

Checks that the digits within the annotated character
sequence pass the mod 11 checksum algorithm.
threshold specifies the threshold for the
mod11 multiplier growth; if no value is specified the multiplier
will grow indefinitely. treatCheck10As
and treatCheck11As specify the check
digits to be used when the mod 11 checksum equals 10 or 11,
respectively. Default to X and 0, respectively.
startIndex, endIndex
acheckDigitIndex and
ignoreNonDigitCharacters carry the same
semantics as in @Mod10Check.

None

@NotBlank

CharSequence

Checks that the annotated character sequence is not null
and the trimmed length is greater than 0. The difference to
@NotEmpty is that this constraint can
only be applied on strings and that trailing whitespaces are
ignored.

None

@NotEmpty

CharSequence,
Collection, Map
and arrays

Checks whether the annotated element is not
null nor empty

None

@Range(min=, max=)

BigDecimal,
BigInteger,
CharSequence,
byte, short,
int, long and the
respective wrappers of the primitive types

Checks whether the annotated value lies between
(inclusive) the specified minimum and maximum

Checks whether the annotated value contains
potentially malicious fragments such as
<script/>. In order to use this constraint,
the jsoup library must be
part of the class path.

With the
whitelistType attribute a predefined
whitelist type can be chosen which can be refined via
additionalTags or
additionalTagsWithAttributes. The
former allows to add tags without any attributes, whereas the
latter allows to specify tags and optionally allowed attributes
using the annotation
@SafeHtml.Tag.

None

@ScriptAssert(lang=,script=, alias=)

Any type

Checks whether the given script can successfully be
evaluated against the annotated element. In order to use this
constraint, an implementation of the Java Scripting API as
defined by JSR 223 ("Scripting for the
JavaTM Platform") must part of the
class path. The expressions to be evaluated can be written in
any scripting or expression language, for which a JSR 223
compatible engine can be found in the class path.

None

@URL(protocol=,host=,
port=regexp=,
flags=)

CharSequence

Checks if the annotated character sequence is a valid URL
according to RFC2396. If any of the optional parameters
protocol, host or
port are specified, the corresponding URL
fragments must match the specified values. The optional
parameters regexp and
flags allow to specify an additional
regular expression (including regular expression flags) which
the URL must match.

None

2.3.2.1. Country specific constraints

Hibernate Validator offers also some country specific
constraints, e.g. for the validation of social security numbers.

Note

If you have to implement a country specific constraint,
consider making it a contribution to Hibernate Validator!

Table 2.4. Custom country specific constraints

Annotation

Supported data types

Use

Country

Hibernate metadata impact

@CNPJ

CharSequence

Checks that the annotated character sequence represents
a Brazilian corporate tax payer registry number (Cadastro de
Pessoa Juríeddica)

Brazil

None

@CPF

CharSequence

Checks that the annotated character sequence represents
a Brazilian individual taxpayer registry number (Cadastro de
Pessoa Fídsica)

Brazil

None

@TituloEleitoral

CharSequence

Checks that the annotated character sequence represents
a Brazilian voter ID card number (Título
Eleitoral)

Brazil

None

Tip

In some cases neither the Bean Validation constraints nor the
custom constraints provided by Hibernate Validator will fulfill your
requirements. In this case you can easily write your own constraint.
You can find more information in Chapter 6, Creating custom constraints.

As of Bean Validation 1.1, constraints can not only be applied to
JavaBeans and their properties, but also to the parameters and return values
of the methods and constructors of any Java type. That way Bean Validation
constraints can be used to specify

the preconditions that must be satisfied by the caller before a
method or constructor may be invoked (by applying constraints to the
parameters of an executable)

the postconditions that are guaranteed to the caller after a
method or constructor invocation returns (by applying constraints to the
return value of an executable)

Note

For the purpose of this reference guide, the term method
constraint refers to both, method and constructor constraints,
if not stated otherwise. Ocassionally, the term
executable is used when referering to methods and
constructors.

This approach has several advantages over traditional ways of checking
the correctness of parameters and return values:

the checks don't have to be performed manually (e.g. by throwing
IllegalArgumentExceptions or similar), resulting
in less code to write and maintain

an executable's pre- and postconditions don't have to be expressed
again in its documentation, since the constraint annotations will
automatically be included in the generated JavaDoc. This avoids
redundancies and reduces the chance of inconsistencies between
implementation and documentation

Tip

In order to make annotations show up in the JavaDoc of annoted
elements, the annotation types themselves must be annotated with the meta
annotation @Documented. This is the case for all
built-in constraints and is considered a best practice for any custom
constraints.

In the remainder of this chapter you will learn how to declare
parameter and return value constraints and how to validate them using the
ExecutableValidator API.

When invoking the rentCar() method,
the given customer must not be null, the rental's
start date must not be null and must be in the
future and the rental duration must be at least one day

Note that declaring method or constructor constraints itself does
not automatically cause their validation upon invocation of the
executable. Instead, the ExecutableValidator API (see Section 3.2, “Validating method constraints”) must be used to
perform the validation, which is often done using a method interception
facility such as AOP, proxy objects etc.

Constraints may only be applied to instance methods, i.e.
declaring constraints on static methods is not supported. Depending on
the interception facility you use for triggering method validation,
additional restrictions may apply, e.g. with respect to the visibility
of methods supported as target of interception. Refer to the
documentation of the interception technology to find out whether any
such limitations exist.

3.1.1.1. Cross-parameter constraints

Sometimes validation does not only depend on a single parameter
but on several or even all parameters of a method or constructor. This
kind of requirement can be fulfilled with help of a cross-parameter
constraint.

Cross-parameter constraints can be considered as the method
validation equivalent to class-level constraints. Both can be used to
implement validation requirements which are based on several elements.
While class-level constraints apply to several properties of a bean,
cross-parameter constraints apply to several parameters of an
executable.

In contrast to single-parameter constraints, cross-parameter
constraints are declared on the method or constructor as you can see
in Example 3.2, “Declaring a cross-parameter constraint”. Here
the cross-parameter constraint
@LuggageCountMatchesPassengerCount declared on
the load() method is used to ensure that no
passenger has more than two pieces of luggage.

As you will learn in the next section, return value constraints
are also declared on the method level. In order to distinguish
cross-parameter constraints from return value constraints, the
constraint target is configured in the
ConstraintValidator implementation using the
@SupportedValidationTarget annotation. You can
find out about the details in Section 6.3, “Cross-parameter constraints” which shows how to
implement your own cross-parameter constraint.

In some cases a constraint can be applied to an executable's
parameters (i.e. it is a cross-parameter constraint), but also to the
return value. One example for this are custom constraints which allow
to specify validation rules using expression or script
languages.

Such constraints must define a member
validationAppliesTo() which can be used at
declaration time to specify the constraint target. As shown in Example 3.3, “Specifying a constraint's target” you apply the
constraint to an executable's parameters by specifying
validationAppliesTo = ConstraintTarget.PARAMETERS,
while ConstraintTarget.RETURN_VALUE is used to
apply the constraint to the executable return value.

Although such a constraint is applicable to the parameters and
return value of an executable, the target can often be inferred
automatically. This is the case, if the constraint is declared
on

a void method with parameters (the constraint applies to the
parameters)

an executable with return value but no parameters (the
constraint applies to the return value)

neither a method nor a constructor, but a field, parameter
etc. (the constraint applies to the annotated element)

In these situations you don't have to specify the constraint
target. It is still recommended to do so if it increases readability
of the source code. If the constraint target is not specified in
situations where it can't be determined automatically, a
ConstraintDeclarationException is
raised.

Any newly created RentalStation object
must satisfy the @ValidRentalStation
constraint

The customer list returned by
getCustomers() must not be
null and must contain at least on element

3.1.3. Cascaded
validation

Similar to the cascaded validation of JavaBeans properties (see
Section 2.1.5, “Object graphs”), the
@Valid annotation can be used to mark executable
parameters and return values for cascaded validation. When validating a
parameter or return value annotated with @Valid,
the constraints declared on the parameter or return value object are
validated as well.

When validating the arguments of the
checkCar() method, the constraints on the
properties of the passed Car object are evaluated
as well. Similarly, the @NotNull constraint on
the name field of Garage is
checked when validating the return value of the
Garage constructor.

Generally, the cascaded validation works for executables in
exactly the same way as it does for JavaBeans properties.

In particular, null values are ignored during
cascaded validation (naturally this can't happen during constructor
return value validation) and cascaded validation is performed
recursively, i.e. if a parameter or return value object which is marked
for cascaded validation itself has properties marked with
@Valid, the constraints declared on the
referenced elements will be validated as well.

Cascaded validation can not only be applied to simple object
references but also to collection-typed parameters and return values.
This means when putting the @Valid annotation to
a parameter or return value which

3.1.4. Method constraints in
inheritance hierarchies

When declaring method constraints in inheritance hierarchies, it
is important to be aware of the following rules:

The preconditions to be satisified by the caller of a method
may not be strengthened in subtypes

The postconditions guaranteed to the caller of a method may
not be weakened in subtypes

These rules are motivated by the concept of behavioral
subtyping which requires that wherever a type
T is used, also a subtype
S of T may be used without
altering the program's behavior.

As an example, consider a class invoking a method on an object
with the static type T. If the runtime type of
that object was S and S
imposed additional preconditions, the client class might fail to satisfy
these preconditions as is not aware of them. The rules of behavioral
subtyping are also known as the Liskov
substitution principle.

The @Max constraint on
Car#drive() is illegal since this method
implements the interface method
Vehicle#drive(). Note that parameter
constraints on overriding methods are also disallowed, if the supertype
method itself doesn't declare any parameter constraints.

Furthermore, if a method overrides or implements a method declared
in several parallel supertypes (e.g. two interfaces not extending each
other or a class and an interface not implemented by that class), no
parameter constraints may be specified for the method in any of the
involved types. The types in Example 3.8, “Illegal method parameter constraint in parallel types of a
hierarchy”
demonstrate a violation of that rule. The method
RacingCar#drive() overrides
Vehicle#drive() as well as
Car#drive(). Therefore the constraint on
Vehicle#drive() is illegal.

The previously described restrictions only apply to parameter
constraints. In contrast, return value constraints may be added in
methods overriding or implementing any supertype methods.

In this case, all the method's return value constraints apply for
the subtype method, i.e. the constraints declared on the subtype method
itself as well as any return value constraints on overridden/implemented
supertype methods. This is legal as putting additional return value
constraints in place may never represent a weakening of the
postconditions guaranteed to the caller of a method.

If the validation engine detects a violation of any of the
aforementioned rules, a
ConstraintDeclarationException will be
raised.

Note

The rules described in this section only apply to methods but
not constructors. By definition, constructors never override supertype
constructors. Therefore, when validating the parameters or the return
value of a constructor invocation only the constraints declared on the
constructor itself apply, but never any constraints declared on
supertype constructors.

3.2. Validating method constraints

The validation of method constraints is done using the
ExecutableValidator interface.

Instead of calling the ExecutableValidator methods directly from
within application code, they are usually invoked via a method
interception technology such as AOP, proxy objects, etc. This causes
executable constraints to be validated automatically and transparently
upon method or constructor invocation. Typically a
ConstraintViolationException is raised by the
integration layer in case any of the constraints is violated.

In the example the executable validator is retrieved from the
default validator factory, but if required you could also bootstrap a
specifically configured factory as described in Chapter 8, Bootstrapping, for instance in order to use a
specific parameter name provider (see Section 8.2.4, “ParameterNameProvider”).

3.2.2. ExecutableValidator methods

The ExecutableValidator interface offers
altogether four methods:

validateParameters() and
validateReturnValue() for method
validation

validateConstructorParameters() and
validateConstructorReturnValue() for
constructor validation

Just as the methods on Validator, all these
methods return a Set<ConstraintViolation>
which contains a ConstraintViolation instance for
each violated constraint and which is empty if the validation succeeds.
Also all the methods have a var-args groups parameter
by which you can pass the validation groups to be considered for
validation.

ConstraintViolation#getExecutableParameters()
returns the validated parameter array in case of method or constructor
parameter validation, while
ConstraintViolation#getExecutableReturnValue()
provides access to the validated object in case of return value
validation.

All the other ConstraintViolation methods
generally work for method validation in the same way as for validation
of beans. Refer to the JavaDoc
to learn more about the behavior of the individual methods and their
return values during bean and method validation.

Note that getPropertyPath() can be very
useful in order to obtain detailed information about the validated
parameter or return value, e.g. for logging purposes. In particular, you
can retrieve name and argument types of the concerned method as well as
the index of the concerned parameter from the path nodes. How this can
be done is shown in Example 3.16, “Retrieving method and parameter information”.

3.3. Built-in method constraints

In addition to the built-in bean and property-level constraints
discussed in Section 2.3, “Built-in constraints”, Hibernate
Validator currently provides one method-level constraint,
@ParameterScriptAssert. This is a generic
cross-parameter constraint which allows to implement validation routines
using any JSR 223 compatible ("Scripting for the
JavaTM Platform") scripting language, provided
an engine for this language is available on the classpath.

Chapter 4. Interpolating constraint error messages

Message interpolation is the process of creating error messages for
violated Bean Validation constraints. In this chapter you will learn how
such messages are defined and resolved and how you can plug in custom
message interpolators in case the default algorithm is not sufficient for
your requirements.

Example 4.1. Specifying a message descriptor using the
message attribute

package org.hibernate.validator.referenceguide.chapter04;publicclassCar{ @NotNull(message ="The manufacturer name must not be null")privateString manufacturer;//constructor, getters and setters ...}

If a constraint is violated, its descriptor will be interpolated by
the validation engine using the currently configured
MessageInterpolator. The interpolated error message
can then be retrieved from the resulting constraint violation by calling
ConstraintViolation#getMessage().

Message descriptors can contain message
parameters as well as message expressions
which will be resolved during interpolation. Message parameters are string
literals enclosed in {}, while message expressions are
string literals enclosed in ${}. The following
algorithm is applied during method interpolation:

Resolve any message parameters by using them as key for the
resource bundle ValidationMessages. If this
bundle contains an entry for a given message parameter, that parameter
will be replaced in the message with the corresponding value from the
bundle. This step will be executed recursively in case the replaced
value again contains message parameters. The resource bundle is
expected to be provided by the application developer, e.g. by adding a
file named ValidationMessages.properties to the
classpath. You can also create localized error messages by providing
locale specific variations of this bundle, such as
ValidationMessages_en_US.properties. By default,
the JVM's default locale
(Locale#getDefault()) will be used when
looking up messages in the bundle.

Resolve any message parameters by using them as key for a
resource bundle containing the standard error messages for the
built-in constraints as defined in Appendix B of the Bean Validation
specification. In the case of Hibernate Validator, this bundle is
named
org.hibernate.validator.ValidationMessages. If
this step triggers a replacement, step 1 is executed again, otherwise
step 3 is applied.

Resolve any message parameters by replacing them with the value
of the constraint annotation member of the same name. This allows to
refer to attribute values of the constraint (e.g.
Size#min()) in the error message (e.g. "must
be at least ${min}").

Tip

You can find the formal definition of the interpolation algorithm
in section 5.3.1.1
of the Bean Validation specification.

4.1.1. Special characters

Since the characters {, }
and $ have a special meaning in message descriptors
they need to be escaped if you want to use them literally. The following
rules apply:

\{ is considered as
the literal {

\} is considered as the literal
}

\$ is considered as the literal
$

\\ is considered as the literal
\

4.1.2. Interpolation with message expressions

As of Hibernate Validator 5 (Bean Validation 1.1) it is possible
to use the Unified Expression Language (as defined by JSR 341) in constraint
violation messages. This allows to define error messages based on
conditional logic and also enables advanced formatting options. The
validation engine makes the following objects available in the EL
context:

the attribute values of the constraint mapped to the attribute
names

the currently validated value (property, bean, method
parameter etc.) under the name
validatedValue

a bean mapped to the name formatter
exposing the var-arg method format(String format,
Object... args) which behaves like
java.util.Formatter.format(String format, Object...
args).

The following section provides several examples for using EL
expressions in error messages.

the @NotNull constraint on the
manufacturer field causes the error message "may
not be null", as this is the default message defined by the Bean
Validation specification and no specific descriptor is given in the
message attribute

the @Size constraint on the
licensePlate field shows the interpolation of
message parameters ({min},
{max}) and how to add the validated value to the
error message using the EL expression ${validatedValue}

the @Min constraint on
seatCount demonstrates how use an EL expression
with a ternery expression to dynamically chose singular or plural
form, depending on an attribute of the constraint ("There must be at
least 1 seat" vs. "There must be at least 2 seats")

the message for the @DecimalMax
constraint on topSpeed shows how to format the
validated value using the formatter object

finally, the @DecimalMax constraint on
price shows that parameter interpolation has
precedence over expression evaluation, causing the
$ sign to show up in front of the maximum
price

Tip

Only actual constraint attributes can be interpolated using
message parameters in the form {attributeName}. When
referring to the validated value or custom expression variables added
to the interpolation context (see Section 11.6.1, “HibernateConstraintValidatorContext”), an EL
expression in the form ${attributeName} must be
used.

4.2. Custom message interpolation

If the default message interpolation algorithm does not fit your
requirements it is also possible to plug in a custom
MessageInterpolator implementation.

Custom interpolators must implement the interface
javax.validation.MessageInterpolator. Note that
implementations must be thread-safe. It is recommended that custom message
interpolators delegate final implementation to the default interpolator,
which can be obtained via
Configuration#getDefaultMessageInterpolator().

4.2.1. ResourceBundleLocator

In some use cases you want to use the message interpolation
algorithm as defined by the Bean Validation specification, but retrieve
error messages from other resource bundles than
ValidationMessages. In this situation Hibernate
Validator's ResourceBundleLocator SPI can
help.

The default message interpolator in Hibernate Validator,
ResourceBundleMessageInterpolator, delegates
retrieval of resource bundles to that SPI. Using an alternative bundle
only requires passing an instance of
PlatformResourceBundleLocator with the bundle
name when bootstrapping the ValidatorFactory as
shown in Example 4.4, “Using a specific resource bundle”.

Of course you also could implement a completely different
ResourceBundleLocator, which for instance returns
bundles backed by records in a database. In this case you can obtain the
default locator via
HibernateValidatorConfiguration#getDefaultResourceBundleLocator(),
which you e.g. could use as fallback for your custom locator.

Besides PlatformResourceBundleLocator,
Hibernate Validator provides another resource bundle locator
implementation out of the box, namely
AggregateResourceBundleLocator, which allows to
retrieve error messages from more than one resource bundle. You could
for instance use this implementation in a multi-module application where
you want to have one message bundle per module. Example 4.5, “Using
AggregateResourceBundleLocator” shows how to
use AggregateResourceBundleLocator.

Note that the bundles are processed in the order as passed to the
constructor. That means if several bundles contain an entry for a given
message key, the value will be taken from the first bundle in the list
containing the key.

Chapter 5. Grouping constraints

All validation methods on Validator and
ExecutableValidator discussed in earlier chapters
also take a var-arg argument groups. So far we have
been ignoring this parameter, but it is time to have a closer look.

5.1. Requesting groups

Groups allow you to restrict the set of constraints applied during
validation. One use case for validation groups are UI wizards where in
each step only a specified subset of constraints should get validated. The
groups targeted are passed as var-arg parameters to the appropriate
validate method.

Let's have a look at an example. The class
Person in Example 5.1, “Person” has a
@NotNull constraint on name.
Since no group is specified for this annotation the default group
javax.validation.groups.Default is assumed.

Note

When more than one group is requested, the order in which the
groups are evaluated is not deterministic. If no group is specified the
default group javax.validation.groups.Default is
assumed.

The class Driver in Example 5.2, “Driver” extends Person and adds
the properties age and
hasDrivingLicense. Drivers must be at least 18 years
old (@Min(18)) and have a driving license
(@AssertTrue). Both constraints defined on these
properties belong to the group DriverChecks which
is just a simple tagging interface.

Tip

Using interfaces makes the usage of groups type-safe and allows
for easy refactoring. It also means that groups can inherit from each
other via class inheritance.

Finally the class Car (Example 5.3, “Car”) has some
constraints which are part of the default group as well as
@AssertTrue in the group
CarChecks on the property
passedVehicleInspection which indicates whether a car
passed the road worthy tests.

// create a car and check that everything is ok with it.Car car =newCar("Morris","DD-AB-123",2);Set<ConstraintViolation<Car>> constraintViolations = validator.validate( car );assertEquals(0, constraintViolations.size());// but has it passed the vehicle inspection?constraintViolations = validator.validate( car,CarChecks.class);assertEquals(1, constraintViolations.size());assertEquals("The car has to pass the vehicle inspection first", constraintViolations.iterator().next().getMessage());// let's go to the vehicle inspectioncar.setPassedVehicleInspection(true);assertEquals(0, validator.validate( car ).size());// now let's add a driver.He is 18, but has not passed the driving test yetDriver john =newDriver("John Doe");john.setAge(18);car.setDriver( john );constraintViolations = validator.validate( car,DriverChecks.class);assertEquals(1, constraintViolations.size());assertEquals("You first have to pass the driving test", constraintViolations.iterator().next().getMessage());// ok,John passes the testjohn.passedDrivingTest(true);assertEquals(0, validator.validate( car,DriverChecks.class).size());// just checking that everything is in order nowassertEquals(0, validator.validate( car,Default.class,CarChecks.class,DriverChecks.class).size());

The first validate() call in Example 5.4, “Using validation groups” is done using no explicit group. There are
no validation errors, even though the property
passedVehicleInspection is per default
false. However, the constraint defined on this
property does not belong to the default group.

The next validation using the CarChecks group
fails until the car passes the vehicle inspection. Adding a driver to the
car and validating against DriverChecks again
yields one constraint violation due to the fact that the driver has not
yet passed the driving test. Only after setting
passedDrivingTest to true the
validation against DriverChecks passes.

The last validate() call finally shows that all constraints are
passing by validating against all defined groups.

5.2. Defining group sequences

By default, constraints are evaluated in no particular order,
regardless of which groups they belong to. In some situations, however, it
is useful to control the order constraints are evaluated.

In the example from Example 5.4, “Using validation groups” it could
for instance be required that first all default car constraints are
passing before checking the road worthiness of the car. Finally, before
driving away, the actual driver constraints should be checked.

In order to implement such a validation order you just need to
define an interface and annotate it with
@GroupSequence, defining the order in which the
groups have to be validated (see Example 5.5, “Defining a group sequence”). If at least one constraint
fails in a sequenced group none of the constraints of the following groups
in the sequence get validated.

Warning

Groups defining a sequence and groups composing a sequence must
not be involved in a cyclic dependency either directly or indirectly,
either through cascaded sequence definition or group inheritance. If a
group containing such a circularity is evaluated, a
GroupDefinitionException is raised.

5.3. Redefining the default group sequence

5.3.1. @GroupSequence

Besides defining group sequences, the
@GroupSequence annotation also allows to redefine
the default group for a given class. To do so, just add the
@GroupSequence annotation to the class and
specify the sequence of groups which substitute
Default for this class within the
annotation.

Note

Since there must no cyclic dependency in the group and group
sequence definitions one cannot just add
Default to the sequence redefining
Default for a class. Instead the class itself
has to be added!

The Default group sequence overriding is
local to the class it is defined on and is not propagated to associated
objects. For the example this means that adding
DriverChecks to the default group sequence of
RentalCar would not have any effects. Only the
group Default will be propagated to the
driver association.

5.3.2. @GroupSequenceProvider

In addition to statically redefining default group sequences via
@GroupSequence, Hibernate Validator also provides
an SPI for the dynamic redefinition of default group sequences depending
on the object state.

5.4. Group conversion

What if you wanted to validate the car related checks together with
the driver checks? Of course you could pass the required groups to the
validate call explicitly, but what if you wanted to make these validations
occur as part of the Default group validation? Here
@ConvertGroup comes into play which allows you
during cascaded validation to use a different group than the originally
requested one.

Let's have a look at Example 5.10, “@ConvertGroup usage”. Here
@GroupSequence({ CarChecks.class, Car.class }) is used to
combine the car related constraints under the
Default group (see Section 5.3, “Redefining the default group sequence”). There is also a
@ConvertGroup(from = Default.class, to = DriverChecks.class)
which ensures the Default group gets converted to
the DriverChecks group during cascaded validation
of the driver association.

As a result the validation in Example 5.11, “Test case for @ConvertGroup” succeeds, even though the
constraint on hasDrivingLicense belongs to the
DriverChecks group and only the
Default group is requested in the
validate() call.

Example 5.11. Test case for @ConvertGroup

// create a car and validate.TheDriver is still null and does not get validatedCar car =newCar("VW","USD-123",4);car.setPassedVehicleInspection(true);Set<ConstraintViolation<Car>> constraintViolations = validator.validate( car );assertEquals(0, constraintViolations.size());// create a driver who has not passed the driving testDriver john =newDriver("John Doe");john.setAge(18);// now let's add a driver to the carcar.setDriver( john );constraintViolations = validator.validate( car );assertEquals(1, constraintViolations.size());assertEquals("The driver constraint should also be validated as part of the default group", constraintViolations.iterator().next().getMessage(),"You first have to pass the driving test");

You can define group conversions wherever
@Valid can be used, namely associations as well as
method and constructor parameters and return values. Multiple conversions
can be specified using @ConvertGroup.List.

However, the following restrictions apply:

@ConvertGroup must only be used in
combination with @Valid. If used without, a
ConstraintDeclarationException is
thrown.

It is not legal to have multiple conversion rules on the same
element with the same from value. In this
case, a ConstraintDeclarationException is
raised.

The from attribute must not refer to a
group sequence. A
ConstraintDeclarationException is raised in
this situation.

Note

Rules are not executed recursively. The first matching
conversion rule is used and subsequent rules are ignored. For example
if a set of @ConvertGroup declarations chains
group A to B and B to C, the group A will be converted to B and not to
C.

The Bean Validation API defines a whole set of standard constraint
annotations such as @NotNull,
@Size etc. In cases where these buit-in constraints
are not sufficient, you cean easily create custom constraints tailored to
your specific validation requirements.

6.1. Creating a simple constraint

To create a custom constraint, the following three steps are
required:

Create a constraint annotation

Implement a validator

Define a default error message

6.1.1. The constraint annotation

This section shows how to write a constraint annotation which can
be used to ensure that a given string is either completely upper case or
lower case. Later on this constraint will be applied to the
licensePlate field of the
Car class from Chapter 1, Getting started to ensure, that the field is always
an upper-case string.

The first thing needed is a way to express the two case modes.
While you could use String constants, a better
approach is using a Java 5 enum for that purpose:

An annotation type is defined using the @interface
keyword. All attributes of an annotation type are declared in a
method-like manner. The specification of the Bean Validation API
demands, that any constraint annotation defines

an attribute message that returns the
default key for creating error messages in case the constraint is
violated

an attribute groups that allows the
specification of validation groups, to which this constraint belongs
(see Chapter 5, Grouping constraints). This must default to an
empty array of type Class<?>.

an attribute payload that can be used
by clients of the Bean Validation API to assign custom payload
objects to a constraint. This attribute is not used by the API
itself. An example for a custom payload could be the definition of a
severity:

Now a client can after the validation of a
ContactDetails instance access the severity
of a constraint using
ConstraintViolation.getConstraintDescriptor().getPayload()
and adjust its behaviour depending on the severity.

Besides these three mandatory attributes there is another one,
value, allowing for the required case mode to be
specified. The name value is a special one, which
can be omitted when using the annotation, if it is the only attribute
specified, as e.g. in @CheckCase(CaseMode.UPPER).

In addition, the constraint annotation is decorated with a couple
of meta annotations:

@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE
}): Defines the supported target element types for the
constraint. @CheckCase may be used on fields
(element type FIELD), JavaBeans properties as
well as method return values (METHOD) and
method/constructor parameters (PARAMETER).
The element type ANNOTATION_TYPE allows for
the creation of composed constraints (see Section 6.4, “Constraint composition”) based on
@CheckCase.

When creating a class-level constraint (see Section 2.1.3, “Class-level
constraints”), the element type
TYPE would have to be used. Constraints
targetting the return value of a constructor need to support the
element type CONSTRUCTOR. Cross-parameter
constraints (see Section 6.3, “Cross-parameter constraints”) which are used to
validate all the parameters of a method or constructor together,
must support METHOD or
CONSTRUCTOR, respectively.

@Retention(RUNTIME): Specifies, that annotations
of this type will be available at runtime by the means of
reflection

@Constraint(validatedBy =
CheckCaseValidator.class): Marks the annotation type as
constraint annotation and specifies the validator to be used to
validate elements annotated with @CheckCase.
If a constraint may be used on several data types, several
validators may be specified, one for each data type.

@Documented: Says, that the use of
@CheckCase will be contained in the JavaDoc
of elements annotated with it

Finally, there is an inner annotation type named
List. This annotation allows to specify several
@CheckCase annotations on the same element, e.g.
with different validation groups and messages. While also another name
could be used, the Bean Validation specification recommends to use the
name List and make the annotation an inner
annotation of the corresponding constraint type.

6.1.2. The constraint
validator

Having defined the annotation, you need to create a constraint
validator, which is able to validate elements with a
@CheckCase annotation. To do so, implement the
interface ConstraintValidator as shown
below:

Example 6.3. Implementing a constraint validator for the constraint
@CheckCase

The ConstraintValidator interface defines
two type parameters which are set in the implementation. The first one
specifies the annotation type to be validated
(CheckCase), the second one the type of elements,
which the validator can handle (String). In case
a constraint supports several data types, a
ConstraintValidator for each allowed type has to
be implemented and registered at the constraint annotation as shown
above.

The implementation of the validator is straightforward. The
initialize() method gives you access to the
attribute values of the validated constraint and allows you to store
them in a field of the validator as shown in the example.

The isValid() method contains the actual
validation logic. For @CheckCase this is the
check whether a given string is either completely lower case or upper
case, depending on the case mode retrieved in
initialize(). Note that the Bean Validation
specification recommends to consider null values as being
valid. If null is not a valid value for an element, it
should be annotated with @NotNull explicitly.

6.1.2.1. The ConstraintValidatorContext

Example 6.3, “Implementing a constraint validator for the constraint
@CheckCase” relies on the
default error message generation by just returning
true or false from the
isValid() method. Using the passed
ConstraintValidatorContext object it is
possible to either add additional error messages or completely disable
the default error message generation and solely define custom error
messages. The ConstraintValidatorContext API is
modeled as fluent interface and is best demonstrated with an
example:

6.1.3. The error message

The last missing building block is an error message which should
be used in case a @CheckCase constraint is
violated. To define this, create a file
ValidationMessages.properties with the following contents
(see also Section 4.1, “Default message interpolation”):

org.hibernate.validator.referenceguide.chapter06.CheckCase.message=Case mode must be {value}.

If a validation error occurs, the validation runtime will use the
default value, that you specified for the message attribute of the
@CheckCase annotation to look up the error
message in this resource bundle.

6.1.4. Using the constraint

You can now use the constraint in the Car
class from the Chapter 1, Getting started chapter to
specify that the licensePlate field should only
contain upper-case strings:

As the example demonstrates, you need to use the element type
TYPE in the @Target
annotation. This allows the constraint to be put on type definitions. The
validator of the constraint in the example receives a
Car in the isValid()
method and can access the complete object state to decide whether the
given instance is valid or not.

6.2.1. Custom property paths

By default the constraint violation for a class-level constraint
is reported on the level of the annotated type, e.g.
Car.

In some cases it is preferable though that the violation's
property path refers to one of the involved properties. For instance you
might want to report the @ValidPassengerCount
constraint against the passengers property instead
of the Car bean.

6.3. Cross-parameter constraints

Bean Validation distinguishes between two different kinds of
constraints.

Generic constraints (which have been discussed so far) apply to the
annotated element, e.g. a type, field, method parameter or return value
etc. Cross-parameter constraints, in contrast, apply to the array of
parameters of a method or constructor and can be used to express
validation logic which depends on several parameter values.

In order to define a cross-parameter constraint, its validator class
must be annotated with
@SupportedValidationTarget(ValidationTarget.PARAMETERS).
The type parameter T from the
ConstraintValidator interface must resolve to
either Object or Object[] in
order to receive the array of method/constructor arguments in the
isValid() method.

The following example shows the definition of a cross-parameter
constraint which can be used to check that two Date
parameters of a method are in the correct order:

The definition of a cross-parameter constraint isn't any different
from defining a generic constraint, i.e. it must specify the members
message(), groups() and
payload() and be annotated with
@Constraint. This meta annotation also specifies
the corresponding validator, which is shown in Example 6.11, “Generic and cross-parameter constraint”. Note that besides the
element types METHOD and
CONSTRUCTOR also
ANNOTATION_TYPE is specified as target of the
annotation, in order to enable the creation of composed constraints based
on @ConsistentDateParameters (see Section 6.4, “Constraint composition”).

Note

Cross-parameter constraints are specified directly on the
declaration of a method or constructor, which is also the case for
return value constraints. In order to improve code readability, it is
therefore recommended to chose constraint names - such as
@ConsistentDateParameters - which make the
constraint target apparent.

As discussed above, the validation target
PARAMETERS must be configured for a cross-parameter
validator by using the @SupportedValidationTarget
annotation. Since a cross-parameter constraint could be applied to any
method or constructor, it is considered a best practice to check for the
expected number and types of parameters in the validator
implementation.

As with generic constraints, null parameters
should be considered valid and @NotNull on the
individual parameters should be used to make sure that parameters are not
null.

Tip

Similar to class-level constraints, you can create custom
constraint violations on single parameters instead of all parameters
when validating a cross-parameter constraint. Just obtain a node builder
from the ConstraintValidatorContext passed to
isValid() and add a parameter node by calling
addParameterNode(). In the example you could
use this to create a constraint violation on the end date parameter of
the validated method.

In rare situations a constraint is both, generic and
cross-parameter. This is the case if a constraint has a validator class
which is annotated with
@SupportedValidationTarget({ValidationTarget.PARAMETERS,
ValidationTarget.ANNOTATED_ELEMENT}) or if it has a generic and a
cross-parameter validator class.

When declaring such a constraint on a method which has parameters
and also a return value, the intended constraint target can't be
determined. Constraints which are generic and cross-parameter at the same
time, must therefore define a member
validationAppliesTo() which allows the constraint
user to specify the constraint's target as shown in Example 6.12, “Generic and cross-parameter constraint”.

The @ScriptAssert constraint has two
validators (not shown), a generic and a cross-parameter one and thus
defines the member validationAppliesTo(). The
default value IMPLICIT allows to derive the target
automatically in situations where this is possible (e.g. if the constraint
is declared on a field or on a method which has parameters but no return
value).

6.4. Constraint composition

Looking at the licensePlate field of the
Car class in Example 6.6, “Applying the @CheckCase
constraint”, you see three constraint
annotations already. In complexer scenarios, where even more constraints
could be applied to one element, this might become a bit confusing easily.
Furthermore, if there was a licensePlate field in
another class, you would have to copy all constraint declarations to the
other class as well, violating the DRY principle.

To create a composed constraint, simply annotate the constraint
declaration with its comprising constraints. If the composed constraint
itself requires a validator, this validator is to be specified within the
@Constraint annotation. For composed constraints
which don't need an additional validator such as
@ValidLicensePlate, just set
validatedBy() to an empty array.

Using the new composed constraint at the
licensePlate field is fully equivalent to the
previous version, where the three constraints were declared directly at
the field itself:

The set of ConstraintViolations retrieved
when validating a Car instance will contain an
entry for each violated composing constraint of the
@ValidLicensePlate constraint. If you rather prefer
a single ConstraintViolation in case any of the
composing constraints is violated, the
@ReportAsSingleViolation meta constraint can be
used as follows:

Chapter 7. Configuring via XML

So far we have used the default configuration source for Bean
Validation, namely annotations. However, there also exist two kinds of XML
descriptors allowing configuration via XML. The first descriptor describes
general Bean Validation behaviour and is provided as
META-INF/validation.xml. The second one describes
constraint declarations and closely matches the constraint declaration
approach via annotations. Let's have a look at these two document
types.

Note

7.1. Configuring the validator factory in
validation.xml

The key to enable XML configuration for Hibernate Validator is the
file META-INF/validation.xml. If this file exists on
the classpath its configuration will be applied when the
ValidatorFactory gets created. Example 7.1, “validation-configuration-1.1.xsd” shows a model view of the XML
schema to which validation.xml has to adhere.

Example 7.1. validation-configuration-1.1.xsd

Example 7.2, “validation.xml” shows the several
configuration options of validation.xml. All settings
are optional and the same configuration options are also available
programmatically through
javax.validation.Configuration. In fact the XML
configuration will be overridden by values explicitly specified via the
programmatic API. It is even possible to ignore the XML configuration
completely via
Configuration#ignoreXmlConfiguration(). See also
Section 8.2, “Configuring a ValidatorFactory”.

Warning

There must only be one file named
META-INF/validation.xml on the classpath. If more
than one is found an exception is thrown.

The node default-provider allows to choose the
Bean Validation provider. This is useful if there is more than one
provider on the classpath. message-interpolator,
traversable-resolver,
constraint-validator-factory and
parameter-name-provider allow to customize the used
implementations for the interfaces
MessageInterpolator,
TraversableResolver,
ConstraintValidatorFactory and
ParameterNameProvider defined in the
javax.validation package. See the sub-sections of
Section 8.2, “Configuring a ValidatorFactory” for more
information about these interfaces.

executable-validation and its subnodes define
defaults for method validation. The Bean Validation specification defines
constructor and non getter methods as defaults. The
enabled attribute acts as global switch to turn
method validation on and off (see also Chapter 3, Declaring and validating method constraints).

Via the constraint-mapping element you can list
an arbitrary number of additional XML files containing the actual
constraint configuration. Mapping file names must be specified using their
fully-qualified name on the classpath. Details on writing mapping files
can be found in the next section.

Last but not least, you can specify provider specific properties via
the property nodes. In the example we are using the
Hibernate Validator specific
hibernate.validator.fail_fast property (see Section 11.2, “Fail fast mode”).

7.2. Mapping constraints via
constraint-mappings

Expressing constraints in XML is possible via files adhering to the
schema seen in Example 7.3, “validation-mapping-1.1.xsd”. Note that
these mapping files are only processed if listed via
constraint-mapping in
validation.xml.

The XML configuration is closely mirroring the programmatic API. For
this reason it should suffice to just add some comments.
default-package is used for all fields where a class
name is expected. If the specified class is not fully qualified the
configured default package will be used. Every mapping file can then have
several bean nodes, each describing the constraints
on the entity with the specified class name.

Warning

A given entity can only be configured once across all
configuration files. The same applies for constraint definitions for a
given constraint annotation. It can only occur in one mapping file. If
these rules are violated a ValidationException
is thrown.

Setting ignore-annotations to
true means that constraint annotations placed on the
configured bean are ignored. The default for this value is
true. ignore-annotations is also available for the
nodes class, fields,
getter, constructor,
method, parameter,
cross-parameter and
return-value. If not explicitly specified on these
levels the configured bean value applies.

The nodes class, field,
getter, constructor and
method (and its sub node
parameter) determine on which level the constraint
gets placed. The constraint node is then used to add
a constraint on the corresponding level. Each constraint definition must
define the class via the annotation attribute. The
constraint attributes required by the Bean Validation specification
(message, groups and
payload) have dedicated nodes. All other constraint
specific attributes are configured using the element
node.

Last but not least, the list of
ConstraintValidators associated to a given
constraint can be altered via the
constraint-definition node. The
annotation attribute represents the constraint
annotation being altered. The validated-by elements
represent the (ordered) list of ConstraintValidator
implementations associated to the constraint. If
include-existing-validator is set to
false, validators defined on the constraint
annotation are ignored. If set to true, the list of
constraint validators described in XML is concatenated to the list of
validators specified on the annotation.

In Section 2.2.1, “Obtaining a Validator instance” you already saw one
way for creating a Validator instance - via
Validation#buildDefaultValidatorFactory(). In this
chapter you will learn how to use the other methods in
javax.validation.Validation in order to bootstrap
specifically configured validators.

8.1. Retrieving ValidatorFactory and
Validator

You obtain a Validator by retrieving a
ValidatorFactory via one of the static methods on
javax.validation.Validation and calling
getValidator() on the factory instance.

Tip

The generated ValidatorFactory and
Validator instances are thread-safe and can be
cached. As Hibernate Validator uses the factory as context for caching
constraint metadata it is recommended to work with one factory instance
within an application.

Bean Validation supports working with several providers such as
Hibernate Validator within one application. If more than one provider is
present on the classpath, it is not guaranteed which one is chosen when
creating a factory via
buildDefaultValidatorFactory().

Note that the configuration object returned by
configure() allows to specifically customize the
factory before calling buildValidatorFactory().
The available options are discussed later in this chapter.

Note

If a ValidatorFactory instance is no longer
in use, it should be disposed by calling
ValidatorFactory#close(). This will free any
resources possibly allocated by the factory.

8.1.1. ValidationProviderResolver

By default, available Bean Validation providers are discovered
using the Java
Service Provider mechanism.

For that purpose, each provider includes the file
META-INF/services/javax.validation.spi.ValidationProvider,
containing the fully qualified classname of its
ValidationProvider implementation. In the case of
Hibernate Validator this is
org.hibernate.validator.HibernateValidator.

Depending on your environment and its classloading specifics,
provider discovery via the Java's service loader mechanism might not
work. In this case you can plug in a custom
ValidationProviderResolver implementation which
performs the provider retrieval. An example is OSGi, where you could
implement a provider resolver which uses OSGi services for provider
discovery.

8.2. Configuring a ValidatorFactory

By default validator factories retrieved from
Validation and any validators they create are
configured as per the XML descriptor
META-INF/validation.xml (see Chapter 7, Configuring via XML), if present.

If you want to disable the XML based configuration, you can do so by
invoking
Configuration#ignoreXmlConfiguration().

The different values of the XML configuration can be accessed via
Configuration#getBootstrapConfiguration(). This
can for instance be helpful if you want to integrate Bean Validation into
a managed environment and want to create managed instances of the objects
configured via XML.

Using the fluent configuration API, you can override one or more of
the settings when bootstrapping the factory. The following sections show
how to make use of the different options. Note that the
Configuration class exposes the default
implementations of the different extension points which can be useful if
you want to use these as delegates for your custom implementations.

8.2.1. MessageInterpolator

Message interpolators are used by the validation engine to create
user readable error messages from constraint message descriptors.

8.2.2. TraversableResolver

In some cases the validation engine should not access the state of
a bean property. The most obvious example for that is a lazily loaded
property or association of a JPA entity. Validating this lazy property
or association would mean that its state would have to be accessed,
triggering a load from the database.

Hibernate Validator provides two
TraversableResolvers out of the box which will be
enabled automatically depending on your environment. The first is
DefaultTraversableResolver which will always
return true for
isReachable() and
isTraversable(). The second is
JPATraversableResolver which gets enabled when
Hibernate Validator is used in combination with JPA 2.

8.2.3. ConstraintValidatorFactory

ConstraintValidatorFactory is the extension
point for customizing how constraint validators are instantiated and
released.

The default ConstraintValidatorFactory
provided by Hibernate Validator requires a public no-arg constructor to
instantiate ConstraintValidator instances (see
Section 6.1.2, “The constraint
validator”). Using a custom
ConstraintValidatorFactory offers for example the
possibility to use dependency injection in constraint validator
implementations.

Warning

Any constraint implementations relying on
ConstraintValidatorFactory behaviors specific
to an implementation (dependency injection, no no-arg constructor and
so on) are not considered portable.

Note

ConstraintValidatorFactory
implementations should not cache validator instances as the state of
each instance can be altered in the
initialize() method.

8.2.4. ParameterNameProvider

In case a method or constructor parameter constraint is violated,
the ParameterNameProvider interface is used to
retrieve the parameter's name and make it available to the user via the
constraint violation's property path.

The default implementation returns parameter names in the form
arg0, arg1 etc., while custom
implementations could e.g. be based on parameter annotations, debug
symbols or a feature for retrieving parameter names at runtime possibly
provided by future Java versions.

Chapter 9. Using constraint metadata

The Bean Validation specification provides not only a validation
engine, but also an API for retrieving constraint metadata in a uniform way,
no matter whether the constraints are declared using annotations or via XML
mappings. Read this chapter to learn more about this API and its
possibilities. You can find all the metadata API types in the package
javax.validation.metadata.

9.1. BeanDescriptor

The entry point into the metadata API is the method
Validator#getConstraintsForClass(), which returns an instance
of the BeanDescriptor
interface. Using this descriptor, you can obtain metadata for constraints
declared directly on the bean itself (class- or property-level), but also
retrieve metadata descriptors representing single properties, methods and
constructors.

You can determine whether the specified class hosts any class- or
property-level constraints via isBeanConstrained(). Method or
constructor constraints are not considered by
isBeanConstrained().

The method getConstraintDescriptors() is common to all
descriptors derived from ElementDescriptor (see
Section 9.4, “ElementDescriptor”) and returns a
set of descriptors representing the constraints directly declared on the
given element. In case of BeanDescriptor, the
bean's class-level constraints are returned. More details on
ConstraintDescriptor can be found in Section 9.6, “ConstraintDescriptor”.

Via getConstraintsForProperty(),
getConstraintsForMethod() and
getConstraintsForConstructor() you can obtain a
descriptor representing one given property or executable element,
identified by its name and, in case of methods and constructors, parameter
types. The different descriptor types returned by these methods are
described in the following sections.

Note that these methods consider constraints declared at super-types
according to the rules for constraint inheritance as described in Section 2.1.4, “Constraint inheritance”. An example is the descriptor
for the manufacturer property, which provides access to
all constraints defined on
Vehicle#getManufacturer() and the implementing
method Car#getManufacturer().
null is returned in case the specified element does not
exist or is not constrained.

The methods getConstrainedProperties(),
getConstrainedMethods() and
getConstrainedConstructors() return (potentially
empty) sets with all constrained properties, methods and constructors,
respectively. An element is considered constrained, if it has at least one
constraint or is marked for cascaded validation. When invoking
getConstrainedMethods(), you can specify the type
of the methods to be returned (getters, non-getters or both).

9.2. PropertyDescriptor

The interface PropertyDescriptor
represents one given property of a class. It is transparent whether
constraints are declared on a field or a property getter, provided the
JavaBeans naming conventions are respected. Example 9.3, “Using PropertyDescriptor” shows how to use the
PropertyDescriptor interface.

Example 9.3. Using PropertyDescriptor

PropertyDescriptor licensePlateDescriptor = carDescriptor.getConstraintsForProperty("licensePlate");//"licensePlate" has two constraints, is not marked with @Valid and defines no group conversionsassertEquals("licensePlate", licensePlateDescriptor.getPropertyName());assertEquals(2, licensePlateDescriptor.getConstraintDescriptors().size());assertTrue( licensePlateDescriptor.hasConstraints());assertFalse( licensePlateDescriptor.isCascaded());assertTrue( licensePlateDescriptor.getGroupConversions().isEmpty());PropertyDescriptor driverDescriptor = carDescriptor.getConstraintsForProperty("driver");//"driver" has no constraints, is marked with @Valid and defines one group conversionassertEquals("driver", driverDescriptor.getPropertyName());assertTrue( driverDescriptor.getConstraintDescriptors().isEmpty());assertFalse( driverDescriptor.hasConstraints());assertTrue( driverDescriptor.isCascaded());assertEquals(1, driverDescriptor.getGroupConversions().size());

Using getConstrainedDescriptors(), you can
retrieve a set of ConstraintDescriptors providing
more information on the individual constraints of a given property. The
method isCascaded() returns
true, if the property is marked for cascaded validation
(either using the @Valid annotation or via XML),
false otherwise. Any configured group conversions are
returned by getGroupConversions(). See Section 9.5, “GroupConversionDescriptor” for more details on
GroupConversionDescriptor.

//driveAway(int) has a constrained parameter and an unconstrained return valueMethodDescriptor driveAwayDescriptor = carDescriptor.getConstraintsForMethod("driveAway",int.class);assertEquals("driveAway", driveAwayDescriptor.getName());assertTrue( driveAwayDescriptor.hasConstrainedParameters());assertFalse( driveAwayDescriptor.hasConstrainedReturnValue());//always returns an empty set; constraints are retrievable by navigating to//one of the sub-descriptors, e.g.for the return valueassertTrue( driveAwayDescriptor.getConstraintDescriptors().isEmpty());ParameterDescriptor speedDescriptor = driveAwayDescriptor.getParameterDescriptors().get(0);//The"speed" parameter is located at index 0, has one constraint and is not cascaded//nor does it define group conversionsassertEquals("arg0", speedDescriptor.getName());assertEquals(0, speedDescriptor.getIndex());assertEquals(1, speedDescriptor.getConstraintDescriptors().size());assertFalse( speedDescriptor.isCascaded());assert speedDescriptor.getGroupConversions().isEmpty();//getDriver() has no constrained parameters but its return value is marked for cascaded//validation and declares one group conversionMethodDescriptor getDriverDescriptor = carDescriptor.getConstraintsForMethod("getDriver");assertFalse( getDriverDescriptor.hasConstrainedParameters());assertTrue( getDriverDescriptor.hasConstrainedReturnValue());ReturnValueDescriptor returnValueDescriptor = getDriverDescriptor.getReturnValueDescriptor();assertTrue( returnValueDescriptor.getConstraintDescriptors().isEmpty());assertTrue( returnValueDescriptor.isCascaded());assertEquals(1, returnValueDescriptor.getGroupConversions().size());//load(List<Person>,List<PieceOfLuggage>) has one cross-parameter constraintMethodDescriptor loadDescriptor = carDescriptor.getConstraintsForMethod("load",List.class,List.class);assertTrue( loadDescriptor.hasConstrainedParameters());assertFalse( loadDescriptor.hasConstrainedReturnValue());assertEquals(1, loadDescriptor.getCrossParameterDescriptor().getConstraintDescriptors().size());//Car(String,String,Person,String) has one constrained parameterConstructorDescriptor constructorDescriptor = carDescriptor.getConstraintsForConstructor(String.class,String.class,Person.class,String.class);assertEquals("Car", constructorDescriptor.getName());assertFalse( constructorDescriptor.hasConstrainedReturnValue());assertTrue( constructorDescriptor.hasConstrainedParameters());assertEquals(1, constructorDescriptor.getParameterDescriptors().get(0).getConstraintDescriptors().size());

getName() returns the name of the given
method or constructor. The methods
hasConstrainedParameters() and
hasConstrainedReturnValue() can be used to
perform a quick check whether an executable element has any parameter
constraints (either constraints on single parameters or cross-parameter
constraints) or return value constraints.

Note that any constraints are not directly exposed on
MethodDescriptor and
ConstructorDescriptor, but rather on dedicated
descriptors representing an executable's parameters, its return value and
its cross-parameter constraints. To get hold of one of these descriptors,
invoke getParameterDescriptors(),
getReturnValueDescriptor() or
getCrossParameterDescriptor(),
respectively.

These descriptors provide access to the element's constraints
(getConstraintDescriptors()) and, in case of
parameters and return value, to its configuration for cascaded validation
(isValid() and
getGroupConversions()). For parameters, you also
can retrieve the index and the name, as returned by the currently used
parameter name provider (see Section 8.2.4, “ParameterNameProvider”) via
getName() and
getIndex().

Tip

Getter methods following the JavaBeans naming conventions are
considered as bean properties but also as constrained methods.

That means you can retrieve the related metadata either by
obtaining a PropertyDescriptor (e.g.
BeanDescriptor.getConstraintsForProperty("foo")) or by
examining the return value descriptor of the getter's
MethodDescriptor (e.g.
BeanDescriptor.getConstraintsForMethod("getFoo").getReturnValueDescriptor()).

9.4. ElementDescriptor

The ElementDiscriptor
interface is the common base class for the individual descriptor types
such as BeanDescriptor,
PropertyDescriptor etc. Besides
getConstraintDescriptors() it provides some more
methods common to all descriptors.

hasConstraints() allows for a quick check whether an
element has any direct constraints (e.g. class-level constraints in case
of BeanDescriptor).
getElementClass() returns the Java type of the
element represented by a given descriptor. More specifically, the method
returns

the object type when invoked on
BeanDescriptor,

the type of a property or parameter when invoked on
PropertyDescriptor or
ParameterDescriptor respectively,

Object[].class when invoked on
CrossParameterDescriptor,

the return type when invoked on
ConstructorDescriptor,
MethodDescriptor or
ReturnValueDescriptor.
void.class will be returned for methods which
don't have a return value.

Finally, ElementDescriptor offers access to
the ConstraintFinder API which allows you to query
for constraint metadata in a fine grained way. Example 9.6, “Usage of ConstraintFinder” shows how to retrieve a
ConstraintFinder instance via
findConstraints() and use the API to query for
constraint metadata.

Example 9.6. Usage of ConstraintFinder

PropertyDescriptor manufacturerDescriptor = carDescriptor.getConstraintsForProperty("manufacturer");//"manufacturer" constraints are declared on the getter, not the fieldassertTrue( manufacturerDescriptor.findConstraints().declaredOn(ElementType.FIELD ).getConstraintDescriptors().isEmpty());//@NotNull on Vehicle#getManufacturer() is part of another groupassertEquals(1, manufacturerDescriptor.findConstraints().unorderedAndMatchingGroups(Default.class).getConstraintDescriptors().size());//@Size on Car#getManufacturer()assertEquals(1, manufacturerDescriptor.findConstraints().lookingAt(Scope.LOCAL_ELEMENT ).getConstraintDescriptors().size());//@Size on Car#getManufacturer() and @NotNull on Vehicle#getManufacturer()assertEquals(2, manufacturerDescriptor.findConstraints().lookingAt(Scope.HIERARCHY ).getConstraintDescriptors().size());//Combining several filter optionsassertEquals(1, manufacturerDescriptor.findConstraints().declaredOn(ElementType.METHOD ).lookingAt(Scope.HIERARCHY ).unorderedAndMatchingGroups(Vehicle.Basic.class).getConstraintDescriptors().size());

Via declaredOn() you can search for
ConstraintDescriptors declared on certain element
types. This is useful to find property constraints declared on either
fields or getter methods.

unorderedAndMatchingGroups() restricts the
resulting constraints to those matching the given validation
group(s).

lookingAt() allows to distinguish between
constraints directly specified on the element
(Scope.LOCAL_ELEMENT) or constraints belonging to the
element but hosted anywhere in the class hierarchy
(Scope.HIERARCHY).

You can also combine the different options as shown in the last
example.

Warning

Order is not respected by
unorderedAndMatchingGroups(), but group
inheritance and inheritance via sequence are.

9.5. GroupConversionDescriptor

All those descriptor types that represent elements which can be
subject of cascaded validation (i.e.,
PropertyDescriptor,
ParameterDescriptor and
ReturnValueDescriptor) provide access to the
element's group conversions via
getGroupConversions(). The returned set contains
a GroupConversionDescriptor
for each configured conversion, allowing to retrieve source and target
groups of the conversion. Example 9.7, “Using GroupConversionDescriptor” shows an
example.

9.6. ConstraintDescriptor

Last but not least, the ConstraintDescriptor
interface describes a single constraint together with its composing
constraints. Via an instance of this interface you get access to the
constraint annotation and its parameters.

Example 9.8, “Using ConstraintDescriptor” shows
how to retrieve default constraint attributes (such as message template,
groups etc.) as well as custom constraint attributes
(piecesOfLuggagePerPassenger) and other metadata such
as the constraint's annotation type and its validators from a
ConstraintDescriptor.

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.

10.1. ORM integration

Hibernate Validator integrates with both Hibernate and all pure Java
Persistence providers.

Tip

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.

10.1.1. Database schema-level validation

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.

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.

10.1.2. Hibernate event-based validation

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 ConstraintViolations 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.

Note

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:

10.1.3. JPA

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.

10.2. JSF & Seam

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.

Tip

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}

10.3. CDI

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”.

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.

Tip

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.

10.3.2. Method validation

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.

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.

10.3.2.1. Validated executable types

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:

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.

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.

Tip

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.

In this chapter you will learn how to make use of several features
provided by Hibernate Validator in addition to the functionality defined by
the Bean Validation specification. This includes the fail fast mode, the API
for programmatic constraint configuration and the boolean composition of
constraints.

Note

Using the features described in the following sections may result in
application code which is not portable between Bean Validation
providers.

11.1. Public API

Let's start, however, with a look at the public API of Hibernate
Validator. Table 11.1, “Hibernate Validator public API” lists all packages
belonging to this API and describes their purpose. Note that when a
package is part of the public this is not necessarily true for its
sub-packages.

Table 11.1. Hibernate Validator public API

Packages

Description

org.hibernate.validator

Classes used by the Bean Validation bootstrap mechanism
(eg. validation provider, configuration class); For more details
see Chapter 8, Bootstrapping.

Hibernate Validator's fluent API for constraint
declaration; In org.hibernate.validator.cfg you
will find the ConstraintMapping interface
and in org.hibernate.validator.cfg.defs all
constraint definitions. Refer to Section 11.3, “Programmatic constraint declaration” for the details.

Some useful custom constraints provided by Hibernate
Validator in addition to the built-in constraints defined by the
Bean Validation specification; The constraints are described in
detail in Section 2.3.2, “Additional constraints”.

Note

The public packages of Hibernate Validator fall into two
categories: while the actual API parts are intended to be
invoked or used by clients
(e.g. the API for programmatic constraint declaration or the custom
constraints), the SPI (service provider interface) packages contain
interfaces which are intended to be implemented by
clients (e.g. ResourceBundleLocator).

Any packages not listed in that table are internal packages of
Hibernate Validator and are not intended to be accessed by clients. The
contents of these internal packages can change from release to release
without notice, thus possibly breaking any client code relying on
it.

11.2. Fail fast mode

Using the fail fast mode, Hibernate Validator allows to return from
the current validation as soon as the first constraint violation occurs.
This can be useful for the validation of large object graphs where you are
only interested in a quick check whether there is any constraint violation
at all.

Here the validated object actually fails to satisfy both the
constraints declared on the Car class, yet the
validation call yields only one ConstraintViolation
since the fail fast mode is enabled.

Note

There is no guarantee in which order the constraints are
evaluated, i.e. it is not deterministic whether the returned violation
originates from the @NotNull or the
@AssertTrue constraint. If required, a
deterministic evaluation order can be enforced using group sequences as
described in Section 5.2, “Defining group sequences”.

11.3. Programmatic constraint declaration

As per the Bean Validation specification, you can declare
constraints using Java annotations and XML based constraint
mappings.

In addition, Hibernate Validator provides a fluent API which allows
for the programmatic configuration of constraints. Use cases include the
dynamic addition of constraints at runtime depending on some application
state or tests where you need entities with different constraints in
different scenarios but don't want to implement actual Java classes for
each test case.

By default, constraints added via the fluent API are additive to
constraints configured via the standard configuration capabilities. But it
is also possible to ignore annotation and XML configured constraints where
required.

The API is centered around the
ConstraintMapping interface. You obtain a new
mapping via
HibernateValidatorConfiguration#createConstraintMapping()
which you then can configure in a fluent manner as shown in Example 11.2, “Programmatic constraint declaration”.

Constraints can be configured on multiple classes and properties
using method chaining. The constraint definition classes
NotNullDef and SizeDef are
helper classes which allow to configure constraint parameters in a
type-safe fashion. Definition classes exist for all built-in constraints
in the org.hibernate.validator.cfg.defs package. By
calling ignoreAnnotations() any constraints
configured via annotations or XML are ignored for the given
element.

Note

Each element (type, property, method etc.) may only be configured
once within all the constraint mappings used to set up one validator
factory. Otherwise a ValidationException is
raised.

Note

It is not supported to add constraints to non-overridden supertype
properties and methods by configuring a subtype. Instead you need to
configure the supertype in this case.

Having configured the mapping, you must add it back to the
configuration object from which you then can obtain a validator
factory.

By invoking valid() you can mark a member
for cascaded validation which is equivalent to annotating it with
@Valid. Configure any group conversions to be
applied during cascaded validation using the
convertGroup() method (equivalent to
@ConvertGroup). An example can be seen in Example 11.4, “Marking a property for cascaded validation”.

You can not only configure bean constraints using the fluent API but
also method and constructor constraints. As shown in Example 11.5, “Programmatic declaration of method and constructor
constraints” constructors are identified
by their parameter types and methods by their name and parameter types.
Having selected a method or constructor, you can mark its parameters
and/or return value for cascaded validation and add constraints as well as
cross-parameter constraints.

11.4. Boolean composition of constraints

Bean Validation specifies that the constraints of a composed
constraint (see Section 6.4, “Constraint composition”) are all
combined via a logical AND. This means all of the
composing constraints need to return true in order
for an overall successful validation.

Hibernate Validator offers an extension to this and allows you to
compose constraints via a logical OR or
NOT. To do so you have to use the
ConstraintComposition annotation and the enum
CompositionType with its values
AND, OR and
ALL_FALSE.

Example 11.7, “OR composition of constraints” shows how
to build a composed constraint @PatternOrSize where
only one of the composing constraints needs to be valid in order to pass
the validation. Either the validated string is all lower-cased or it is
between two and three characters long.

11.5. ResourceBundleLocator

With ResourceBundleLocator, Hibernate
Validator provides an additional SPI which allows to retrieve error
messages from other resource bundles than
ValidationMessages while still using the actual
interpolation algorithm as defined by the specification. Refer to Section 4.2.1, “ResourceBundleLocator” to learn how to make use of
that SPI.

11.6. Custom contexts

The Bean Validation specification offers at several points in its
API the possibility to unwrap a given interface to a implementor specific
subtype. In the case of constraint violation creation in
ConstraintValidator implementations as well as
message interpolation in Messageinterpolator
instances, there exist unwrap() methods for the
provided context instances -
ConstraintValidatorContext respectively
MessageInterpolatorContext. Hibernate Validator
provides custom extensions for both of these interfaces.

Note

Note that the parameters specified via
addExpressionVariable(String, Object) are
global and apply for all constraint violations created by this
isValid() invocation. This includes the
default constraint violation, but also all violations created by the
ConstraintViolationBuilder. You can, however,
update the parameters between invocations of
ConstraintViolationBuilder#addConstraintViolation().

Warning

This functionality is currently experimental and might change in
future versions.

11.6.2. HibernateMessageInterpolatorContext

Hibernate Validator also offers a custom extension of
MessageInterpolatorContext, namely
HibernateMessageInterpolatorContext (see Example 11.9, “HibernateMessageInterpolatorContext”). This subtype
was introduced to allow a better integration of Hibernate Validator into
the Glassfish. The root bean type was in this case needed to determine
the right classloader for the message resource bundle. If you have any
other usecases, let us know.

11.7. ParaNamer based
ParameterNameProvider

Hibernate Validator comes with a
ParameterNameProvider implementation which
leverages the ParaNamer library.

This library provides several ways for obtaining parameter names at
runtime, e.g. based on debug symbols created by the Java compiler,
constants with the parameter names woven into the bytecode in a
post-compile step or annotations such as the @Named
annotation from JSR 330.

In order to use
ParanamerParameterNameProvider, either pass an
instance when bootstrapping a validator as shown in Example 8.8, “Using a custom
ParameterNameProvider” or specify
org.hibernate.validator.parameternameprovider.ParanamerParameterNameProvider
as value for the <parameter-name-provider>
element in the META-INF/validation.xml file.

Tip

When using this parameter name provider, you need to add the
ParaNamer library to your classpath. It is available in the Maven
Central repository with the group id
com.thoughtworks.paranamer and the artifact id
paranamer.

By default ParanamerParameterNameProvider
retrieves parameter names from constants added to the byte code at build
time (via DefaultParanamer) and debug symbols (via
BytecodeReadingParanamer). Alternatively you can
specify a Paranamer implementation of your choice
when creating a ParanamerParameterNameProvider
instance.

Note

The concept of value unwrapping is considered experimental at this
time and may evolve into more general means of value handling in future
releases. Please let us know about your use cases for such functionality.

In JavaFX, bean properties are typically not of simple data types
like String or int, but are
wrapped in Property types which allows to make them
observable, use them for data binding etc. When applying a constraint such
as @Size to an element of type
Property<String> without further preparation,
an exception would be raised, indicating that no suitable validator for
that constraint and data type can be found. Thus the validated value must
be unwrapped from the containing property object before looking up a
validator and invoking it.

To do so, put the @UnwrapValidatedValue
annotation to the element in question. This will advice the validation
engine to look for an unwrapper implementation which returns the data type
to be used for constraint validator resolution and unwraps the validated
value. Unwrapper types must extend the SPI class
ValidatedValueUnwrapper as shown in
Example 11.11, “Implementing the ValidatedValueUnwrapper
interface”.

Several unwrapper implementations can be registered when working
with different kinds of wrapper types in one application. Note that it is
not specified which of the unwrapper implementations is chosen when more
than one implementation is suitable to unwrap a given element.

Alternatively, the fully-qualified names of one ore more unwrapper
implementations can be specified via the configuration property
hibernate.validator.validated_value_handlers which
can be useful when configuring the default validator factory using the
descriptor META-INF/validation.xml (see Chapter 7, Configuring via XML).

annotating the setter of a JavaBeans property (instead of the
getter method)

annotating static fields/methods with constraint annotations
(which is not supported)?

Then the Hibernate Validator Annotation Processor is the right thing
for you. It helps preventing such mistakes by plugging into the build
process and raising compilation errors whenever constraint annotations are
incorrectly used.

Tip

You can find the Hibernate Validator Annotation Processor as part of
the distribution bundle on Sourceforge
or in the usual Maven repositories such as Maven Central under the GAV
org.hibernate:hibernate-validator-annotation-processor:5.1.3.Final.

12.1. Prerequisites

The Hibernate Validator Annotation Processor is based on the
"Pluggable Annotation Processing API" as defined by JSR 269 which is part of
the Java Platform since Java 6.

Controls how constraint problems are reported. Must be the
string representation of one of the values from the enum
javax.tools.Diagnostic.Kind, e.g.
WARNING. A value of
ERROR will cause compilation to halt
whenever the AP detects a constraint problem. Defaults to
ERROR.

methodConstraintsSupported

Controls whether constraints are allowed at methods of any
kind. Must be set to true when working with
method level constraints as supported by Hibernate Validator. Can
be set to false to allow constraints only at
JavaBeans getter methods as defined by the Bean Validation API.
Defaults to true.

verbose

Controls whether detailed processing information shall be
displayed or not, useful for debugging purposes. Must be either
true or false. Defaults to
false.

12.4. Using the Annotation Processor

This section shows in detail how to integrate the Hibernate
Validator Annotation Processor into command line builds (javac, Ant,
Maven) as well as IDE-based builds (Eclipse, IntelliJ IDEA,
NetBeans).

12.4.1. Command line builds

12.4.1.1. javac

When compiling on the command line using javac,
specify the JAR hibernate-validator-annotation-processor-5.1.3.Final.jar
using the "processorpath" option as shown in the following listing.
The processor will be detected automatically by the compiler and
invoked during compilation.

The processor will then be executed automatically by the
compiler. This basically works, but comes with the disadavantage that
in some cases messages from the annotation processor are not displayed
(see MCOMPILER-66).

Another option is using the Maven
Annotation Plugin. To work with this plugin, disable the
standard annotation processing performed by the compiler plugin and
configure the annotation plugin by specifying an execution and adding
the Hibernate Validator Annotation Processor as plugin dependency
(that way the processor is not visible on the project's actual
classpath):

Any constraint annotation problems will then be marked directly
within the editor:

12.5. Known issues

The following known issues exist as of May 2010:

HV-308:
Additional validators registered for a constraint using
XML are not evaluated by the annotation processor.

Sometimes custom constraints can't be properly
evaluated when using the processor within Eclipse. Cleaning
the project can help in these situations. This seems to be an issue
with the Eclipse JSR 269 API implementation, but further investigation
is required here.

When using the processor within Eclipse, the check of dynamic
default group sequence definitions doesn't work. After further
investigation, it seems to be an issue with the Eclipse JSR 269 API
implementation.

Chapter 13. Further reading

Last but not least, a few pointers to further information.

A great source for examples is the Bean Validation TCK which is
available for anonymous access on GitHub.
In particular the TCK's tests
might be of interest. The JSR 349
specification itself is also a great way to deepen your understanding of
Bean Validation resp. Hibernate Validator.