Preface

Validating data is a common task that occurs throughout any
application, from the presentation layer to the persistence layer. Often the
same validation logic is implemented in each layer, proving time consuming
and error-prone. To avoid duplication of these validations in each layer,
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 303 - Bean Validation - defines a metadata model and API for
entity validation. The default metadata source is 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 or programming model. It is
specifically not tied to either the web tier or the 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. The
implementation itself as well as the Bean Validation API and TCK are all
provided and distributed under the Apache Software License
2.0.

Maven will create your project in the directory hv-quickstart.
Change into this directory and run:

mvn test

Maven will compile the
example code and run the implemented unit tests. Let's have a look at the
actual code in the next section.

Tip

For the purposes of logging, Hibernate Validator uses the JBoss
Logging API. This is an abstraction layer which supports several known
logging solutions (e.g. log4j or the logging framework provided by the
JDK) as implementation. Just add your preferred logging library to the
classpath and all log requests from Hibernate Validator will
automatically be delegated to that logging provider.

Alternatively, you can explicitely specify a provider using the
system property org.jboss.logging.provider. Supported
values currently are jboss, jdk,
log4j and slf4j.

1.2. Applying constraints

Open the project in the IDE of your choice and have a look at the
class Car:

In the setUp() method we get a
Validator instance from the
ValidatorFactory. A
Validator instance is thread-safe and may be reused
multiple times. For this reason we store it as field of our test class. We
can use the Validator now to validate the different
car instances in the test methods.

The validate() method returns a set of
ConstraintViolation instances, which we can iterate
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.

Note that we only use classes from the package
javax.validation from the Bean Validation API. As we
don't reference any classes of the RI directly, it would be no problem to
switch to another implementation of the API, should that need
arise.

In this chapter we will see in more detail how to use Hibernate
Validator to validate constraints for a given entity model. We will also
learn which default constraints the Bean Validation specification provides
and which additional constraints are only provided by Hibernate Validator.
Let's start with how to add constraints to an entity.

2.1. Defining constraints

Constraints in Bean Validation are expressed via Java annotations.
In this section we show how to annotate an object model with these
annotations. We have to differentiate between three different type of
constraint annotations - field-, property-, and class-level
annotations.

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 3, 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 bean validation
provider directly accesses the instance variable and does not invoke the
property accessor method also if such a method exists.

Note

The access type (private, protected or public) does not
matter.

Note

Static fields and properties cannot be validated.

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.

When using property level constraints property access strategy is
used to access the value to be validated. This means the bean validation
provider accesses the state via the property accessor method. One
advantage of annotating properties instead of fields is that the
constraints become part of the constrained type's API that way and users
are aware of the existing constraints without having to examine the
type's implementation.

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 class
level. When a constraint annotation is placed on this level the class
instance itself passed to the
ConstraintValidator. Class level constraints are
useful if it is necessary to inspect more than a single property of the
class to validate it or if a correlation between different state
variables has to be evaluated. In Example 2.3, “Class level constraint”
we add the property passengers to the class
Car. We also add the constraint
PassengerCount on the class level. We will later
see how we can actually create this custom constraint (see Chapter 3, Creating custom constraints). For now it is enough to know
that PassengerCount will ensure that there cannot
be more passengers in a car than there are seats.

2.1.4. Constraint inheritance

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

Our well-known class Car is now extended by
RentalCar with the additional property
rentalStation. If an instance of
RentalCar is validated, not only the
@NotNull constraint on
rentalStation is validated, but also the constraint
on manufacturer from the parent class.

The same would hold true, if Car were an
interface implemented by RentalCar.

Constraint annotations are aggregated if methods are overridden.
If RentalCar would override the
getManufacturer() method from
Car any constraints annotated at the overriding
method would be evaluated in addition to the
@NotNull constraint from the super-class.

2.1.5. Object graphs

The Bean Validation API does not only allow to validate single
class instances but also complete object graphs. To do so, just annotate
a field or property representing a reference to another object with
@Valid. If the parent object is validated, all
referenced objects annotated with @Valid will be
validated as well (as will be their children etc.). See Example 2.6, “Adding a driver to the car”.

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.

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.

If a Car instance is validated, a
ConstraintValidation will be created, if any of
the Person objects contained in the
passengers list has a null name.

Note

null values are getting ignored when
validating object graphs.

2.2. Validating constraints

The Validator interface is the main entry
point to Bean Validation. In Section 5.1, “Configuration and
ValidatorFactory”
we will first show how to obtain an Validator
instance. Afterwards we will 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
Validation.buildDefaultValidatorFactory()
method:

For other ways of obtaining a Validator instance see Chapter 5, Bootstrapping. For now we just want to see how we
can use the Validator instance to validate entity
instances.

