1. Overview
In this quick article, we’ll go over the basics of validating a Java bean with the standard frameworks – JSR 303 and JSR 349.
Validating user input is of course a super common requirement in most applications, and the Java Bean Validation framework has become the de-facto standard of handling this kind of logic.
2. JSR 303 and JSR 349
JSR 303 is a specification of the Java API for bean validation, part of JavaEE and JavaSE, which ensures that the properties of a bean meet specific criteria, using annotations such as @NotNull, @Min, and @Max.
JSR 349 extends JSR 303, with features such as dynamic expression evaluation in constraint violation messages, message interpolation, and more.
For full information on the specifications, go ahead and read through the JSR 303 or JSR 349 JSRs.
3. Dependencies
We’re going to use a Maven example here to show of the exact required dependencies, but of course these jars can be added to a project in any number of ways.
3.1. Validation API
Per the specification JSR 303 and 349, the validation-api dependency contains the standard validation APIs:
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency>
3.2. Validation API Reference Implementation
Hibernate Validator is the reference implementation of the validation API. In order to use it, we must add the following dependencies.
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator-annotation-processor</artifactId> <version>5.2.1.Final</version> </dependency>
A quick note here is that hibernate-validator is entirely separate from the persistence aspects of Hibernate and by adding it as a dependency, we’re not adding these persistence aspects into the project.
3.3. Expression Language Dependencies
JSR 349 provides for variable interpolation, allowing expressions inside the violation messages. In order to parse these expressions, we must add a dependency on both the expression language API and an implementation of that API. GlassFish provides the reference implementation.
<dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>2.2.4</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.4</version> </dependency>
If these JARs are not added, you will get an error message at run time as shown below:
HV000183: Unable to load ‘javax.el.ExpressionFactory’. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
4. Using Validation Annotations
We’ll use a User bean as the main example here and work on adding some simple validation to it:
import javax.validation.constraints.AssertTrue; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; public class User { @NotNull(message = "Name cannot be null") private String name; @AssertTrue private boolean working; @Size(min = 10, max = 200, message = "About Me must be between 10 and 200 characters") private String aboutMe; @Min(value = 18, message = "Age should not be less than 18") @Max(value = 150, message = "Age should not be greater than 150") private int age; // standard setters and getters }
All of the annotations used in the example are standard JSR annotations:
- @NotNull – Validates that the annotated property value is not null
- @AssertTrue – Validates that the annotated property value is true
- @Size – Validates that the annotated property value has a size between the attributes min and max; can be applied to String, Collection, Map, and array properties
- @Min – Validates that the annotated property has a value no smaller than the value attribute
- @Max – Validates that the annotated property has a value no larger than the value attribute
Some annotations accept additional attributes, but the message attribute is common to all of them. This is the message that will be usually rendered when the value of the respective property fails validation.
Finally – beyond the standard annotations, there are a few specific ones that Hibernate Validator adds on top; these aren’t part of the standard spec, but they do sometimes make validation a lot easier.
5. Programmatic Validation
Some frameworks – such as Spring – have simple ways of triggering the validation process by just using annotations. This is mainly so that we don’t have to interact with the programmatic validation API.
Let’s now go the manual route and actually set things up programmatically:
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator();
In order to validate a bean, we must first have a Validator object, which is constructed using a ValidatorFactory.
5.1. Defining the Bean
We’re not going to set up this invalid user – with a null name value:
User user = new User(); user.setWorking(true); user.setAboutMe("Its all about me!"); user.setAge(50);
5.2. Validate the Bean
Now that we have a Validator, we can validate our bean by passing it to the validate method. Any violations of the constraints defined in the User object will be returned as a Set.
Set<ConstraintViolation<User>> violations = validator.validate(user);
By iterating over the violations, we can get all the violation messages by using the getMessage method.
for (ConstraintViolation<User> violation : violations) { log.error(violation.getMessage()); }
In our example (ifNameIsNull_nameValidationFails), the set would contain a single ConstraintViolation, with the message, “Name cannot be null”.
6. Conclusion
This tutorial focused on a simple pass through the standard Java Validation API and illustrated the basics of bean validation using javax.validation annotations and APIs.
An implementation of this the concepts in this article can be found in the GitHub project. We will feature more features of JSR 303, JSR 349, and Hibernate Validator in upcoming articles.