del.icio.us Digg DZone Reddit StumbleUpon
Tutorial: Getting Started with Hibernate Validator - Willie Wheeler
« Previous | 1 | 2 | 3 | 4 | 5

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. Listing 3 presents a simple example.

Listing 3. ValidatorMessages.properties resource bundle
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.

Social bookmarks: del.icio.us Digg DZone Reddit StumbleUpon
« Previous | 1 | 2 | 3 | 4 | 5

Comments (22)

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 on Feb 17, 2009 at 1:46 AM PST

Oh, the spec itself would be good too. Here's the latest working version.

By Willie Wheeler on Feb 17, 2009 at 1:48 AM PST

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 Mario Gleichmann on Feb 18, 2009 at 1:06 PM PST

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 Chris on Feb 18, 2009 at 3:14 PM PST

@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 Willie Wheeler on Feb 19, 2009 at 5:53 PM PST

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

I'm interested :)

By JT on Apr 6, 2009 at 3:30 PM PDT

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 Ilker Ozen on May 11, 2009 at 12:24 AM PDT

I keep coming back to this article. Very useful and well-written - thank you!

By Frederic Daoud on Aug 2, 2009 at 4:25 AM PDT

many Thks

By MJA on Aug 5, 2009 at 9:28 AM PDT

Great article, and your Manning book is coming along nicely!

By Gordon Dickens on Sep 9, 2009 at 10:42 AM PDT

Nice article , It helps to the begginers ...... thanks

By Sandeep Natoo on Sep 14, 2009 at 4:32 AM PDT

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 vicina on Oct 4, 2009 at 11:53 PM PDT

@vicina: Yup, Hibernate 4 is the JSR 303 reference implementation now, and Hibernate 3.1 is now legacy.

By Willie Wheeler on Oct 24, 2009 at 3:32 PM PDT

(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 Willie Wheeler on Oct 24, 2009 at 9:55 PM PDT

Hi,

Its a very good article to start with hibernate validator framework..........

By Shivendra on Dec 7, 2009 at 8:43 PM PST

Thanks a lot for your outstanding article.

By Fernando on Jan 20, 2010 at 2:54 PM PST

Excellent article.

By Rajesh Koilpillai on Jan 25, 2010 at 3:00 AM PST

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 xyz on Feb 9, 2010 at 2:58 AM PST

It is really a Nice article and helps to the begginers, many thanks!

By William on May 26, 2010 at 11:02 AM PDT

It would be better if there is a link to print it nicly. Thanks a lot.

By William on May 26, 2010 at 11:03 AM PDT

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 albert kao on Jun 14, 2010 at 8:08 AM PDT

like!

By javadood on Jun 15, 2010 at 1:52 PM PDT

Post a comment

Your name:
Your e-mail address (won't be displayed):
Your web site (optional):
example: www.xyz.com
Your comment:
Preview:
By You
Please help us reduce comment spam:
Spring in Practice
My brother and I are writing Spring in Practice for Manning!

What's New?

2009-08-30 - Check out my two-part series on DZone: Spring Integration: A Hands-On Tutorial.
2009-03-25 - My new article Getting Started with Spring Batch 2.0 is available on DZone.
Home | Consulting | Tech Articles | Mailing List | Contact | Spring Blog
Copyright © 2008 Wheeler Software, LLC.