In this tutorial we’re going to learn how to get started with Hibernate Validator, which as its name suggests is a validation framework associated with the Hibernate project. This article is really a follow-up to my earlier article on using the Bean Validation Framework (part of the larger Spring Modules project), which is a competing framework that seems to have lost the battle for Spring’s “preferred validation provider” status to Hibernate Validator. Both Uri Boness (in an e-mail correspondence) and Juergen Hoeller (at SpringOne) agreed that people should start moving toward Hibernate Validator since that will eventually support the emerging JSR 303 standard.
Hibernate Validator is nice because it (like the Bean Validation Framework) supports declarative validation via Java 5 annotations. Let’s say you create a bean class, like an Account or a PurchaseOrder or whatever. With Hibernate Validator you can attach validation annotations to the bean properties and that will define the validation constraints for the bean. Moreover, unlike earlier approaches to validation (such as Struts Validation), Hibernate Validator isn’t tied to the web tier, and so if you want to validate your beans from within your service beans, or within your DAOs, or even just before you ORM them into your database, no sweat. You can do just that.
Anyway, for now we’re just going to look at some of the basics: how to specify annotation constraints and how to check for constraint violations. We’re not going to worry about integrating Hibernate Validator with Spring’s native validation framework (so that, for instance, we might render Hibernate Validator error messages out using Spring Web MVC taglibs) though I’ll probably write another article on that sometime in the future if people are interested.
For this article we’re using Java 5 or higher (we need Java 5 annotations) and Hibernate Validator 3.1.0. For your convenience I’ve created a Maven 2 project that you can download: hibernate-validator-demo.zip
OK, let’s jump into some examples of annotated bean classes.
Specifying validation constraints with Hibernate Validator annotations
Here are a couple of examples of annotated bean classes: a User class and an Address class. Note that the two objects are related in a parent-child fashion.
First, here is the User bean class:
package com.wheelersoftware.demos.hibernatevalidator;
import org.hibernate.validator.Email;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.Valid;
public class User {
private String username;
private String firstName;
private String lastName;
private Address address;
private String email;
private String password;
@NotEmpty
@Length(max = 20)
public String getUsername() { return username; }
public void setUsername(String username) {
this.username = username;
}
@NotEmpty
@Length(max = 20)
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@NotEmpty
@Length(max = 20)
public String getLastName() { return lastName; }
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Valid
public Address getAddress() { return address; }
public void setAddress(Address address) {
this.address = address;
}
@NotEmpty
@Email
public String getEmail() { return email; }
public void setEmail(String email) {
this.email = email;
}
@NotEmpty
@Length(max = 20)
public String getPassword() { return password; }
public void setPassword(String password) {
this.password = password;
}
}
Let’s talk a little about what’s going on with the code above. As we noted earlier, we have a bean class (here, a class that represents user accounts of some sort) and we’re using annotations to specify validation constraints. For a full list of the built-in constraints, see the official Hibernate Validator documentation, but we’ll just focus on a small handful for right now.
First notice that we’ve attached our annotations to the getter methods. This is how we specify the validation constraints that attach to the associated properties.
We’ve used @NotEmpty in several places. This annotation means that the annotated property can’t be null and it can’t be the empty string either. There’s also a @NotNull annotation that we could have used if we’d wanted to, but in this case I wanted to prevent the empty string from being used as values.
Another annotation that appears multiple times is the @Length annotation. We can specify associated minimum and maximum lengths by using the min and max elements, respectively, though in the example above we’ve specified only maximum lengths. (In the example that follows we’ll see how to specify a minimum length as well.) So for example we’ve specified that passwords can’t be any longer than 20 characters.
A third annotation is the @Email annotation. As you would guess, this indicates that the property must contain a valid e-mail address.
The fourth and final annotation of the ones that appear above is the @Valid annotation. This tells Hibernate Validator that it should validate the associated object—here an associated Address object—using whatever validation annotations we define on the Address class.
And that’s our segue into our second example, the Address bean class, which appears below.
package com.wheelersoftware.demos.hibernatevalidator;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.Pattern;
public class Address {
private String street1;
private String street2;
private String city;
private String state;
private String zip;
@NotEmpty
@Length(max = 40)
public String getStreet1() { return street1; }
public void setStreet1(String street1) {
this.street1 = street1;
}
// No validation constraints
public String getStreet2() { return street2; }
public void setStreet2(String street2) {
this.street2 = street2;
}
@NotEmpty
@Length(max = 40)
public String getCity() { return city; }
public void setCity(String city) {
this.city = city;
}
@NotEmpty
@Length(max = 3)
public String getState() { return state; }
public void setState(String state) {
this.state = state;
}
@NotEmpty
@Length(min = 5, max = 5, message = "{zip.length}")
@Pattern(regex = "[0-9]+")
public String getZip() { return zip; }
public void setZip(String zip) {
this.zip = zip;
}
}
Our validation annotations for Address are pretty similar to what we saw for User, but there are a few differences worth mentioning. First, notice that we don’t have to attach validation constraints to every property. It’s OK, for example, for street2 to be null or anything else, so we simply refrain from defining validation constraints for this property.
Second, we’re using a @Pattern annotation for the zip property. This allows us to specify regular expression match patterns.
The third and final difference is the @Length annotation we’ve defined for the zip property. Besides including a min element (which, when combined with the max element, indicates that the ZIP code must be exactly five characters long), we’ve also included a message element. We can use this element to do either of two things. First, we can use it to define a hardcoded message to display when the given validation constraint fails. That’s not what we’re doing here. Instead we’re doing the second thing we can do, which is specify a message key using the brace syntax: message = {key_name}. The idea is that we’ll eventually use this message key to look up a message in a resource bundle, thus externalizing the message. Later in the tutorial we’ll map the zip.length message key to an actual message using a resource bundle.
That’s it for the validation constraints themselves. Now let’s see how we can tell Hibernate Validator to use them to perform our bean validation.
How to tell Hibernate Validator to validate annotated beans
It’s fairly straightforward to get Hibernate Validator to validate our annotated beans. The following listing presents some demo code for doing exactly this. Let’s take a look.
package com.wheelersoftware.demos.hibernatevalidator;
import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
public final class Demo {
private static ClassValidator<User>
userValidator = new ClassValidator<User>(User.class);
public static void main(String[] args) {
validateUser(createUser());
}
private static User createUser() {
User user = new User();
user.setFirstName("123456789012345678901");
user.setEmail("aol.com");
Address addr = new Address();
addr.setStreet1("");
addr.setCity("Moreno Valley");
addr.setState("CA");
addr.setZip("QWERTY");
user.setAddress(addr);
return user;
}
private static void validateUser(User user) {
InvalidValue[] invalidValues = userValidator.getInvalidValues(user);
for (InvalidValue value : invalidValues) {
System.out.println("========");
System.out.println(value);
System.out.println("message=" + value.getMessage());
System.out.println("propertyName=" + value.getPropertyName());
System.out.println("propertyPath=" + value.getPropertyPath());
System.out.println("value=" + value.getValue());
}
}
}
There are really only a few interesting things happening here. First, we create a ClassValidator<User> instance for validating our User beans. We have to associate the ClassValidator with a type (here, User) because this is where Hibernate Validator goes in and reads all the annotations off of the bean class in question.
Next, we have to create the bean we want to validate. Usually this would come from a user form (for example, a web-based form, or maybe a Swing-based form) though that’s not necessarily the case. Here we just create a bean manually, and we intentionally make a lot of the fields invalid so we can see how Hibernate Validator responds.
Finally we make the call userValidator.getInvalidValues(user). This generates an array of InvalidValue instances—one for each validation constraint violation. Let’s examine the InvalidValue class in more detail.
Understanding InvalidValue
To understand InvalidValue it will help to run the demo. So do that right now. You should see output that looks something like this:
26 [main] INFO org.hibernate.validator.Version - Hibernate Validator 3.1.0.GA
45 [main] INFO org.hibernate.annotations.common.Version - Hibernate Commons Annotations 3.1.0.GA
========
username may not be null or empty
message=may not be null or empty
propertyName=username
propertyPath=username
value=null
========
firstName length must be between 0 and 20
message=length must be between 0 and 20
propertyName=firstName
propertyPath=firstName
value=123456789012345678901
========
lastName may not be null or empty
message=may not be null or empty
propertyName=lastName
propertyPath=lastName
value=null
========
email not a well-formed email address
message=not a well-formed email address
propertyName=email
propertyPath=email
value=aol.com
========
password may not be null or empty
message=may not be null or empty
propertyName=password
propertyPath=password
value=null
========
street1 may not be null or empty
message=may not be null or empty
propertyName=street1
propertyPath=address.street1
value=
========
zip {zip.length}
message={zip.length}
propertyName=zip
propertyPath=address.zip
value=QWERTY
========
zip must match "[0-9]+"
message=must match "[0-9]+"
propertyName=zip
propertyPath=address.zip
value=QWERTY
If you look at the source code for Demo.validateUser() you’ll see that we’re printing out each InvalidValue instance itself (the first line) as well as the values of the message, propertyName, propertyPath and value properties (the rest of the lines). When we print out the instance itself, we get Hibernate Validator’s attempt at a user-friendly validation eror message. It starts with the property name and then appends the message; examples include
email not a well-formed e-mail addresspassword may not be null or emptyzip must match "[0-9]+"
Each message value (such as may not be null or empty) is a default associated with a validation annotation (such as @NotEmpty). Note that in the case of the length violation for the zip property, we’re seeing not the default length message, but instead the new message key name (namely, zip.length) we specified in listing 2. We’ll see how to map zip.length to an actual message using a resource bundle in a little bit. For now we’re seeing just the key name because we haven’t yet associated a message with the key.
The propertyName property specifies the name of the bean property whose value is invalid. For example, if we provide a bad ZIP code, then propertyName is zip.
The propertyPath property is similar to propertyName property, except that with propertyPath we get to see the path from the top-level bean down to the invalid property. You can see the difference, for instance, with the invalid ZIP code: propertyName is zip but propertyValue is address.zip.
Finally, value is just the bad value that violated the validation constraint in the first place.
While we can use InvalidValue itself as a source of semi-user-friendly messages, it’s clear that the defaults leave something to be desired. After all, zip must match "[0-9]+" wouldn’t be what most users would consider user-friendly. We can however provide a resource bundle to improve the error messages and that’s what we’ll look at now.
Improving validation error messages using ValidatorMessages.properties
With Hibernate Validator we can override the default messages associated with the various validation annotations. We can also provide highly specific error messages associated with property/constraint pairs. We do this using resource bundles. Though it’s possible to provide Hibernate Validator with arbitrary resource bundles, the easiest approach is to create a ValidatorMessages.properties resource bundle on the classpath and use that. Hibernate Validator knows to look for that particular bundle (including any associated localizations) and use it as a message source. The next listing presents a simple example.
validator.notEmpty=may not be null or empty!
validator.length=must be {max} or fewer characters.
zip.length=Please enter a {max}-character ZIP code.
The first two lines of listing 3 provide alternatives for the validator.notEmpty and validator.length message keys. The key names are defined by the validation annotations themselves, so consult the Javadocs for the annotations if you need the key names (though you should be able to figure them out using the examples above).
Notice the {max} that appears in the message for the validator.length key. You can reference annotation elements from messages using the brace syntax. Consult the Javadocs for the various annotations—or else the Hibernate Validator reference manual—for a complete list of annotations and annotation elements.
The third line also specifies a message, but this time we’re associating a message with the zip.length custom key we defined in listing 2. Note that here we don’t use the braces for the key name. And also note that we can still reference annotation elements using the brace syntax. The custom message key approach is useful when you want to be very specific about the error message you provide to the end user.
Here’s what it looks like when you run it:
29 [main] INFO org.hibernate.validator.Version - Hibernate Validator 3.1.0.GA 59 [main] INFO org.hibernate.annotations.common.Version - Hibernate Commons Annotations 3.1.0.GA ======== username may not be null or empty! message=may not be null or empty! propertyName=username propertyPath=username value=null ======== firstName must be 20 or fewer characters. message=must be 20 or fewer characters. propertyName=firstName propertyPath=firstName value=123456789012345678901 ======== lastName may not be null or empty! message=may not be null or empty! propertyName=lastName propertyPath=lastName value=null ======== email not a well-formed email address message=not a well-formed email address propertyName=email propertyPath=email value=aol.com ======== password may not be null or empty! message=may not be null or empty! propertyName=password propertyPath=password value=null ======== street1 may not be null or empty! message=may not be null or empty! propertyName=street1 propertyPath=address.street1 value= ======== zip Please enter a 5-character ZIP code. message=Please enter a 5-character ZIP code. propertyName=zip propertyPath=address.zip value=QWERTY ======== zip must match "[0-9]+" message=must match "[0-9]+" propertyName=zip propertyPath=address.zip value=QWERTY
Discussion
That wraps it up for this tutorial. It’s a good idea to get familiar with Hibernate Validator for a number of reasons:
- Annotation-based declarative annotations are an intuitive and convenient way to specify validation constraints.
- Hibernate Validator isn’t tied to any particular application tier.
- It will support the JSR 303 standard once that finalizes.
We haven’t explored everything that Hibernate Validator has to offer. For instance, it’s possible to configure it such that Hibernate ORM automatically runs Hibernate Validator when performing persistence operations.
One slight annoyance that I’ve found is that there doesn’t seem to be built-in way to substitute the bad value into the message itself. Sometimes I like to have messages like
willie2gmail.com is not a valid e-mail address
I suppose that I could create messages like
{1} is not a valid e-mail address
and then perform the substitution when processing the InvalidValue array, but it would be nice to be able to do this out of the box. Maybe there’s a way to do it after all, but if so, I haven’t found it.
Also, the documentation for Hibernate Validator is a little thin, both with respect to the reference manual and the Javadocs. Hopefully as JSR 303 matures we’ll see improvements in this area. In the meantime, this tutorial will be my contribution to helping people understand Hibernate Validator.

