The Bean Validation API allows code reuse of validators through annotations. Validators pass constraint violations to the application so that it can decide error handling. Despite its name, the Bean Validation API does not require the use of JavaBeans or Java EE.
Learn how to use the Bean Validation API 2.0
- What are the features and limitations?
- Add tests to verify behaviour not covered in the original examples from Hibernate Validator's reference guide1
- Find out the minimal dependency set required
- JDK 8
- Apache Maven
Two dependencies required.
-
Hibernate Validator - implementation of the Bean Validation API
pom.xml
<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.13.Final</version> </dependency>
-
Unified EL - implementation of the Unified Expression Language (JSR 341) for evaluating dynamic expressions in constraint violation messages. Not required if the application is running in a Java EE container.
pom.xml
<dependency> <groupId>org.glassfish</groupId> <artifactId>javax.el</artifactId> <version>3.0.1-b09</version> </dependency>
My personal opinion of Hibernate Validator: TLDR; yes I will definitely use it in my next Java project!
- Out of the box, constraints can be declared on the following via Java annotations
- Fields
- Properties i.e. getter methods, following the JavaBean standard
- Values in standard Java containers like
java.util.Iterable
,java.util.Map
andjava.util.Optional
- Also works on nested containers like
Map<@NotNull Part, List<@NotNull Manufacturer>>
- Custom containers require additional work by writing a
ValueExtractor
- Also works on nested containers like
- Validating the entire class, useful for interactions among fields e.g. the seating capacity of a car and number of passengers
- Inheriting contraints from the superclass
- Cascading validation through the object graph (when an object holds a reference to another object)
- Also works for containers
null
is ignored during cascaded validation- The validation engine ensures that no infinite loops occur during cascaded validation, for example if two objects hold references to each other.
- Validators can check the entire object or parts of it e.g. a single field
- List of built-in constraints
- Common business objects like
@Email
,@CreditCardNumber
,@Currency
- Web:
@URL
,@SafeHtml
- Time:
@PastOrPresent
,@Future
- Common business objects like
- Write your own custom validator or compose a new one from existing constraints
- By default, constraint composition is logical
AND
. It is also possible to configure logicalOR
andALL FALSE
- By default, constraint composition is logical
- Group constraints to check in stages
- This mimics business processes/object lifecycles that require different validation logic in each stage
- e.g. driving off a new car at the showroom
- car must have passed vehicle inspection
- driver must have a license
- Set dynamic error messages
- Dynamic payload
- Pass a payload to the constraint, so as to set the control flow of the validation
- e.g. a custom constraint
@CheckCase
can have two different payloads@CheckCase(UPPER)
or@CheckCase(LOWER)
- e.g. a custom constraint
- As part of
ConstraintViolation
- Customise error messages e.g. suggest valid values
- Provide hints to the application on how to handle the error e.g. error severity
- Pass a payload to the constraint, so as to set the control flow of the validation
- For reproducible testing, define what is the time now for time-related validation (such as
@Past
or@Future
constraints) - By default, validation reports all the errors found instead of stopping at the first error. Optionally the validator can be configured to fail fast e.g. expensive validation of large object graphs
- Do not recommend use of method constraints
- Requires an additional library that has a method interception facility, like Spring AOP
- Can only used for instance methods (static methods are not supported)
[1]: Hibernate Validator reference guide and source code