Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Keeping Your Data Sane with Bean Validation 2.0

Keeping Your Data Sane with Bean Validation 2.0

-- Presented at JavaOne 2017 --

Rich UIs, schemaless data stores, REST-based APIs—the need for powerful data validation is greater than ever. The Bean Validation standard is here to help, defining a rich validation API based on annotations.

Bean Validation 2.0 (JSR 380) makes validation even more expressive, leveraging Java 8 features such as type and repeatable annotations or default methods. This opens up exciting opportunities for Bean Validation, such as List<@Email String>. Part of Java EE 8, Bean Validation 2.0 can be used on Java SE too.

This code-centric session explores many of the new features right in the IDE. Find out how Bean Validation integrates with specs such as JAX-RS and how to implement your own constraints, ensuring that your data is sane at all times.

Gunnar Morling

October 05, 2017
Tweet

More Decks by Gunnar Morling

Other Decks in Programming

Transcript

  1. Keeping Your Data Sane with
    Bean Validation 2.0
    Gunnar Morling
    @gunnarmorling
    1

    View Slide

  2. Agenda
    What is Bean Validation?
    What's new in Bean Validation 2.0?
    Questions
    2

    View Slide

  3. Gunnar Morling
    Open source software engineer at Red Hat
    Debezium
    Hibernate
    Spec Lead for Bean Validation 2.0
    Other projects: ModiTect, MapStruct
    [email protected]
    @gunnarmorling
    http://in.relation.to/gunnar-morling/
    3

    View Slide

  4. What is Bean Validation?
    "Constrain once, validate everywhere"
    Constraints for JavaBeans
    Validation via API or automatically

    JPA
    JSF, Spring MVC, GWT
    JAX-RS
    Extensible (custom constraints)
    BV 1.1: ​
    method validation
    4

    View Slide

  5. Demo
    5

    View Slide

  6. Bean Validation 2.0 - JSR 380
    Benefit from new Java 8 language features
    Support for API extensions
    6

    View Slide

  7. Use Case: Different Passwords
    for Different Roles
    @Size.List({
    @Size(min = 8, group = Default.class),
    @Size(min = 12, group = Admin.class)
    })
    private char[] password = ...;
    7

    View Slide

  8. Use Case: Different Passwords
    for Different Roles
    @Size.List({
    @Size(min = 8, group = Default.class),
    @Size(min = 12, group = Admin.class)
    })
    private char[] password = ...;
    @Size(min = 8, group = Default.class)
    @Size(min = 12, group = Admin.class)
    private char[] password = ...;
    8

    View Slide

  9. Use Case: Ensure Non-Empty
    Collection Elements
    private List names;
    9

    View Slide

  10. Use Case: Ensure Non-Empty
    Collection Elements
    private List names;
    @NotEmpty
    private List names;
    10

    View Slide

  11. Use Case: Ensure Non-Empty
    Collection Elements
    private List names;
    @OnElements([email protected])
    private List names;
    11

    View Slide

  12. Use Case: Ensure Non-Empty
    Collection Elements
    private List names;
    private List<@NotEmpty String> names;
    @OnElements([email protected])
    private List names;
    12

    View Slide

  13. Use Case: Ensure Non-Empty
    Collection Elements
    private List names;
    private List<@NotEmpty
    @Pattern(regexp="[a-zA-Z]*") String> names;
    @OnElements([email protected])
    private List names;
    13

    View Slide

  14. private List<@NotEmpty
    @Pattern(regexp="[a-zA-Z]*") String> names;
    Use Case: Ensure Non-Empty
    Collection Elements
    private List names;
    @NotEmpty
    private List<@NotEmpty String> names;
    @OnElements([email protected])
    private List names;
    14

    View Slide

  15. @Target({
    METHOD, FIELD, ANNOTATION_TYPE,
    CONSTRUCTOR, PARAMETER,
    TYPE_USE
    })
    @Retention(RUNTIME)
    @Repeatable(List.class)
    @Documented
    @Constraint(validatedBy = { })
    public @interface Size {
    ...
    }
    Type Annotations (JSR 308)
    New element type TYPE_USE
    15

    View Slide

  16. Cascaded Validation
    @Valid
    private List addresses;
    16

    View Slide

  17. Cascaded Validation
    @Valid
    private List addresses;
    private List<@Valid Address> addresses;
    17

    View Slide

  18. Cascaded Validation
    @Valid
    private List addresses;
    private List<@Valid Address> addresses;
    private Map<@Valid Comment, Integer> scorePerComment;
    18

    View Slide

  19. Cascaded Validation
    @Valid
    private List addresses;
    private List<@Valid Address> addresses;
    private Map<@Valid Comment, Integer> scorePerComment;
    private Map<@Valid AddressType,
    List<@Valid Address>> addressesByType;
    19

    View Slide

  20. Further Supported Containers
    Optional, OptionalInt, OptionalLong, OptionalDouble
    JavaFX's property types
    Optional<@Email String> getEmail() { ... };
    20

    View Slide

  21. Custom Containers
    Specific collection types (e.g. Google Guava)
    Other JVM languages (Ceylon, Scala etc.)
    Enabled via Extractor SPI
    private Table revenuePerYearAndCategory;
    21

    View Slide

  22. private Table revenuePerYearAndCategory;
    private Table
    revenuePerYearAndCategory;
    Custom Containers
    Specific collection types (e.g. Google Guava)
    Other JVM languages (Ceylon, Scala etc.)
    Enabled via Extractor SPI
    22

    View Slide

  23. Demo
    23

    View Slide

  24. Use Case: Delivery Date in the
    Future
    @Past/@Future supported for JSR 310 types:
    java.time.LocalDateTime, ZonedDateTime etc.
    @Future
    private LocalDate deliveryDate = LocalDate.of(
    2017, Month.MAY, 12
    );
    24

    View Slide

  25. Use Case: Delivery Date in the
    Future
    @Past/@Future supported for JSR 310 types:
    java.time.LocalDateTime, ZonedDateTime etc.
    @FutureOrPresent
    private LocalDate deliveryDate = LocalDate.of(
    2017, Month.MAY, 12
    );
    @Future
    private LocalDate deliveryDate = LocalDate.of(
    2017, Month.MAY, 12
    );
    25

    View Slide

  26. Use Case: Testing
    ValidatorFactory vf = Validation.byDefaultProvider()
    .configure()
    .clockProvider(
    new FixedClockProvider(
    ZonedDateTime.of(
    2016, 6, 15, 0, 0, 0, 0,
    ZoneId.of( "Europe/Paris" )
    )
    )
    )
    .buildValidatorFactory();
    26

    View Slide

  27. New Constraints
    @NotEmpty, @NotBlank
    @Email
    @Positive, @PositiveOrZero , @Negative, @NegativeOrZero
    @PastOrPresent, @FutureOrPresent
    27

    View Slide

  28. Other Java 8 Goodies
    Real parameter names in error messages
    ConstraintValidator without initialize()
    public class NotNullValidator implements
    ConstraintValidator {
    public void initialize(NotNull constraintAnnotation) {}
    public boolean isValid(Object object,
    ConstraintValidatorContext ctx) {
    return object != null;
    }
    }
    public class NotNullValidator implements
    ConstraintValidator {
    public boolean isValid(Object object,
    ConstraintValidatorContext ctx) {
    return object != null;
    }
    }
    28

    View Slide

  29. Status
    Released final
    version in August
    Reference implementation:
    Hibernate Validator 6.0
    29

    View Slide

  30. Final Release
    Part of Java EE 8
    Contained in GlassFish 5; easy-to-use patch for WildFly
    Supported by Spring 5
    Everything open source: spec, API, TCK and reference
    implementation
    30

    View Slide

  31. Summary
    Support for container-element constraints
    Repeatable constraints
    New constraint types
    Improved date/time support
    ConstraintValidator#initialize() is a default method
    http://beanvalidation.org/2.0/spec/#whatsnew-20
    31.1

    View Slide

  32. Outlook Bean Validation 2.1
    Constraint-API
    ConstraintMapping mapping = ...;
    mapping.type( Marathon.class )
    .property( "numberOfHelpers", FIELD )
    .constraint( new MinDef().value( 1 ) )
    .property( "runners", METHOD )
    .valid();
    31.2

    View Slide

  33. Outlook Bean Validation 2.1
    Constraint-API
    ConstraintMapping mapping = ...;
    mapping.type( Marathon.class )
    .property( "numberOfHelpers", FIELD )
    .constraint( new MinDef().value( 1 ) )
    .property( "runners", METHOD )
    .valid();
    mapping.constraintDefinition( FileExists.class )
    .validateType( File.class )
    .with( f -> f.exists() );
    Constraint-API: Lambda
    31.3

    View Slide

  34. Resources
    Spec
    Reference implementation
    API, specifikation, TCK, website
    Contributions welcome!
    @gunnarmorling
    http://beanvalidation.org/2.0/spec/
    github.com/hibernate/hibernate-validator/
    github.com/beanvalidation/
    32

    View Slide

  35. 33

    View Slide