By Willie Wheeler February 17, 2009 - 2:46 am
Also, Hibernate Validator 4.0.0 Alpha just came out, and I believe it's a reference implementation for JSR 303. Here are some relevant links:
By Willie Wheeler February 17, 2009 - 2:48 am
Oh, the spec itself would be good too. Here's the
latest working version.
By Mario Gleichmann February 18, 2009 - 2:06 pm
Thanks for that interesting introduction!
Personally, i'm kind of unhappy with JSR 303, since it doesn't provide the full power 'Design By Contract' (in form of preconditions for the case of formulating 'input' constraints, not talking about invariants and postcondtions) could give you.
I wonder why to be restricted to a limited set of constraints instead of being able to express custom conditions using an adequate constraint (or predicate) language.
In addition to that, i wonder why you explicitly have to apply a 'Helper' in order to get into action and trigger validation, which is pretty decoupled from the causer of the constraint violation (instead of obeying the stated contract 'permanently', whenever you try to call an annotated method, clearly pointing to the causer of the constraint violation).
For an example of DBC you might want to take a look at
http://gleichmann.wordpress.com/2007/11/21/springcontracts-design-by-contract-with-seamless-integration-into-spring-is-now-open-source/
for a first starting point (while there are of course some other solutions for DBC).
Greetings
Mario
By Chris February 18, 2009 - 4:14 pm
I'm interested in how to "render Hibernate Validator error messages out using Spring Web MVC taglibs". Is there a better way than simply converting the Hibernate InvalidValue object to a BindingResult object?
By Willie Wheeler February 19, 2009 - 6:53 pm
@Mario: Thanks for the thoughts and link. I will check your blog post out.
@Chris: The approach I've taken so far is exactly the one you just described. Whether there's a better approach or not I don't know, but at some level it would seem that the conversion has to take place, even if Spring 3 ends up handling the conversion at the framework level (which is what I would expect).
By JT April 6, 2009 - 4:30 pm
I'm interested :)
By Ilker Ozen May 11, 2009 - 1:24 am
Thanks for the tutorial. That's really very explanatory.
I will have a question about the ClassValidator declaration. Let's assume User class extends the abstract class Person and getting annotations through Person class is needed.
ClassValidator
personValidator = new ClassValidator
(Person.class);
InvalidValue[] invalid Values = itemValidator.get Invalid Values(person);
I couldn't get it working. No invalid values are found. Is there a way to get invalid values in a child class of an abstract class through annotations?
The Person class might seem weird but I am just trying to illustrate the situation in my project. There exists an abstract class and there are many classes extending it. And there are custom validator annotations are declared in those classes and i want to validate these classes through one ClassValidator
declaration but i couldn't succeed.
Any help would be appreciated!
By Frederic Daoud August 2, 2009 - 5:25 am
I keep coming back to this article. Very useful and well-written – thank you!
By MJA August 5, 2009 - 10:28 am
many Thks
By Gordon Dickens September 9, 2009 - 11:42 am
Great article, and your Manning book is coming along nicely!
By Sandeep Natoo September 14, 2009 - 5:32 am
Nice article , It helps to the begginers …… thanks
By vicina October 5, 2009 - 12:53 am
The Hibernate 4.0, a reference implementation of the Bean validator, seems to be a different animal. The APIs are not the same, nor the usage.
By Willie Wheeler October 24, 2009 - 4:32 pm
@vicina: Yup, Hibernate 4 is the JSR 303 reference implementation now, and Hibernate 3.1 is now legacy.
By Willie Wheeler October 24, 2009 - 10:55 pm
(Oops, in the message above I meant "Hibernate Validator 4" and "Hibernate Validator 3.1.")
Regarding integrating Hibernate Validator with Spring, Spring 3 now supports this directly. See the
Spring 3 reference docs.
By Shivendra December 7, 2009 - 9:43 pm
Hi,
Its a very good article to start with hibernate validator framework……….
By Fernando January 20, 2010 - 3:54 pm
Thanks a lot for your outstanding article.
By Rajesh Koilpillai January 25, 2010 - 4:00 am
Excellent article.
By xyz February 9, 2010 - 3:58 am
hi,
its working fine but if i configure it with class that extends "ListResourceBundle"
then i am not getting desired output..
is there any thing else i need to specify ?
By William May 26, 2010 - 12:02 pm
It is really a Nice article and helps to the begginers, many thanks!
By William May 26, 2010 - 12:03 pm
It would be better if there is a link to print it nicly. Thanks a lot.
By albert kao June 14, 2010 - 9:08 am
I still use Spring 2.5.6 (don't plan to upgrade to Spring 3.0 yet).
Which Hibernate Validator should I use (3.1.0)?
I'm interested in how to "render Hibernate Validator error messages out using Spring Web MVC taglibs" (same question as Mario). Is there a better way than simply converting the Hibernate InvalidValue object to a BindingResult object?
Any tutorial or sample code available?
By javadood June 15, 2010 - 2:52 pm
like!
By Jamie Bolat May 12, 2012 - 3:58 pm
Hi,
I have also bought the early access book for Spring in Practice and in chapter 4, which uses @ScriptAssert for duplication validation (such as passwords). My problem is, if we want check that the passwords match, we do something like:
@ScriptAssert(
lang = “javascript”,
script = “_this.confirmPassword.equals(_this.password)”,
message = “account.password.mismatch.message”)
I know that in my jsp file, I can receive this error message globally together with all the other errors as follows:
However, I want to receive this specific password duplication error message and have it displayed by the password field, however, I do not know by what path name I can retrieve this error? For example, to receive the Username error by the Username field, the jsp looks like:
…but by what name do we retrieve the password error that is checked by @ScriptAssert, especially when there are multiple @ScriptAssert within @ScriptAssert.List?
…which uses username as the path name. I have checked other forums, etc. to find the path name for @ScriptAssert or the path name for each @ScriptAssert within @ScriptAssert.List, but could not find any solutions. Any help will be appreciated.
Kind regards,
Jamie
By Willie Wheeler May 12, 2012 - 6:56 pm
Hey Jamie. Take a look at the various
rejectValue()methods on theorg.springframework.validation.Errorsinterface. They allow you to associate an error condition with a specific field.By Jamie Bolat May 13, 2012 - 2:35 am
Hi Willie,
Thanks for your reply.
Regards,
Jamie
By Jamie Bolat June 24, 2012 - 10:06 am
Hi Willie,
Can I ask you one more question regarding Hibernate Validation: In my web flow I have incorporated the Hibernate validation using the model attribute in the flow.xml file and this works all fine. However, in the view-stage tag, if I prefix the model attribute variable with flowScope (e.g. model=”flowScope.customer”) in the flow.xml file, the validation errors do not get displayed. What is the workaround this problem as I need a new instance of the model on each entry?
Many thanks.
Jamie
By How to Invoke JSR 303 Bean Validation Programmatically | Beyond Java November 10, 2012 - 10:05 am
[...] now that you know how to adapt the examples, I’d like to recommend you the tutorial on Hibernate Validator I mentioned [...]