2.2.2. Validator methods

The Validator interface contains three
methods that can be used to either validate entire entities or just a
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) will be used.
We will go into more detail on the topic of validation groups in Section 2.3, “Validating groups”

Note

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

2.2.3. ConstraintViolation methods

Now it is time to have a closer look at what a
ConstraintViolation. Using the different methods
of ConstraintViolation a lot of useful
information about the cause of the validation failure can be determined.
Table 2.1, “The various ConstraintViolation
methods” gives an overview of these
methods:

If a bean constraint, the bean instance the constraint is
applied on. If a property constraint, the bean instance hosting
the property the constraint is applied on.

car

getPropertyPath()

The property path to the value from root bean.

getInvalidValue()

The value failing to pass the constraint.

passengers

getConstraintDescriptor()

Constraint metadata reported to fail.

2.2.4. Message interpolation

As we will see in Chapter 3, Creating custom constraints
each constraint definition must define a default message descriptor.
This message can be overridden at declaration time using the
message attribute of the constraint. You can
see this in Example 2.13, “Driver”. This message descriptors
get interpolated when a constraint validation fails using the configured
MessageInterpolator. The interpolator will try to
resolve any message parameters, meaning string literals enclosed in
braces. In order to resolve these parameters Hibernate Validator's
default MessageInterpolator first recursively
resolves parameters against a custom
ResourceBundle called
ValidationMessages.properties at the root of the
classpath (It is up to you to create this file). If no further
replacements are possible against the custom bundle the default
ResourceBundle under
/org/hibernate/validator/ValidationMessages.properties
gets evaluated. If a replacement occurs against the default bundle the
algorithm looks again at the custom bundle (and so on). Once no further
replacements against these two resource bundles are possible remaining
parameters are getting resolved against the attributes of the constraint
to be validated.

Since the braces { and } have special meaning in the messages they
need to be escaped if they are used literally. The following The
following rules apply:

\{ is considered as the literal {

\} is considered as the literal }

\\ is considered as the literal \

If the default message interpolator does not fit your requirements
it is possible to plug a custom
MessageInterpolator when the
ValidatorFactory gets created. This can be seen
in Chapter 5, Bootstrapping.

2.3. Validating groups

Groups allow you to restrict the set of constraints applied during
validation. This makes for example wizard like validation possible where
in each step only a specified subset of constraints get validated. The
groups targeted are passed as var-args parameters to
validate,
validateProperty and
validateValue. Let's have a look at an extended
Car with Driver example.
First we have the class Person (Example 2.12, “Person”) which has a @NotNull
constraint on name. Since no group is
specified for this annotation its default group is
javax.validation.groups.Default.

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.

Next we have the class Driver (Example 2.13, “Driver”) extending Person. Here
we are adding the properties age and
hasDrivingLicense. In order to drive you must be at
least 18 (@Min(18)) and you must have a driving
license (@AssertTrue). Both constraints defined on
these properties belong to the group DriverChecks.
As you can see in Example 2.14, “Group interfaces” the group
DriverChecks is just a simple tagging interface.
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.

Overall three different groups are used in our example.
Person.name, Car.manufacturer,
Car.licensePlate and
Car.seatCount all belong to the
Default group. Driver.age and
Driver.hasDrivingLicense belong to
DriverChecks and last but not least
Car.passedVehicleInspection belongs to the group
CarChecks. Example 2.16, “Drive away”
shows how passing different group combinations to the
Validator.validate method result in different
validation results.

First we create a car and validate it 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. Next we just validate the
CarChecks group which will fail until we make sure
that the car passes the vehicle inspection. When we then add a driver to
the car and validate against DriverChecks we get
again a 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 will pass.

Last but not least, we show that all constraints are passing by
validating against all defined groups.

2.3.1. 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 our
example from Section 2.3, “Validating groups”
we could for example require that first all default car constraints are
passing before we check the road worthiness of the car. Finally before
we drive away we check the actual driver constraints. In order to
implement such an order one would define a new interface and annotate it
with @GroupSequence defining the order in which
the groups have to be validated.

Note

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.

2.3.2. Redefining the default group sequence of a class

2.3.2.1. @GroupSequence

The @GroupSequence annotation also
fulfills a second purpose. It allows you to redefine what the
Default group means for a given class. To
redefine Default for a given class, add a
@GroupSequence annotation to the class. The
defined groups in the annotation express the sequence of groups that
substitute Default for this class. Example 2.19, “RentalCar with @GroupSequence” introduces a new class
RentalCar with a redefined default group. With
this definition you can evaluate the constraints belonging to
RentalChecks, CarChecks
and RentalCar by just requesting the
Default group as seen in Example 2.20, “RentalCar with redefined default group”.

Note

