Friday 29 January 2016

JSR303 & JSR349 Validation

Here is a simple memory jogger for doing the validation framework.

Annotations

@Null
@NotNull
@Min - Also creates a column check constraint
@Max - Also creates a column check constraint
@DecimalMin
@DecimalMax
@Future
@Past
@Size(max = , min = ) - used for strings, collections etc
@Pattern(regex = )
@AssertTrue
@AssertFalse


Test Case


For a Car class,

import javax.validation.constraints.NotNull;

/**
 * The Car type.
 */
public class Car
{
    /**
     * The manufacturer field.
     */
    @NotNull
    private String manufacturer;

    /**
     * Constructs a new Car with the given parameters.
     */
    public Car()
    {

    }

    /**
     * Gets the manufacturer value.
     *
     * @return the manufacturer
     */
    public String getManufacturer()
    {
        return manufacturer;
    }

    /**
     * Sets manufacturer to the given value.
     *
     * @param manufacturer the manufacturer to set
     */
    public void setManufacturer(String manufacturer)
    {
        this.manufacturer = manufacturer;
    }
}


A test to exercise the validation framework,

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
 * Test class to check the validation framework.
 */
public class ValidationTest
{

    /**
     * Test class to print out the values of a failed validation check.
     */
    @Test
    public void testValidate()
    {
        // Arrange
        final ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        final Validator validator = validatorFactory.getValidator();

        final Car car = new Car();

        // Act
        final Set<ConstraintViolation<Car>> violations = validator.validate(car);

        // Assert
        final ConstraintViolation constraintViolation = violations.iterator().next();

        assertTrue(constraintViolation.getRootBean() instanceof Car);
        assertEquals("com.package.to.validated.class.Car", constraintViolation.getRootBeanClass().getName());
        assertEquals("manufacturer", constraintViolation.getPropertyPath().toString());
        assertEquals("may not be null", constraintViolation.getMessage());
    }
}


Alternatively you can use the ValidationFactory to query the actual annotations that are on a bean and test that way.  For example, 


    final PropertyDescriptor propertyDescriptor = validator.getConstraintsForClass(Car.class).getConstraintsForProperty("manufacturer");

    final Set<ConstraintDescriptor<?>> constraints = propertyDescriptor.getConstraintDescriptors();
    final String message = descriptor.getMessageTemplate();
    final Object annotationType = descriptor.getAnnotation().annotationType();
        etc.


Maven


These are the maven dependencies that are required to make the validation classes available,


    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.0.0.GA</version>
    </dependency>
      
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.3.1.Final</version>
    </dependency>


BVal

BVal is an alternative JSR303 implementation from Apache.  Because Hibernate is written by JBoss it doesn't necessarily play well with old JBoss AS instances and in that case using BVal can work well.

    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.1.0.Final</version>
    </dependency>

    <dependency>
        <groupId>org.apache.bval</groupId>
        <artifactId>bval-jsr</artifactId>
        <version>1.1.1</version>
    </dependency>

References

http://docs.jboss.org/hibernate/validator/4.2/reference/en-US/pdf/hibernate_validator_reference.pdf

No comments:

Post a Comment