Be Standard, be Free: Use JSR-303 for Validation
First, let's write a validator (constraint in Bean Validation nomenclature) and then let's use it in our code, to see what we are talking about.
Creating a JSR-303 constraint
A JSR-303 constraint is just a plain Java annotation. For example, if we want to validate ISBNs, we have to create an @ISBN annotation like the next one:
package org.openxava.books.constraints;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
import javax.validation.*;
import org.openxava.books.constraints.impl.*;
@Constraint(validatedBy = ISBNValidator.class) // ISBNValidator contains the validation logic
@Target({ METHOD, FIELD })
@Retention(RUNTIME)
public @interface ISBN {
String message() default "{org.openxava.books.constraints.ISBN.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
The key part here is the @Constraint annotation. It marks this annotation as a constraint and indicates the validator class, ISBNValidator, that is the class with the validation logic:
package org.openxava.books.constraints.impl;
import javax.validation.*;
import org.openxava.books.constraints.*;
public class ISBNValidator implements ConstraintValidator<ISBN, String> {
private static org.apache.commons.validator.ISBNValidator validator =
new org.apache.commons.validator.ISBNValidator(); // Validator from commons validator
public void initialize(ISBN isbn) {
}
public boolean isValid(String value, ConstraintValidatorContext ctx) { // The validation logic
if (value == null || value.trim().equals("")) return true;
return validator.isValid(value); // We simply delegate in commons validator
}
}
The
validator must implement ConstraintValidator, so it needs to have the
initialize() and isValid() methods, the latter contains the validation
logic. In this case we simply delegate in a validator from Apache
Commons Validator project.
As we can see create a validator is pretty simple. Now, how can we use this validation in our application?
Using the validator
The
JSR-303 specification talks about how to define validators, but not
about how they are used and behave in our application, this depends on
the framework we are using. JPA2 and JSF2 have Bean Validation
integration, moreover many modern frameworks have support for JSR-303 as
well. In this case we are going to develop a mini-application using the
OpenXava
framework that use the above @ISBN application. Don't panic, developing
an OpenXava application is short (and sweet), given we only need to
write the domain classes.
After creating a new OpenXava project (executing an ant target) we add the Author and Book classes to it.
Author.groovy:
package org.openxava.books.model
import javax.persistence.*
import org.openxava.model.*
import org.openxava.annotations.*
@Entity
class Author extends Identifiable {
@Required
String name
}
Book.groovy:
package org.openxava.books.model
import org.openxava.model.*;
import org.openxava.annotations.*;
import org.openxava.books.constraints.*;
import javax.persistence.*;
@Entity
class Book extends Identifiable {
@Required @Column(length=60)
String title
@ManyToOne(fetch=FetchType.LAZY)
@DescriptionsList
Author author
@Column(length=10)
@ISBN
String isbn
}
Although we could write the classes with Java, we have chosen Groovy. Yes, Groovy Web Development without Grails is possible. However, the important point here is the @ISBN annotation in isbn property. We do not need more work to see the validation working. If we go to http://localhost:8080/Books/modules/Book, and we try to add a Book with an incorrect ISBN, we'll get something like this:
Why should I use Bean Validation?
Though JSR-303 is easy to use and versatile enough to meet our validation needs, really is not something spectacular, and possibly not much better than our current validation framework, so, why should we use it? Because it is supported by JPA2, JSF2, Spring Roo, Wicket, Tapestry, etc. in addition to be included as part of Java EE 6. Therefore, it gives us more freedom, because our code is less dependent from the application framework we are using, thus it's easier to migrate our code (at least the model part) from Wicket to Tapestry, or from Spring Roo to OpenXava.
Use the Bean Validation standard. Be free!
Resources
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





Comments
Zqudlyba Navis replied on Thu, 2011/03/03 - 3:14am
Javier Paniza replied on Thu, 2011/03/03 - 4:50am
in response to:
Zqudlyba Navis
Hi Zqudlyba,
No, the point of the article is "use the standard for validation", not "use standards for everthing". You're right, there are a lot of non-standard tools like Eclipse, JUnit, Maven, Ant, etc. that are essencial for Java developers. Moreover, the standards have a hard time when they try to produce innovation, look at MDA, CORBA or EJB for example. However, when a standard is already consolidated (like JPA) using it allows you to not depend on a specific vendor, and it is a very important advantage. For example, if you use JPA (the standard) instead of Hibernate, you can move from Hibernate to other persistence provider to improve performance, to access to non-relational database, etc.
Nicolas Frankel replied on Thu, 2011/03/03 - 7:03am
in response to:
Javier Paniza
Hi Javier,
Although I agree to the general content of your article, I must tell you the JPA/Hibernate example couldn't be worse. I have the freedom to tell you so because I made the mistake of bringing JPA 1 as the standard to use in my enterprise.
Big mistake indeed: JPA 1 features are less than 10% that of Hibernate (50% with JPA v2?) and you always have to dig the Hibernate Session delegate from the EntityManager or use Hibernates annotations because there's no JPA equivalent.
Beyond "Hello world!", JPA should be a big no no, although using JPA annotations with Hibernate is a good idea.
My own 2 cents...
Andrew Spencer replied on Fri, 2011/03/04 - 6:35am
Norris Shelton replied on Fri, 2011/03/04 - 7:56am
in response to:
Zqudlyba Navis
Liam Knox replied on Fri, 2011/03/04 - 5:56pm
in response to:
Zqudlyba Navis
Cloves Almeida replied on Sun, 2011/03/06 - 1:10pm
Standards are not a panacea - where they exists, they should be preffered over non-standard solutions. The reason is obvious, just think what the world would be if each city could choose it's electric voltage (50v, 300v, 180v, etc.) instead of using a standard like 220v or 110v.
As for JPA, I might implement only 20% of what Hibernate provides. However, those 20% features solves 90% of the problems. You might need to access org.hibernate.Session every now and then, but that's no excuse to use it when javax.persistence.EntityManager would suffice.