Due to the fact that there cannot be a 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!

Note

The Default group sequence overriding
is local to the class it is defined on and is not propagated to the
associated objects. This means in particular 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 when validation a rental car instance.

2.3.2.2. @GroupSequenceProvider

The @javax.validation.GroupSequence
annotation is a standardized Bean Validation annotation. As seen in
the previous section it allows you to statically redefine the default
group sequence for a class. Hibernate Validator also offers a custom,
non standardized annotation -
org.hibernate.validator.group.GroupSequenceProvider
- which allows for dynamic redefinition of the default
group sequence. Using the rental car scenario again, one could
dynamically add the CarChecks as seen in Example 2.21, “RentalCar with @GroupSequenceProvider” and Example , “DefaultGroupSequenceProvider implementation”.

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

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

The annotated element must be a number whose value must
be lower 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

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

The annotated element must be a number whose value must
be higher 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,
String, byte,
short, int,
long and the respective wrappers of the
primitive types. Additionally supported by HV: any sub-type of
Number and
CharSequence.

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

Define 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

BigDecimal,
BigInteger, byte,
short, int,
long and the respective wrappers of the
primitive types. Additionally supported by HV: any sub-type
ofCharSequence (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.

Add a check constraint on the column.

@Min

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.

Add a check constraint on the column.

@NotNull

Any type

Checks that the annotated value is not
null.

Column(s) are not null.

@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=)

String. Additionally supported by
HV: any sub-type of CharSequence.

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

none

@Size(min=, max=)

String,
Collection, Map
and arrays. Additionally supported by HV:
any sub-type of CharSequence.

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 supports the
parameters message,
groups and payload. This
is a requirement of the Bean Validation specification.

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

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.

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 mod 10 or mod 11 checksum algorithm.
modType is used to select the modulo type
and the multiplier determines the algorithm
specific multiplier (see also Luhn
algorithm). startIndex and
endIndex allow to only run the modulo
algorithm on the specified sub-string.
checkDigitPosition allows to use an
arbitrary digit within the character sequence to be 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.

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.

none

@SafeHtml(whitelistType=, additionalTags=)

CharSequence

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 predefined whitelist types can be chosen. You can also
specify additional html tags for the whitelist with the
additionalTags attribute.

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.4.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.
We will discuss this in Chapter 3, Creating custom constraints.

Chapter 3. Creating custom constraints

Though the Bean Validation API defines a whole set of standard
constraint annotations one can easily think of situations in which these
standard annotations won't suffice. For these cases you are able to create
custom constraints tailored to your specific validation requirements in a
simple manner.

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

3.1.1. The constraint annotation

Let's write a constraint annotation, that can be used to express
that a given string shall either be upper case or lower case. We'll
apply it later on to the licensePlate field of the
Car class from Chapter 1, Getting started to ensure, that the field is
always an upper-case string.

First we need a way to express the two case modes. We might use
String constants, but a better way to go is to
use a Java 5 enum for that purpose:

Example 3.1. Enum CaseMode to express upper vs. lower
case

package com.mycompany;public enum CaseMode{ UPPER, LOWER;}

Now we can define the actual constraint annotation. If you've
never designed an annotation before, this may look a bit scary, but
actually it's not that hard:

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 Section 2.3, “Validating groups”).
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.

Tip

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 those three mandatory attributes
(message, groups and
payload) we add another one allowing for the
required case mode to be specified. The name value
is a special one, which can be omitted upon using the annotation, if it
is the only attribute specified, as e.g. in
@CheckCase(CaseMode.UPPER).

In addition we annotate the annotation type with a couple of
so-called meta annotations:

Tip

In order to use a custom constraint for parameter validation the
ElementType.PARAMETER must be specified within
the @Target annotation. This is already the
case for all constraints defined by the Bean Validation API and also
the custom constraints provided by Hibernate Validator.

3.1.2. The constraint
validator

Next, we need to implement a constraint validator, that's able to
validate elements with a @CheckCase annotation.
To do so, we implement the interface
ConstraintValidator as shown below:

Example 3.3. Implementing a constraint validator for the constraint
CheckCase

The ConstraintValidator interface defines
two type parameters, which we set in our implementation. The first one
specifies the annotation type to be validated (in our example
CheckCase), the second one the type of elements,
which the validator can handle (here
String).

In case a constraint annotation is allowed at elements of
different 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 us access to the
attribute values of the annotation to be validated. In the example we
store the CaseMode in a field of the validator
for further usage.

In the isValid() method we implement the
logic, that determines, whether a String is valid
according to a given @CheckCase annotation or
not. This decision depends on the case mode retrieved in
initialize(). As the Bean Validation
specification recommends, we consider null values as being
valid. If null is not a valid value for an element, it
should be annotated with @NotNull explicitly.

