9 min read

Using annotations in JavaBeans is an elegant way of defining validation rules in a declarative way. Apart from MyFaces ExtVal there are other projects that introduced declarative validation, such as the Hibernate Validator and the Bean Validation Framework for Spring. Some framework developers realized that it would be a good idea to standardize this type of validation. This led to the Bean Validation specification that was developed as JSR 303 in the Java Community Process. Accordingly, Bean Validation will be a standard part of Java EE 6, but it can be used in Java EE 5 by manually including a Bean Validation implementation.

One of the benefits of having an official standard for validation is that various user interface frameworks can implement support for this type of validation. For example, JavaServer Faces 2.0 will have support for Bean Validation embedded in it, and other UI frameworks will probably follow

But at the moment, we’re still building Java EE 5 and JSF 1.2 applications. And although we can use Bean Validation in Java EE 5, JSF 1.2 doesn’t have Bean Validation support. And that’s where ExtVal comes in. We can use ExtVal to integrate JSR 303 Bean Validation into JSF 1.2 (and even JSF 1.1) projects. This section will discuss some Bean Validation basics and show how to use Bean Validation with ExtVal.

Note that we can only cover some basics of Bean Validation here. As Bean Validation is a new standard, there is not much reference documentation available yet. However, some decent documentation comes bundled with Hibernate Validator—the reference implementation of JSR 303. That documentation is also available online at http://docs.jboss.org/hibernate/stable/validator/reference/. As an alternative, the official specification of JSR 303 can be used as documentation. The official specification can be found at http://jcp.org/en/jsr/summary?id=303.

Setting up Bean Validation and ExtVal

To use Bean Validation, we need a JSR 303 implementation, unless we’re using a Java EE 6 compliant application server. Currently, the only available JSR 303 implementation is the reference implementation, which is Hibernate Validator 4.0. Hibernate Validator can be downloaded from http://www.hibernate.org/subprojects/validator/download.html . We should make sure we download a 4.0 version, as versions before 4.0 do not implement the JSR 303 standard. At the time of writing this article, the latest release is 4.0.2 GA.

After downloading Hibernate Validator, we have to add the Bean Validation libraries to our project. All libraries have to be in the shared lib directory of our EAR. We also have to add the libraries that Hibernate Validator depends on. The following table shows a list of libraries that have to be added to our project in order to be able to use the Hibernate Validator. If we had used Maven, these libraries would have been downloaded and added to our project automatically by Maven.

Library

Description

Where to get

hibernate-validator-4.0.2.GA.jar

The main Hibernate Validator library.

Included in the root directory of the Hibernate Validator distribution.

validation-api-1.0.0.GA.jar

Contains all interfaces and annotations defined by the JSR 303 standard.

Included in the lib directory of the Hibernate Validator distribution.

slf4j-log4j12-1.5.6.jar

slf4j-api-1.5.6.jar

log4j-1.2.14.jar

jpa-api-2.0.Beta-20090815.jar

 

Runtime dependencies of Hibernate Validator.

Included in the lib directory of the Hibernate Validator distribution.

activation-1.1.jar

jaxb-api-2.1.jar

jaxb-impl-2.1.3.jar

stax-api-1.0-2.jar

Runtime dependencies for Hibernate Validator. These libraries are only needed if we run Hibernate Validator on a JDK 5 version. So even if we use a Java EE 5 server that runs on a JDK 6, we don’t need these libs.

Included in the lib/jdk5 directory of the Hibernate Validator distribution.

Once we have added the Bean Validation libraries to our project, we have to make sure that we have also added ExtVal’s Bean Validation module to our project. The Bean Validation module is only available from ExtVal version 1.2.3 onwards. See the Setting up ExtVal section for more details.

Using Bean Validation annotations

The basic usage of Bean Validation is very similar to the use of ExtVal’s Property Validation annotations. There are some differences in the annotations, though. The following table lists all of the annotations that are defined in the Bean Validation specification:

Annotation

Attributes

Description

@AssertFalse

 

Assure that the element that is annotated is false.

@AssertTrue

 

Assure that the element that is annotated is true.

@DecimalMin

value

The value of the annotated element must be a numeric value greater than or equal to the indicated value. The value attribute must be a String that will be interpreted as a BigDecimal string representation.

@DecimalMax

value

The value of the annotated element must be a numeric value less than or equal to the indicated value. The value attribute has the same behavior as the value attribute of the @DecimalMin annotation.

@Digits

integer, fraction

The annotated element must have a numeric value that can’t have more integer digits and fraction digits than indicated by the integer and fraction attributes.

@Past

 

Can be applied to java.util.Date and java.util.Calendar elements. The value of the annotated element must be in the past.

@Future

 

