Chapter 13. Bean Validation
13.1. About Bean Validation
Bean Validation, or JavaBeans Validation, is a model for validating data in Java objects. The model uses built-in and custom annotation constraints to ensure the integrity of application data. The specification is documented here: JSR 349: Bean Validation 1.1.
Hibernate Validator is the JBoss EAP implementation of Bean Validation. It is also the reference implementation of the JSR.
JBoss EAP is 100% compliant with JSR 349 Bean Validation 1.1 specification. Hibernate Validator also provides additional features to the specification.
To get started with Bean Validation, see the bean-validation
quickstart that ships with JBoss EAP. For information about how to download and run the quickstarts, see Using the Quickstart Examples in the JBoss EAP Getting Started Guide.
JBoss EAP 7.1 now includes Hibernate Validator 5.3.x.
New Features of Hibernate Validator 5.3.x
Programmatic API for constraint definition and declaration.
Hibernate Validator introduces a new fluid API, more consistent than what existed in previous releases.
For example, if you want to define a new
ValidPassengerCount
constraint annotation which relies on aValidPassengerCountValidator
validator, you can use the API as follows:ConstraintMapping constraintMapping = configuration.createConstraintMapping(); constraintMapping .constraintDefinition( ValidPassengerCount.class ) .validatedBy( ValidPassengerCountValidator.class );
It can also be used to replace the implementation of the validator used for a given annotation constraint.
For more information on this, see Hibernate Validator 5.3.0.CR1 is out.
Constraint mapping contributors.
With the new
hibernate.validator.constraint_mapping_contributors
property you can now declare several constraint mapping contributors separated by a comma.NoteIn Hibernate Validator 5.3.x, the existing
hibernate.validator.constraint_mapping_contributor
property is still supported, but has been deprecated.Dynamic payloads for constraints.
Hibernate Validator 5.3.x allows you to enrich custom constraint violations with additional context data. Code examining constraint violations can access and interpret this data in a safer way than by parsing string-based constraint violation messages. This is like a dynamic variant of the existing bean validation payload feature.
For more information on this, see Hibernate Validator 5.3.0.Alpha1 is out.
Email validation.
The way email validation is done has been changed. The domain of the email now needs to be a valid domain with each label being at most 63 characters long.
13.2. Validation Constraints
13.2.1. About Validation Constraints
Validation constraints are rules applied to a Java element, such as a field, property or bean. A constraint will usually have a set of attributes used to set its limits. There are predefined constraints, and custom ones can be created. Each constraint is expressed in the form of an annotation.
The built-in validation constraints for Hibernate Validator are listed here: Hibernate Validator Constraints.
13.2.2. Hibernate Validator Constraints
When applicable, the application-level constraints lead to creation of database-level constraints that are described in the Hibernate Metadata Impact column in the table below.
Java-specific Validation Constraints
The following table includes validation constraints defined in the Java specifications, which are included in the javax.validation.constraints
package.
Annotation | Property type | Runtime checking | Hibernate Metadata impact |
---|---|---|---|
@AssertFalse | Boolean | Check that the method evaluates to false. Useful for constraints expressed in code rather than annotations. | None. |
@AssertTrue | Boolean | Check that the method evaluates to true. Useful for constraints expressed in code rather than annotations. | None. |
@Digits(integerDigits=1) | Numeric or string representation of a numeric |
Check whether the property is a number having up to | Define column precision and scale. |
@Future | Date or calendar | Check if the date is in the future. | None. |
@Max(value=) | Numeric or string representation of a numeric | Check if the value is less than or equal to max. | Add a check constraint on the column. |
@Min(value=) | Numeric or string representation of a numeric | Check if the value is more than or equal to Min. | Add a check constraint on the column. |
@NotNull | Check if the value is not null. | Column(s) are not null. | |
@Past | Date or calendar | Check if the date is in the past. | Add a check constraint on the column. |
@Pattern(regexp="regexp", flag=) or @Patterns( {@Pattern(…)} ) | String |
Check if the property matches the regular expression given a match flag. See | None. |
@Size(min=, max=) | Array, collection, map | Check if the element size is between min and max, both values included. | None. |
@Valid | Object | Perform validation recursively on the associated object. If the object is a Collection or an array, the elements are validated recursively. If the object is a Map, the value elements are validated recursively. | None. |
The parameter @Valid
is a part of the Bean Validation specification, even though it is located in the javax.validation.constraints
package.
Hibernate Validator-specific Validation Constraints
The following table includes vendor-specific validation constraints, which are a part of the org.hibernate.validator.constraints
package.
Annotation | Property type | Runtime checking | Hibernate Metadata impact |
---|---|---|---|
@Length(min=, max=) | String | Check if the string length matches the range. | Column length will be set to max. |
@CreditCardNumber | String | Check whether the string is a well formatted credit card number, derivative of the Luhn algorithm. | None. |
@EAN | String | Check whether the string is a properly formatted EAN or UPC-A code. | None. |
| String | Check whether the string is conform to the e-mail address specification. | None. |
@NotEmpty | Check if the string is not null nor empty. Check if the connection is not null nor empty. | Columns are not null for String. | |
@Range(min=, max=) | Numeric or string representation of a numeric | Check if the value is between min and max, both values included. | Add a check constraint on the column. |
13.2.3. Bean Validation Using Custom Constraints
Bean Validation API defines a set of standard constraint annotations, such as @NotNull
, @Size
, and so on. However, in cases where these predefined constraints are not sufficient, you can easily create custom constraints tailored to your specific validation requirements.
Creating a Bean Validation custom constraint requires that you create a constraint annotation and implement a constraint validator. The following abbreviated code examples are taken from the bean-validation-custom-constraint
quickstart that ships with JBoss EAP. See that quickstart for a complete working example.
13.2.3.1. Creating A Constraint Annotation
The following example shows the personAddress
field of entity Person
is validated using a set of custom constraints defined in the class AddressValidator
.
Create the entity
Person
.Example:
Person
Classpackage org.jboss.as.quickstarts.bean_validation_custom_constraint; @Entity @Table(name = "person") public class Person implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue @Column(name = "person_id") private Long personId; @NotNull @Size(min = 4) private String firstName; @NotNull @Size(min = 4) private String lastName; // Custom Constraint @Address for bean validation @NotNull @Address @OneToOne(mappedBy = "person", cascade = CascadeType.ALL) private PersonAddress personAddress; public Person() { } public Person(String firstName, String lastName, PersonAddress address) { this.firstName = firstName; this.lastName = lastName; this.personAddress = address; } /* getters and setters omitted for brevity*/ }
Create the constraint validator files.
Example:
Address
Interfacepackage org.jboss.as.quickstarts.bean_validation_custom_constraint; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; // Linking the AddressValidator class with @Address annotation. @Constraint(validatedBy = { AddressValidator.class }) // This constraint annotation can be used only on fields and method parameters. @Target({ ElementType.FIELD, ElementType.PARAMETER }) @Retention(value = RetentionPolicy.RUNTIME) @Documented public @interface Address { // The message to return when the instance of MyAddress fails the validation. String message() default "Address Fields must not be null/empty and obey character limit constraints"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
Example:
PersonAddress
Classpackage org.jboss.as.quickstarts.bean_validation_custom_constraint; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; @Entity @Table(name = "person_address") public class PersonAddress implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "person_id", unique = true, nullable = false) @GeneratedValue(strategy = GenerationType.SEQUENCE) private Long personId; private String streetAddress; private String locality; private String city; private String state; private String country; private String pinCode; @OneToOne @PrimaryKeyJoinColumn private Person person; public PersonAddress() { } public PersonAddress(String streetAddress, String locality, String city, String state, String country, String pinCode) { this.streetAddress = streetAddress; this.locality = locality; this.city = city; this.state = state; this.country = country; this.pinCode = pinCode; } /* getters and setters omitted for brevity*/ }
13.2.3.2. Implementing A Constraint Validator
Having defined the annotation, you need to create a constraint validator that is able to validate elements with an @Address
annotation. To do so, implement the interface ConstraintValidator
as shown below:
Example: AddressValidator
Class
package org.jboss.as.quickstarts.bean_validation_custom_constraint; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import org.jboss.as.quickstarts.bean_validation_custom_constraint.PersonAddress; public class AddressValidator implements ConstraintValidator<Address, PersonAddress> { public void initialize(Address constraintAnnotation) { } /** * 1. A null address is handled by the @NotNull constraint on the @Address. * 2. The address should have all the data values specified. * 3. Pin code in the address should be of at least 6 characters. * 4. The country in the address should be of at least 4 characters. */ public boolean isValid(PersonAddress value, ConstraintValidatorContext context) { if (value == null) { return true; } if (value.getCity() == null || value.getCountry() == null || value.getLocality() == null || value.getPinCode() == null || value.getState() == null || value.getStreetAddress() == null) { return false; } if (value.getCity().isEmpty() || value.getCountry().isEmpty() || value.getLocality().isEmpty() || value.getPinCode().isEmpty() || value.getState().isEmpty() || value.getStreetAddress().isEmpty()) { return false; } if (value.getPinCode().length() < 6) { return false; } if (value.getCountry().length() < 4) { return false; } return true; } }
13.3. Validation Configuration
You can configure bean validation using XML descriptors in the validation.xml
file located in the /META-INF
directory. If this file exists in the class path, its configuration is applied when the ValidatorFactory
gets created.
Example: Validation Configuration File
The following example shows several configuration options of the validation.xml
file. All the settings are optional. These options can also be configured using the javax.validation
package.
<validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration"> <default-provider> org.hibernate.validator.HibernateValidator </default-provider> <message-interpolator> org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator </message-interpolator> <constraint-validator-factory> org.hibernate.validator.engine.ConstraintValidatorFactoryImpl </constraint-validator-factory> <constraint-mapping> /constraints-example.xml </constraint-mapping> <property name="prop1">value1</property> <property name="prop2">value2</property> </validation-config>
The node default-provider
allows to choose the bean validation provider. This is useful if there is more than one provider on the classpath. The message-interpolator
and constraint-validator-factory
properties are used to customize the used implementations for the interfaces MessageInterpolator
and ConstraintValidatorFactory
, which are defined in the javax.validation
package. The constraint-mapping
element lists additional XML files containing the actual constraint configuration.