3.1.2.1. The ConstraintValidatorContext

Example 3.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 call. 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:

Example 3.4. Use of ConstraintValidatorContext to define custom error
messages

Tip

It is important to end each new constraint violation with
addConstraintViolation. Only after that
the new constraint violation will be created.

In case you are implementing a
ConstraintValidator a class level constraint it
is also possible to adjust set the property path for the created
constraint violations. This is important for the case where you
validate multiple properties of the class or even traverse the object
graph. A custom property path creation could look like Example 3.5, “Adding new ConstraintViolation with
custom property path”.

3.1.3. The error message

Finally we need to specify the error message, that shall be used,
in case a @CheckCase constraint is violated. To
do so, we add the following to our custom
ValidationMessages.properties (see also Section 2.2.4, “Message interpolation”)

com.mycompany.constraints.CheckCase.message=Case mode must be {value}.

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

3.1.4. Using the constraint

Now that our first custom constraint is completed, we can use it
in the Car class from the Chapter 1, Getting started chapter to specify that the
licensePlate field shall only contain upper-case
strings:

3.2. Constraint composition

Looking at the licensePlate field of the
Car class in Example 3.7, “Applying the CheckCase
constraint”, we 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 we had a licensePlate field in
another class, we would have to copy all constraint declarations to the
other class as well, violating the DRY principle.

This problem can be tackled using compound constraints. In the
following we create a new constraint annotation
@ValidLicensePlate, that comprises the constraints
@NotNull, @Size and
@CheckCase:

To do so, we just have to annotate the constraint declaration with
its comprising constraints (btw. that's exactly why we allowed annotation
types as target for the @CheckCase annotation). As
no additional validation is required for the
@ValidLicensePlate annotation itself, we don't
declare a validator within the @Constraint meta
annotation.

Using the new compound constraint at the
licensePlate field now is fully equivalent to the
previous version, where we declared the three constraints 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 4. XML configuration

4.1. validation.xml

The key to enable XML configuration for Hibernate Validator is the
file validation.xml. If this file exists in the
classpath its configuration will be applied when the
ValidationFactory gets created. Example 4.1, “validation-configuration-1.0.xsd” shows a model view of the xsd
valiation.xml has to adhere to.

Warning

There can only be one validation.xml in the
classpath. If more than one is found an exception is thrown.

All settings shown in the validation.xml are
optional and in the case of Example 4.2, “validation.xml” show
the defaults used within Hibernate Validator. The node
default-provider allows to choose the Bean Validation
provider. This is useful if there is more than one provider in the
classpath. message-interpolator,
traversable-resolver and
constraint-validator-factory allow to customize the
javax.validation.MessageInterpolator,
javax.validation.TraversableResolver resp.
javax.validation.ConstraintValidatorFactory. The
same configuration options are also available programmatically through the
javax.validation.Configuration. In fact XML
configuration will be overridden by values explicitly specified via the
API. It is even possible to ignore the XML configuration completely via
Configuration.ignoreXmlConfiguration(). See also
Chapter 5, Bootstrapping.

Via the constraint-mapping you can list an
arbitrary number of additional XML files containing the actual constraint
configuration. See Section 4.2, “Mapping constraints”.

Last but not least, you can specify provider specific properties via
the property nodes.

4.2. Mapping constraints

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

<constraint-mappingsxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd"xmlns="http://jboss.org/xml/ns/javax/validation/mapping"><default-package>org.hibernate.validator.quickstart</default-package><beanclass="Car"ignore-annotations="true"><fieldname="manufacturer"><constraintannotation="javax.validation.constraints.NotNull"/></field><fieldname="licensePlate"><constraintannotation="javax.validation.constraints.NotNull"/></field><fieldname="seatCount"><constraintannotation="javax.validation.constraints.Min"><elementname="value">2</element></constraint></field><fieldname="driver"><valid/></field><gettername="passedVehicleInspection"ignore-annotations="true"><constraintannotation="javax.validation.constraints.AssertTrue"><message>The car has to pass the vehicle inspection first</message><groups><value>CarChecks</value></groups><elementname="max">10</element></constraint></getter></bean><beanclass="RentalCar"ignore-annotations="true"><classignore-annotations="true"><group-sequence><value>RentalCar</value><value>CarChecks</value></group-sequence></class></bean><constraint-definitionannotation="org.mycompany.CheckCase"><validated-byinclude-existing-validators="false"><value>org.mycompany.CheckCaseValidator</value></validated-by></constraint-definition></constraint-mappings>

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
classname 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. If the same class is configured more than once an
exception is thrown.

