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

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, listing 1 presents the User bean class:

Listing 1: User.java, a bean for user accounts
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 in listing 2 below.

Listing 2: Address.java, a bean for addresses
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.

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

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 Annotations RefCard
Check out the new DZone Spring Annotations Refcard by Craig Walls!

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.