Chapter 2. Validation Step by Step: Prev Next
Chapter 2. Validation Step by Step: Prev Next
Prev Next
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.
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
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 1/19
2/20/13 Chapter 2. Validation step by step
Constraints can be expressed by annotating a field of a class. Example 2.1, “Field level constraint”
shows a field level configuration example:
package com.mycompany;
import javax.validation.constraints.NotNull;
public class C ar {
@NotNull
private String manufacturer;
@AssertTrue
private boolean isRegistered;
When using field level constraints field access strategy is used to access the value to be validated.
This means the instance variable directly independed of the access type.
Note
The access type (private, protected or public) does not matter.
Note
Static fields and properties cannot be validated.
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 2/19
2/20/13 Chapter 2. Validation step by step
If your model class adheres to the JavaBeans standard, it is also possible to annotate the properties
of a bean class instead of its fields. Example 2.2, “Property level constraint” uses the same entity as
in Example 2.1, “Field level constraint”, however, property level constraints are used.
Note
The property's getter method has to be annotated, not its setter.
package com.mycompany;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;
public class C ar {
@NotNull
public String getManufacturer() {
return manufacturer;
}
@AssertTrue
public boolean isRegistered() {
return isRegistered;
}
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 3/19
2/20/13 Chapter 2. Validation step by step
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.
Tip
It is recommended to stick either to field or property annotation 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.
Last but not least, a constraint can also be placed on class level. When a constraint annotation is
placed on this le vel the class instance itself passed to the C onstraintValidator. 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 C ar. We also add the constraint
PassengerC ount on the class level. We will later see how we can actually create this custom constraint
(see Chapter 3, Creating custom constraints). For now we it is enough to know that PassengerC ount will
ensure that there cannot be more passengers in a car than there are seats.
package com.mycompany;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@PassengerCount
public class C ar {
@NotNull
private String manufacturer;
@NotNull
@Size(min = 2, max = 14)
private String licensePlate;
@Min(2)
private int seatC ount;
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 4/19
2/20/13 Chapter 2. Validation step by step
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:
package com.mycompany;
import javax.validation.constraints.NotNull;
@NotNull
public String getRentalStation() {
return rentalStation;
}
Our well-known class C ar from ??? is now extended by RentalC ar with the additional property
rentalStation. If an instance of RentalC ar 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 C ar were an interface implemented by RentalC ar.
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 5/19
2/20/13 Chapter 2. Validation step by step
Constraint annotations are aggregated if methods are overridden. If RentalC ar would override the
getManufacturer() method from C ar any constraints annotated at the overriding method would be
evaluated in addition to the @NotNull constraint from the super-class.
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”.
package com.mycompany;
import javax.validation.constraints.NotNull;
@NotNull
private String name;
package com.mycompany;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
public class C ar {
@NotNull
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 6/19
2/20/13 Chapter 2. Validation step by step
@Valid
private Person driver;
If an instance of C ar is validated, the referenced Person object will be validated as well, as the driver
field is annotated with @Valid. Therefore the validation of a C ar 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 C ollection, 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.
package com.mycompany;
import java.util.ArrayList;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
public class C ar {
@NotNull
@Valid
private List<Person> passengers = new ArrayList<Person>();
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 7/19
2/20/13 Chapter 2. Validation step by step
Note
null values are getting ignored when validating object graphs.
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.
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<C onstraintViolation>. The set is empty, if the validation succeeds.
Otherwise a C onstraintViolation 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.Default) will be used. We will go into more detail on the topic
of validation groups in Section 2.3, “Validating groups”
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 8/19
2/20/13 Chapter 2. Validation step by step
2.2.2.1. validate
Use the validate() method to perform validation of all constraints of a given entity instance (see
Example 2.9, “Usage of Validator.validate()” ).
assertEquals(1, constraintViolations.size());
assertEquals("may not be null", constraintViolations.iterator().next().getMessage());
2.2.2.2. validateProperty
With help of the validateProperty() a single named property of a given object can be validated. The
property name is the JavaBeans property name.
assertEquals(1, constraintViolations.size());
assertEquals("may not be null", constraintViolations.iterator().next().getMessage());
Validator.validateProperty is for example used in the integration of Bean Validation into JSF 2 (see
Section 6.3, “Presentation layer validation”).
2.2.2.3. validateValue
Using the validateValue() method you can check, whether a single property of a given class can be
validated successfully, if the property had the specified value:
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 9/19
2/20/13 Chapter 2. Validation step by step
assertEquals(1, constraintViolations.size());
assertEquals("may not be null", constraintViolations.iterator().next().getMessage());
Note
@Valid is not honored by validateProperty() or validateValue().
Now it is time to have a closer look at what a C onstraintViolation. Using the different methods of
C onstraintViolation 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:
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 10/19
2/20/13 Chapter 2. Validation step by step
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:
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.
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.Default is
assumed.
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 11/19
2/20/13 Chapter 2. Validation step by step
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 DriverC hecks. As you can see in Example 2.14, “Group interfaces” the group DriverC hecks 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.
Note
The Bean Validation specification does not enforce that groups have to be interfaces.
Non interface classes could be used as well, but we recommend to stick to interfaces.
@AssertTrue(message = "You first have to pass the driving test", groups = DriverChecks.class)
public boolean hasDrivingLicense;
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 12/19
2/20/13 Chapter 2. Validation step by step
Last but not least we add the property passedVehicleInspection to the C ar class (Example 2.15,
“Car”) indicating whether a car passed the road worthy tests.
public class C ar {
@NotNull
private String manufacturer;
@NotNull
@Size(min = 2, max = 14)
private String licensePlate;
@Min(2)
private int seatC ount;
@AssertTrue(message = "The car has to pass the vehicle inspection first", groups = CarChecks.class
private boolean passedVehicleInspection;
@Valid
private Driver driver;
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 13/19
2/20/13 Chapter 2. Validation step by step
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 DriverC hecks and last but not least Car.passedVehicleInspection
belongs to the group C arC hecks. Example 2.16, “Drive away” shows how passing different group
combinations to the Validator.validate method result in different validation results.
@BeforeC lass
public static void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
public void driveAway() {
// create a car and check that everything is ok with it.
C ar car = new C ar( "Morris", "DD-AB-123", 2 );
Set<C onstraintViolation<C ar>> constraintViolations = validator.validate( car );
assertEquals( 0, constraintViolations.size() );
// now let's add a driver. He is 18, but has not passed the driving test yet
Driver john = new Driver( "John Doe" );
john.setAge( 18 );
car.setDriver( john );
constraintViolations = validator.validate( car, DriverC hecks.class );
assertEquals( 1, constraintViolations.size() );
assertEquals( "You first have to pass the driving test", constraintViolations.iterator().next().getMessage() );
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 C arC hecks 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 DriverC hecks 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 DriverC hecks will pass.
Last but not least, we show that all constraints are passing by validating against all defined groups.
By default, constraints are evaluated in no particular order and this regardless of which groups they
belong to. In some situations, however, it is useful to control the order of the constraints evaluation.
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 constraints fails in a sequenced group none of the constraints of the
follwoing 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.
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 15/19
2/20/13 Chapter 2. Validation step by step
The usage of the new sequence could then look like in Example 2.18, “Usage of a group sequence”.
@Test
public void testOrderedC hecks() {
C ar car = new C ar( "Morris", "DD-AB-123", 2 );
car.setPassedVehicleInspection( true );
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 class, place a @GroupSequence
annotation on the class. The defined groups in the annotation express the sequence of groups that
substitute Default for this class. Example 2.19, “RentalCar” introduces a new class RentalCar with a
redfined default group. With this definition the check for all three groups can be rewritten as seen in
Example 2.20, “testOrderedChecksWithRedefinedDefault”.
@Test
public void testOrderedC hecksWithRedefinedDefault() {
RentalC ar rentalC ar = new RentalC ar( "Morris", "DD-AB-123", 2 );
rentalC ar.setPassedVehicleInspection( true );
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 16/19
2/20/13 Chapter 2. Validation step by step
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 should be added!
field/property.
Supported types
are BigDecimal, Check whether the property is Define
@Digits(integer=, BigInteger, String, a number having up to integer column
yes
fraction=) byte , short, int, long digits and fraction fractional precision
and the respective digits. and scale.
wrappers of the
primitive types.
field/property.
Check whether the specified
@Email no Needs to be a none
string is a valid email address.
string.
field/property.
Supported types Checks whether the
@Future yes are java.util.Date annotated date is in the none
and future.
java.util.C alendar.
field/property. Validate that the annotated
@Length(min=,
no Needs to be a string is between min and max none
max=)
string. included.
field/property.
Supported types
Add a
are BigDecimal, Checks whether the
check
BigInteger, String, annotated value is less than
@Max yes constraint
byte , short, int, long or equal to the specified
on the
and the respective maximum.
column.
wrappers of the
primitive types.
field/property.
Supported types
Add a
are BigDecimal,
Check whether the annotated check
BigInteger, String,
@Min yes value is higher than or equal constraint
byte , short, int, long
to the specified minimum. on the
and the respective
column.
wrappers of the
primitive types.
Column(s)
Check that the annotated
@NotNull yes field/property are not
value is not null.
null.
field/property.
Check if the string is not null
@NotEmpty no Needs to be a none
nor empty.
string.
Check that the annotated
@Null yes field/property none
value is null.
field/property.
Supported types
Checks whether the
@Past yes are java.util.Date none
annotated date is in the past.
and
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 18/19
2/20/13 Chapter 2. Validation step by step
java.util.C alendar.
field/property. Check if the annotated string
@Pattern(regex=,
yes Needs to be a match the regular expression none
flag=)
string. regex .
field/property.
Supported types
are BigDecimal, Check whether the annotated
@Range(min=, BigInteger, String, value lies between (inclusive)
no none
max=) byte , short, int, long the specified minimum and
and the respective maximum.
wrappers of the
primitive types.
field/property.
Supported types Column
Check if the annotated
@Size(min=, are String, length will
yes element size is between min
max=) C ollection, Map and be set to
and max (inclusive).
arrays. max.
Note
On top of the parameters indicated in Table 2.2, “Built-in constraints” each constraint
supports the parameters message , groups and payload. This is a requirement of the Bean
Validation specification.
In some cases these built-in constraints will not fulfill your requirements. In this case you can literally
in a minute write your own constraints. We will discuss this in Chapter 3, Creating custom constraints
docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-annotate 19/19