Settings 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 and getter. If not
explicitly specified on these levels the configured
bean value applies. Otherwise do the nodes
class, fields and
getter determine on which level the constraints are
placed (see Section 2.1, “Defining constraints”). 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 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
ConstraintValidators described in XML are concatenated to the list of
validators described on the annotation.

Chapter 5. Bootstrapping

We already seen in Section 5.1, “Configuration and
ValidatorFactory” the
easiest way to create a Validator instance -
Validation.buildDefaultValidatorFactory. In this
chapter we have a look at the other methods in
javax.validation.Validation and how they allow to
configure several aspects of Bean Validation at bootstrapping time.

The different bootstrapping options allow, amongst other things, to
bootstrap any Bean Validation implementation on the classpath. Generally, an
available provider is discovered by the Java
Service Provider mechanism. A Bean Validation implementation
includes the file
javax.validation.spi.ValidationProvider in
META-INF/services. This file contains the fully
qualified classname of the ValidationProvider of the
implementation. In the case of Hibernate Validator this is
org.hibernate.validator.HibernateValidator.

Note

If there are more than one Bean Validation implementation providers
in the classpath and
Validation.buildDefaultValidatorFactory() is
used, there is no guarantee which provider will be chosen. To enforce the
provider Validation.byProvider() should be
used.

We will learn more about MessageInterpolator,
TraversableResolver and
ConstraintValidatorFactory in the following
sections.

Last but not least you can ask for a Configuration object of a
specific Bean Validation provider. This is useful if you have more than
one Bean Validation provider in your classpath. In this situation you can
make an explicit choice about which implementation to use. In the case of
Hibernate Validator the Validator creation looks
like:

Tip

The generated Validator instance is
thread safe and can be cached.

5.2. ValidationProviderResolver

In the case that the Java Service Provider mechanism does not work
in your environment or you have a special classloader setup, you are able
to provide a custom ValidationProviderResolver. An
example in an OSGi environment you could plug your custom provider
resolver like seen in Example 5.4, “Providing a custom ValidationProviderResolver”.

5.3. MessageInterpolator

Section 2.2.4, “Message interpolation” already discussed
the default message interpolation algorithm. If you have special
requirements for your message interpolation you can provide a custom
interpolator using
Configuration.messageInterpolator(). This message
interpolator will be shared by all validators generated by the
ValidatorFactory created from this
Configuration. Example 5.6, “Providing a custom MessageInterpolator” shows an interpolator (available
in Hibernate Validator) which can interpolate the value being validated in
the constraint message. To refer to this value in the constraint message
you can use:

${validatedValue}: this will call String.valueOf
on the validated value.

${validatedValue:<format>}: provide your own format
string which will be passed to String.format together
with the validated value. Refer to the javadoc of
String.format for more information about the format
options.

Tip

It is recommended that MessageInterpolator
implementations delegate final interpolation to the Bean Validation
default MessageInterpolator to ensure standard
Bean Validation interpolation rules are followed. The default
implementation is accessible through
Configuration.getDefaultMessageInterpolator().

5.3.1. ResourceBundleLocator

A common use case is the ability to specify your own resource
bundles for message interpolation. The default
MessageInterpolator implementation in Hibernate
Validator is called
ResourceBundleMessageInterpolator and per default
loads resource bundles via
ResourceBundle.getBundle. However,
ResourceBundleMessageInterpolator also allows you
to specify a custom implementation of
ResourceBundleLocator allowing you to provide
your own resource bundles. Example 5.7, “Providing a custom ResourceBundleLocator” shows an example. In the
example
HibernateValidatorConfiguration.getDefaultResourceBundleLocator
is used to retrieve the default
ResourceBundleLocator which then can be passed to
the custom implementation in order implement delegation.

Hibernate Validator provides the following implementation of
ResourceBundleLocator -
PlatformResourceBundleLocator (the default) and
AggregateResourceBundleLocator. The latter can be
used to specify a list of resource bundle names which will get loaded
and merged into a single resource bundle. Refer to the JavaDoc
documentation for more information.

5.4. TraversableResolver

The usage of the TraversableResolver has so
far not been discussed. The idea is that in some cases, the state of a
property should not be accessed. The most obvious example for that is a
lazy loaded property or association of a Java Persistence provider.
Validating this lazy property or association would mean that its state
would have to be accessed triggering a load from the database. Bean
Validation controls which property can and cannot be accessed via the
TraversableResolver interface (see Example 5.8, “TraversableResolver interface”). In the example
HibernateValidatorConfiguration.

Example 5.8. TraversableResolver interface

