In every enterprise application there is a need for
validation. You may want to validate data send by user to
your REST service, messages coming to your application from some
other system, or your own entities before saving them to database.
defines API for validating Java Beans without tying us to any
Nevertheless some implementations are more polished than others,
and subject of this post -
Hibernate Validator is considered one of the best.
Before we can use Hibernate Validator we must do
To use Hibernate Validator we need following Maven dependencies:
Hibernate Validator uses Java Unified Expression Language (JavaEL)
to format validation messages. When your application runs
inside JEE container, container already provides JavaEL
Since we want to create a command line application we must provide
JavaEL implementation ourselves and that’s the reason
why we included javax.el:el-api and org.glassfish.web:javax.el as
Later on to demonstrate all features of Hibernate Validator we will need
Spring DI container and commons-beanutils library:
Obtaining Validator instance
After all these preparations we are ready to create Validator
Note that we don’t have any reference to Hibernate Validator in
our code, instead we are relying on classes and interfaces defined in
JSR 303 (Bean Validation).
This is very similar to how JDBC providers works.
Returned Validator instance is thread safe and may be assigned to
static field or registered as a singleton in DI container for later use.
Property level constraints
The easiest way to define validation rules for a bean
is to use JSR 303 annotations.
We may put annotations on both fields and getters, for example:
We should prefer putting annotations on getters since this will
allow for greater flexibility when later we will want to
change our beans.
Said that, to conserve space in this post I will
put annotations on fields from now on.
Here is a simple bean representing a person,
annotated with JSR 303 constraints:
Validation rules should be self evident. There is nothing fancy -
we check that a person must have a non empty name and a non empty
surname, and that an age of a person falls within a range of 1 and 200.
Then we may use Hibernate Validator to check if
a Person instance is valid:
In rare cases when Person is invalid, Hibernate Validator
provides us with all necessary information about what
properties and values are wrong:
Bean level constraints
Some validation rules may be expressed only by using
values of two or more properties, for such rules
Hibernate Validator provides class-level constrains.
Returning to our Person example, suppose that we want to add
two new properties to Person: dateOfBirth and dateOfDeath, with
condition that dateOfBirth cannot be later than dateOfDeath
(when both dates are present):
We can express our rule using proprietary (not included in JSR 303)
class-level @ScriptAssert annotation:
familiar to any Java developer. Hibernate Validator supports
any implementation adhering to JSR 223 standard
(scripting for the Java platform).
must always return either true when validation rule is
fullfiled or false.
We must also take care of handling null values otherwise we may
get pesky javax.script.ScriptException.
Inside script we may refer to currently validated bean by name of _this,
or by name of our choosing if we set alias argument like we do in
@ScriptAssert is a duct tape of validation. You should
use it only when performance is not a concern, and you must
provide a solution quickly. In most cases you should prefer
to write you own constraint and validator. Anyway @ScriptAssert is
a great example of class-level constraint.
Validating child beans
To demonstrate parent-child bean validation we will
add Address to Person class.
Address will be optional so not every Person instance will have one,
we only require that if a Person has an address it must be a
Address will be represented by the following bean:
Also we must add address property to Person bean:
@Valid annotation that we put on address field
tells Hibernate Validator that
when validating a Person the Address should also be
validated, but only when address is provided (address is non null).
If we require that a Person must always have an address we may use
@NotNull to enforce that rule:
Now when validating person with an invalid address we get:
To demonstrate how collection validation works
we will add a list of contacts
to Person bean:
Again we used @Valid annotation to tell Hibernate Validator to
validate all non null beans contained in contacts collection.
Now we may check if all Person contacts are valid:
Unfortunately there is no build-in annotation that would protect
us from collections containing nulls:
To fix that problem we must write a custom constraint ourselves.
Customizing validation messages
The easiest way to customize validation message is to
set it explicitly via
This approach is inflexible and you should avoid it, instead
try to load validation messages from application resources.
Hibernate Validator by default will load validation messages from
We may use this file to either add new validation message or
Then we may use are new message:
Extending Hibernate Validator
Earlier we used the following code to validate phone number:
We certainly don’t want to repeat this annotation with regex expression and
message accross all codebase, that would violate
On the other hand the following code validated person name:
Here we see that to validate name we need two constraints, again
repeating two constraints in various DTO’s is not a receipt for
a good code.
To solve above problems JSR 303 introduces constraint composition.
In short you create a new constraint annotation and put
on it all required constraints, you may also adjust
message, payload and/or groups to which constraint belongs.
For example we may create ValidPhoneNumber constraint:
And then use it accross our codebase:
Not only this adheres to DRY princible but our code
is now more readable.
When we put multiple constraints on composed constraint:
And then use it on a field:
Each of composing constrains will be reported independently:
We may add @ReportAsSingleViolation annotation to our
composed constrain to report all violations as a single error.
With @ReportAsSingleViolation we get:
Notice that this time message was taken from composed constraint.
We may use payloads to pass some additional informations
with validation errors. Canonical example of using payloads is
to differentiate between errors and warnings.
First we must define our payload values:
Then we may use them with constraints:
Finally we may use them to decide if given ConstraintViolation
is warning or error:
I am certain that you will find some creative usages of payloads
in you application.
Creating new constraints
To demonstrate how to create a new constraint,
we will create @NotContain validation rule that
checks that String doesn’t contains specified value.
Then we should define our validation message
in resources/ValidationMessages.properties file, and we are done:
Sometimes we want to validate value that is contained in some other
type. For example we may want to validate a String contained
This is possible in Hibernate Validator thanks to value unwrappers.
Hibernate Validator out of the box supports Optional<T> type, so
for a sake of example we will create our own “wrapper” type:
Now we may use our wapper type in DTOs:
If we try to validate UnwrappingDTO instance we will get
To make validation work again we must create are
own type unwrapper:
And register it in Hibernate Validatior framework:
The last thing that we should do, is to annotate Box<T> properties with
And now we can validate Boxed values, yay!
Integrating Hibernate Validator with Spring DI
This section shows how to quickly integrate Hibernate Validator
with Spring. This is not the offical way of how you should integrate
with DI, just a quick and dirty solution that you may find helpful.
You have been warned. Also remember that Spring provides it’s
own validation framework, fully complaint with JSR 303 and called
First we must create validator factory and register it in Spring
and in Hibernate Validator framework:
And in application configuration we should have:
Also do not forget to mark validators as @Component, now we may
use dependency injection inside validators.