Can be applied to java.util.Date and java.util.Calendar elements. The value of the annotated element must be in the future.

@Min

value

Only for integer values. The value of the annotated element must be greater than or equal to the given value.

@Max

value

Only for integer values. The value of the annotated element must be less than or equal to the given value.

@NotNull

 

The annotated value can’t be null.

@Null

 

The annotated value must be null.

@Pattern

regexp, flags

Can only be applied to Strings. The annotated String must match the regular expression that is given in the regexp attribute. The flags attribute can be set to an array of Pattern.Flag values, indicating which flags should be set to the java.util.regex.Pattern that will be used to match the value against. Valid flags are UNIX_LINES, CASE_INSENSITIVE, COMMENTS, MULTILINE, DOTALL, UNICODE_CASE, and CANON_EQ. See the JavaDoc documentation of java.util.regex.Pattern for an explanation of the flags. (http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html)

@Size

min, max

Can be applied to Strings, Collections, Maps, and arrays. Verifies that the size of the annotated element is between the given min and max values, min and max included.

@Valid

 

For recursive validation.

All annotations are defined in the javax.validation.constraints package. Apart from the attributes mentioned in the previous table, all annotations (except the @Valid annotation) have the following common attributes:

  • message: This attribute can be used to set a custom error message that will be displayed if the constraint defined by the annotation is not met. If we want to set a message bundle key instead of a literal message, we should surround it with braces. So we can set message to either “This value is not valid” or “{inc.monsters.mias.not_valid}”.
  • groups: This attribute can be used to associate a constraint with one or more validation processing groups. Validation processing groups can be used to influence the order in which constraints get validated, or to validate a bean only partially. (See http://docs.jboss.org/hibernate/stable/validator/reference/en/html/validator-usingvalidator.html#validator-usingvalidator-validationgroups for more on validation groups.)
  • payload: This attribute can be used to attach extra meta information to a constraint. The Bean Validation standard does not define any standard metadata that can be used, but specific libraries can define their own metadata. This mechanism can be used with ExtVal to add severity information to constraints, enabling the JSF pages to show certain constraint violations as warnings instead of errors. See the Using payloads to set severity levels section for an example of this.

OK, now we know which annotations can be used. Let’s see how we can use Bean Validation annotations on our Employee class:

// Package declaration and imports omitted for brevity

public class Employee implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;


@Temporal(TemporalType.DATE)
@Column(name="BIRTH_DATE")
@Past
private Date birthDate;

@Column(name="FIRST_NAME")
private String firstName;

@Temporal(TemporalType.DATE)

@Column(name="HIRE_DATE")
@Past
private Date hireDate;

@Column(name="JOB_TITLE")
@NotNull
@Size(min=1)
private String jobTitle;

@Column(name="LAST_NAME")

private String lastName;

@Min(value=100)
private int salary;
@Column(name="KIDS_SCARED")
private int kidsScared;

@OneToMany(mappedBy="employee")

private List<Kid> kids;

// Getters and setters and other code omitted.
}

The Bean Validation annotations are highlighted in the code example. Note that the annotations are applied to the member variables here. Alternatively, we could have applied them to the getter methods. In this example, the birthDate and hireDate are annotated with @Past so that only dates in the past can be set. The jobTitle is set to have a minimum length of one character by the @Size annotation. The salary must have a minimum value of 100, as set by the @Min annotatiion.

Reusing validation

Bean Validation does not have a solution like the @JoinValidation annotation of ExtVal’s Property Validation module. However, Bean Validation offers other ways to avoid repetitive code and help us reusing validation. This section describes some of the possibilities

Inheriting validation

Constraints defined on (the properties of) super classes are inherited. This means that if we have a super class called Person, like the following example, our Employee class can inherit the properties—including the annotated constraints—as follows:

public class Person {
@Size(min=1)
private String firstName;

@Size(min=1)

private String lastName;

@Past
private Date birthDate;

// Getters and setters omitted.
}

No special actions have to be taken to inherit annotated validation constraints.

Using recursive validation

We can use the @Valid annotation to use recursive validation (or graph validation as it is called in the JSR 303 specification). The @Valid annotation can be used on single member objects as well as on Collections. If applied to a Collection, all objects in the collection are validated, but null values in the Collection are ignored. For example, we could use this to validate the List of scared Kids that is part of our Employee class, as follows:

public class Employee implements Serializable {

// Other member variables are left out here.


@OneToMany(mappedBy="employee")
@Valid
private List<Kid> kids;

// Getters and setters are omitted.
}

Now the List of Kids that is referenced by the kidsvariable can only contain valid Kid objects. This means that all Bean Validation constraints that are defined on the Kid class will be checked on all Kid objects in the List.

LEAVE A REPLY

Please enter your comment!
Please enter your name here