/** * Contract determining if a property can be accessed by the Bean Validation provider * This contract is called for each property that is being either validated or cascaded. * * A traversable resolver implementation must be thread-safe. * */publicinterfaceTraversableResolver{/** * Determine if the Bean Validation provider is allowed to reach the property state * * @param traversableObject object hosting <code>traversableProperty</code> or null * if validateValue is called * @param traversableProperty the traversable property. * @param rootBeanType type of the root object passed to the Validator. * @param pathToTraversableObject path from the root object to * <code>traversableObject</code> * (using the path specification defined by Bean Validator). * @param elementType either <code>FIELD</code> or <code>METHOD</code>. * * @return <code>true</code> if the Bean Validation provider is allowed to * reach the property state, <code>false</code> otherwise. */boolean isReachable(Object traversableObject,Path.Node traversableProperty,Class<?> rootBeanType,Path pathToTraversableObject,ElementType elementType);/** * Determine if the Bean Validation provider is allowed to cascade validation on * the bean instance returned by the property value * marked as <code>@Valid</code>. * Note that this method is called only if isReachable returns true for the same set of * arguments and if the property is marked as <code>@Valid</code> * * @param traversableObject object hosting <code>traversableProperty</code> or null * if validateValue is called * @param traversableProperty the traversable property. * @param rootBeanType type of the root object passed to the Validator. * @param pathToTraversableObject path from the root object to * <code>traversableObject</code> * (using the path specification defined by Bean Validator). * @param elementType either <code>FIELD</code> or <code>METHOD</code>. * * @return <code>true</code> if the Bean Validation provider is allowed to * cascade validation, <code>false</code> otherwise. */boolean isCascadable(Object traversableObject,Path.Node traversableProperty,Class<?> rootBeanType,Path pathToTraversableObject,ElementType elementType);}

Hibernate Validator provides two
TraversableResolvers out of the box which will be
enabled automatically depending on your environment. The first is the
DefaultTraversableResolver which will always return
true for isReachable() and
isTraversable(). The second is the
JPATraversableResolver which gets enabled when
Hibernate Validator gets used in combination with JPA 2. In case you have
to provide your own resolver you can do so again using the
Configuration object as seen in Example 5.9, “Providing a custom TraversableResolver”.

5.5. ConstraintValidatorFactory

Last but not least, there is one more configuration option to
discuss, the ConstraintValidatorFactory. The
default ConstraintValidatorFactory provided by
Hibernate Validator requires a public no-arg constructor to instantiate
ConstraintValidator instances (see Section 3.1.2, “The constraint
validator”). Using a custom
ConstraintValidatorFactory offers for example the
possibility to use dependency injection in constraint implementations. The
configuration of the custom factory is once more via the
Configuration (Example 5.10, “Providing a custom ConstraintValidatorFactory”).

Chapter 6. Metadata API

The Bean Validation specification provides not only a validation
engine, but also a metadata repository for all defined constraints. The
following paragraphs are discussing this API. All the introduced classes can
be found in the javax.validation.metadata package.

6.1. BeanDescriptor

The entry into the metadata API is via
Validator.getConstraintsForClass which returns an instance of
the BeanDescriptor
interface. Using this bean descriptor you can determine whether the
specified class hosts any constraints at all via
beanDescriptor.isBeanConstrained.

Tip

If a constraint declaration hosted by the requested class is
invalid, a ValidationException is
thrown.

You can then call
beanDescriptor.getConstraintDescriptors to get a set of
ConstraintDescriptors representing all class level
constraints.

If you are interested in property level constraints, you can call
beanDescriptor.getConstraintsForProperty or
beanDescriptor.getConstrainedProperties to get a single resp.
set of PropertyDescriptors (see Section 6.2, “PropertyDescriptor”).

6.2. PropertyDescriptor

The PropertyDescriptor
interface extends the ElementDescriptor interface
and represents constraints on properties of a class. The constraint can be
declared on the attribute itself or on the getter of the attribute -
provided Java Bean naming conventions are respected. A
PropertyDescriptor adds isCascaded
(returning true if the property is marked with
@Valid) and getPropertyName to the
ElementDescriptor functionality.

6.3. ElementDescriptor

The ElementDiscriptor
interface is the common base class for
BeanDescriptor and
PropertyDescriptor. Next to the
hasConstraints and getConstraintDescriptors
methods it also offers access to the
ConstraintFinder API which allows you to query the
metadata API in a more fine grained way. For example you can restrict your
search to constraints described on fields or on getters or a given set of
groups. Given an ElementDescriptor instance you
just call findConstraints to retrieve a
ConstraintFinder instance.

Example 6.1, “Usage of ConstraintFinder” shows an example on how
to use the ConstraintFinder API. Interesting are
especially the restrictions unorderedAndMatchingGroups and
lookingAt(Scope.LOCAL_ELEMENT).
The former allows to only return
ConstraintDescriptors matching a specified set of
groups wheras the latter allows to distinguish between constraint directly
specified on the element (Scope.LOCAL_ELEMENT) or
constraints belonging to the element but hosted anywhere in the class
hierarchy (Scope.HIERARCHY).

