DMIT221 Bean Validation with Hibernate Validator Learning Objectives • Upon completion of this lesson, you will be able to: – Use bean validation annotations – Test bean validation annotations Validating Data • Common data validation tasks: – Required field validation – Compare validation – Range validation (numeric range, date range, string length range) – Regular Expression validation (email address, phone number, postal code) Custom Validation • With a layered application, validating data is a common task that is often duplicated in each layer, proving time consuming and error-prone DRY Principle • Don’t Repeat Yourself(DRY) • “Every piece of knowledge must have a single, unambiguous, authoritative representation within a system” Domain Model Validation • To avoid duplication of validation code, the validation logic can be bundle directly into the domain model Bean Validation Specification (JSR 303) • Bean Validation Specification defines a metadata model and API for entity validation • Bean Validation Specification API is not tied to a specific application tier or programming model, and is available for both server-side and client-side application programming • Hibernate Validator is the reference implementation for the Bean Validation Specification • Apache Bean Validation is another implementation of the Bean Validation Specification Defining Constraints (1) • Constraints are expressed via Java annotations • Three different type of constraint annotations 1. Field-level constraints 2. Property-level constraints 3. Class-level constraints • The type of constraint annotation is determined by the location of the annotation • Field-level and property-level constraints do the same thing so use either field or property annotation within one class but not both Defining Constraints (2) • Class-level constraints are used when there is a need to: 1. Inspect more than a single property of the class to validate it 2. Evaluate the correlation between different state variables Example: field-level constraints import javax.validation.constraints.*; public class Car { @NotNull private String manufacturer; @AssertTrue private boolean isRegistered; public Car(String manufacturer, boolean isRegistered) { this.manufacturer = manufacturer; this.isRegistered = isRegistered; } // getters and setters … } Example: property-level constraints import javax.validation.constraints.*; public class Car { private String manufacturer; private boolean isRegistered; public Car(String manufacturer, boolean isRegistered) { this.manufacturer = manufacturer; this.isRegistered = isRegistered; } @NotNull public String getManufacturer() { return manufacturer; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } @AssertTrue public boolean isRegistered() { return isRegistered; } public void setRegistered(boolean isRegistered) { this.isRegistered = isRegistered; } } Example: class-level constraints import javax.validation.constraints.*; @PassengerCount public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) private String licensePlate; @Min(2) private int seatCount; private List<Person> passengers; public Car(String manufacturer, String licencePlate, int seatCount) { this.manufacturer = manufacturer; this.licensePlate = licencePlate; this.seatCount = seatCount; } //getters and setters ... } Validating Constraints 1. Obtain a Validator instance javax.validation.ValidatorFactory factory = javax.validation.V alidation.buildDefaultValidatorFactory(); javax.validation.Validator validator = factory.getValidator(); 2. Use one of the three validator methods to validate either entire entities or just a single property of the entity 1. validate() method – use to perform validation of all constraints of a given entity instance 2. validateProperty() method – use to perform validation on a single named property of a given object 3. validateValue() method – use to check whether a single property of a given class can be validated successfully, if the property had the specified value Example: Validator.validate() method ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); Car car = new Car(null); Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car); assertEquals(1, constraintViolations.size()); assertEquals("may not be null", constraintViolations.iterator().next().getMessage()); Example: Validator.validateProperty() method Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Car car = new Car(null); Set<ConstraintViolation<Car>> constraintViolations = validator.validateProperty(car, "manufacturer"); assertEquals(1, constraintViolations.size()); assertEquals("may not be null", constraintViolations.iterator().next().getMessage()); Example: Validator.validateValue() method Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Set<ConstraintViolation<Car>> constraintViolations = validator.validateValue(Car.class, "manufacturer", null); assertEquals(1, constraintViolations.size()); assertEquals("may not be null", constraintViolations.iterator().next().getMessage()); Adding Capabilities To Use Third-Party Libraries • To use a third-party library you can either – Add the library files to the CLASSPATH environment variable of the operating system – For an Eclipse you can add the library files to the Java Build Path project property – For web applications you can copy the library files to "WEB-INF/lib" directory of the web application • The CLASSPATH environment variable tells SDK tools and applications where to find third-party and user-defined classes • The Java Build Path property of a project tells Eclipse where to find third-party and user-defined classes Download and Install Hibernate Validator 4.2.0.Final 1. 2. • • Download Hibernate Validator 4.2.0.Final From a Terminal session type: su unzip /home/dmit/Downloads/hibernate-validator4.2.0.Final-dist.zip –d /opt/dmit221sdk Adding Hibernate Validator Capabilities • Add the following library files from the " /opt/dmit221sdk/hibernate-validator-4.2.0.Final" directory to the Java Build Path property of your Eclipse project: – hibernate-validator-4.2.0.Final.jar – hibernate-validator-annotation-processor4.2.0.Final.jar – lib/required/validaton-api-1.0.0.GA.jar – lib/required/slf4j-api-1.6.1.jar – lib/optional/log4j-1.2.16.jar – lib/optional/slf4j-log4j12-1.6.1.jar Bean Validation Constraints (1) Annotation Use Example @AssertFalse The value of the field or property must be false. @AssertFalse boolean isUnsupported; @AssertTrue The value of the field or property must be true. @AssertTrue boolean isActive; @DecimalMax The value of the field or property must be a decimal value less than or equal to the number in the value element @DecimalMax(value="99.99") double wage; @DecimalMin The value of the field or property must be greater than or equal to the number in the value element @DecimalMin(value="8.88") double wage; Bean Validation Constraints (2) Annotatio n Use Example @Digits( integer=, fraction=) The value of the field or property must be a number within a specific range. The integer element specifies the maximum integral digits for the number, and the fraction element specifies the maximum fractional digits for the number @Digits(integer=6,faction=2) double price; @Future Date must be in the future @Future Date eventDate; Bean Validation Constraints (3) Annotation Use Example @Max The value of the field or property must be an integer value less than or equal to the number in the value element. @Max(value=25) int quantity; @Min The value of the field or property must be an integer value greater than or equal to the number in the value element. @Min(value=5) int quantity; @NotNull The value of the field or property must not be null. @NotNull String username; @Null The value of the field or property must be null. @Null String oldName; Bean Validation Constraints (4) Annotation Use Example @Past The value of the field or property must be a date in the past. @Past Date birthday; @Pattern The value of the field or property must match the regular expression defined in the regexp element. @Pattern(regexp= "^.+@.+\\.[a-zA-Z]{2,4}$") String emailAddress; @Size(min=, max=) The size of the field or property is evaluated and must match the specified boundaries. @Size(min=5,max=25) String username; @Valid Perform validation recursively on the associated object. @Valid Category productCategory; Hibernate Constraints Extensions Annotation Use @CreditCardNumber String passes the Luhn checksum test @Email String must a valid email address @Length(min=,max=) String length is between min and max. Hibernate column constraint metadata added @NotBlank Trimmed string length must be greater than 0 @NotEmpty String is not null and is not empty @Range(min=,max=) Numeric value must be between min and max @URL(protocol=,host=,port= ) String must be a valid URL Review Questions • • • • What is the main reason for using the Bean Validation? Name the three level of constraints Name the three methods used for validation Which annotation is use to check for a minimum integer value? • Which annotation is use to check if a string matches a regular expression pattern? • Which annotation is use to check the number of elements in a collection? • Is the @Past or @Future annotation inclusive? Resources • Hibernate Validator Reference Guide • JSR 303: Bean Validation DO NOW Exercise 13