Warning

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

6.4. 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, as well as the groups the
constraint is supposed to be applied on. It also also you to access the
pass-through constraint payload (see Example 3.2, “Defining CheckCase constraint annotation”).

Chapter 7. Integration with other frameworks

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.

7.1. OSGi

The Hibernate Validator jar file is conform to the OSGi specification
and can be used within any OSGi container. The following lists represent the
packages imported and exported by Hibernate Validator. The classes within the
exported packages are considered part of Hibernate Validator public API.

Tip

The Java Service Provider mechanism used by Bean Validation to automatically
discover validation providers doesn't work in an OSGi environment. To solve this,
you have to provide a custom ValidationProviderResolver. See
Section 5.2, “ValidationProviderResolver”

Exported packages

org.hibernate.validator

org.hibernate.validator.constraints

org.hibernate.validator.cfg

org.hibernate.validator.cfg.context

org.hibernate.validator.cfg.defs

org.hibernate.validator.group

org.hibernate.validator.messageinterpolation

org.hibernate.validator.method

org.hibernate.validator.method.metadata

org.hibernate.validator.resourceloading

Imported packages

javax.persistence.*, [2.0.0,3.0.0), optional

javax.validation.*, [1.0.0,2.0.0)

javax.xml.*

org.xml.sax.*

org.jboss.logging.*, [3.1.0,4.0.0)

org.joda.time.*, [1.6.0,2.0.0), optional

org.jsoup.*, [1.5.2,2.0.0), optional

7.2. Database schema-level validation

Out of the box, Hibernate Annotations (as of Hibernate 3.5.x) will
translate the constraints you have defined for your entities into mapping
metadata. For example, if a property of your entity is annotated
@NotNull, its columns will be declared as not
null in the DDL schema generated by Hibernate.

If, for some reason, the feature needs to be disabled, set
hibernate.validator.apply_to_ddl to
false. See also ???.

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.

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

7.3.1. 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 7.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:

7.3.2. 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 7.3.1, “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 7.3.1, “Hibernate event-based validation” to your
project and register it manually.

7.4. Presentation layer validation

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 7.2, “Usage of Bean Validation within JSF2” shows an example of the f:validateBean tag
in a JSF page. 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):

In the following sections we are having a closer look at some of the
Hibernate Validator specific features (features which are not part of the
Bean Validation specification). This includes the fail fast mode, the
programmatic constraint configuration API and boolean composition of
composing constraints.

Note

The features described in the following sections are not portable
between Bean Validation providers/implementations.

8.1. Public API

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.

Note

In the following table, when a package is public its not
necessarily true for its nested packages.

Table 8.1. Hibernate Validator public API

Packages

Description

org.hibernate.validator

This package contains the classes used by the Bean
Validation bootstrap mechanism (eg. validation provider,
configuration class). For more details see Chapter 5, Bootstrapping.

With Hibernate Validator you can define constraints via a
fluent API. These packages contain all classes needed to use this
feature. In the package
org.hibernate.validator.cfg you will find the
ConstraintMapping class and in package
org.hibernate.validator.cfg.defs all constraint
definitions. For more details see Section 8.4, “Programmatic constraint definition”.

With Hibernate Validator you can define dynamic default
group sequences in function of the validated object state. These
packages contain all classes needed to use this feature
(GroupSequenceProvider annotation and
DefaultGroupSequenceProvider contract). For
more details see Section 2.3.2, “Redefining the default group sequence of a class”.

These packages contain the classes related to constraint
message interpolation. The first package contains two
implementations of MessageInterpolator. The
first one,
ValueFormatterMessageInterpolator allows to
interpolate the validated value into the constraint message, see
Section 5.3, “MessageInterpolator”. The second
implementation named
ResourceBundleMessageInterpolator is the
implementation used by default by Hibernate Validator. This
implementation relies on a
ResourceBundleLocator, see Section 5.3.1, “ResourceBundleLocator”. Hibernate Validator
provides different ResourceBundleLocator
implementations located in the package
org.hibernate.validator.resourceloading.

Hibernate Validator provides support for method-level
constraints based on appendix C of the Bean Validation
specification. The first package contains the
MethodValidator interface allowing you to
validate method return values and parameters. The second package
contains meta data for constraints hosted on parameters and
methods which can be retrieved via the
MethodValidator.

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

8.3. Method validation

The Bean Validation API allows to specify constraints for fields,
properties and types. Hibernate Validator goes one step further and allows
to place contraint annotations also on method parameters and method return
values, thus enabling a programming style known as "Programming by
Contract".

More specifically this means that Bean Validation constraints can be
used to specify

the preconditions that must be met before a method invocation
(by annotating method parameters with constraints) and

the postconditions that are guaranteed after a method invocation
(by annotating methods)

This approach has several advantages over traditional ways of
parameter and return value checking:

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

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

Note

Method validation was also considered to be included in the Bean
Validation API as defined by JSR 303, but it didn't become part of the
1.0 version. A basic draft is outlined in appendix C of the
specification, and the implementation in Hibernate Validator is largely
influenced by this draft. The feature is considered again for inclusion
in BV 1.1.

Here all the constraints declared at the
Customer type will be evaluated when validating
the method parameter and all constraints declared at the returned
Rental objects will be evaluated when validating
the method's return value.

8.3.1.1. Using method constraints in type hierarchies

Special care must be taken when defining parameter constraints
in inheritance hierarchies.

When a method is overridden in sub-types method parameter
constraints can only be declared at the base type. The reason for this
restriction is that the preconditions to be fulfilled by a type's
client must not be strengthened in sub-types (which may not even be
known to the base type's client). Note that also if the base method
doesn't declare any parameter constraints at all, no parameter
constraints may be added in overriding methods.

The same restriction applies to interface methods: no parameter
constraints may be defined at the implementing method (or the same
method declared in sub-interfaces).

This rule only applies to parameter constraints, return value
constraints may be added in sub-types without any restrictions as it
is alright to strengthen the postconditions guaranteed to a type's
client.

8.3.2. Evaluating method-level constraints

As shown in Example 8.7, “The MethodValidator interface” this
interface defines methods for the evaluation of parameter as well as
return value constraints and for retrieving an extended type descriptor
providing method constraint related meta data.

The validation methods defined on
MethodValidator each return a
Set<MethodConstraintViolation>. The type
MethodConstraintViolation (see Example 8.9, “The MethodConstraintViolation
type”) extends
javax.validation.ConstraintViolation and provides
additional method level validation specific information such as the
method and index of the parameter which caused the constraint
violation.

Note

The method getParameterName() currently
returns synthetic parameter identifiers such as "arg0", "arg1" etc. In
a future version of Hibernate Validator support for specifying
parameter identifiers might be added.

Typically the validation of method-level constraints is not
invoked manually but automatically upon method invocation by an
integration layer using AOP (aspect-oriented programming) or similar
method interception facilities such as the JDK's
java.lang.reflect.Proxy API or CDI ("JSR 299:
Contexts and Dependency Injection for the
JavaTM EE platform").

If a parameter or return value constraint can't be validated
sucessfully such an integration layer typically will throw a
MethodConstraintViolationException which similar
to javax.validation.ConstraintViolationException
contains a set with the occurred constraint violations.

Tip

If you are using CDI you might be interested in the Seam
Validation project. This Seam module provides an interceptor
which integrates the method validation functionality with CDI.

Refer to the JavaDoc
of the package
org.hibernate.validator.method.metadata for more
details on the extended meta data API.

8.4. Programmatic constraint definition

Another addition to the Bean Validation specification is the ability
to configure constraints via a fluent API. This API can be used
exclusively or in combination with annotations and xml. If used in
combination programmatic constraints are additive to constraints
configured via the standard configuration capabilities.

The API is centered around the
ConstraintMapping class which can be found in the
package org.hibernate.validator.cfg. Starting with the
instantiation of a new ConstraintMapping,
constraints can be defined in a fluent manner as shown in Example 8.11, “Programmatic constraint definition”.

As you can see constraints can be configured on multiple classes and
properties using method chaining. The constraint definition classes
NotNullDef, SizeDef and
MinDef 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.

Not only standard class- and property-level constraints but also
method constraints can be configured using the API. As shown in Example 8.13, “Programmatic definition of method constraints” methods are
identified by their name and their parameters (if there are any). Having
selected a method, constraints can be placed on the method's parameters
and/or return value.

8.5. Boolean composition for constraint composition

As per Bean Validation specification the constraints of a composed
constraint (see Section 3.2, “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 logical AND combination which
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 8.17, “OR composition of constraints” shows how to build a
composing constraint where only one of the constraints has to be
successful in order to pass the validation. Either the validated string is
all lowercased or it is between two and three characters long.

annotating the setter of a JavaBean 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.

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.

9.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).

9.4.1. Command line builds

9.4.1.1. javac

When compiling on the command line using javac,
specify the JAR hibernate-validator-annotation-processor-4.3.2.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. At the time of this writing the plugin is
not yet available in any of the well-known repositories. Therefore you
have to add the project's own repository to your settings.xml or
pom.xml:

Now 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 AP is not visible on the project's
actual classpath):

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

9.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 10. 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 303 specification itself is also a great way to deepen your
understanding of Bean Validation resp. Hibernate Validator.