Objektvalidierung mit dem
Bean Validation API




                  JUG Hamburg – 07.04.2010

                            ...
Gunnar Morling

 • Contributor bei Hibernate Validator
 • Blogger (http://www.gunnarmorling.de/)
 • Softwarearchitekt/Entw...
Validierung allerorten

 • String:
      – nicht null
      – gültige E-Mail-Adresse oder URL
      – gültige PLZ
 • Zahl:...
Das Problem...




 • Redundante Definition von Constraints
 • Mögliche Inkonsistenzen
 • Verschiedene Runtimes, verschied...
... und die Lösung




 • Constraints an zentraler Stelle, eine Runtime
 • Realisierungsmöglichkeiten: programmatisch vs. ...
“Hello, Bean Validation!”
 public class Car {

     @NotNull
     private String manufacturer;

     @NotNull
     @Size(m...
JSR 303: “Bean Validation”

 • JSR 303:
      – Metamodell: Wie werden Constraints ausgedrückt?
      – API: Wie werden Co...
Demo 1: Constraints definieren

 • Demo 1:
      – Felder
      – Properties
      – Vererbung




07.04.2010             ...
Validierung von Objektgraphen
 public class Person {

     @NotNull
     @Size(min=3, max=50)
     private String name;

 ...
Validierung von Objektgraphen
 public class Person {

     @NotNull
     @Size(min=3, max=50)
     private String name;

 ...
Feldübergreifende Validierung

 • Validierung mitunter von mehreren Attributen einer Klasse
   abhängig:
 public class Car...
Feldübergreifende Validierung

 • Mittels Class-Level-Constraints Zugriff auf alle Attribute
   einer Klasse möglich:
 @Pa...
Vordefinierte Constraints

 • Bestandteil von JSR 303
      –   @Null, @NotNull
      –   @AssertFalse, @AssertTrue
      ...
Constraints auswerten

 • javax.validation.Validator:

 Car car = new Car(null, "DD­AB­123", 4);
     
 Validator validato...
javax.validation.ConstraintViolation
Car car = new Car("Morris", "DD­AB­123", 1);

Validator validator = 
Validation.build...
Validierungsgruppen

 • Erfordernis, nur Teilmengen der Constraints zu prüfen:
      – Objektlebenszyklus
      – Wizards
...
Validierungsgruppen – Beispiel
public class Order {

    @NotNull @Size(min = 10, max = 10)
    @Pattern(regexp = "ON[0­9]...
Validierungsgruppen – Beispiel
public class Order {

    public interface AfterProcessing {}

    @NotNull @Size(min = 10,...
@GroupSequence

 • Festlegung von Ausführungsreihenfolgen:
      – Prüfung sehr teuer (CPU, externe Services etc.)
      –...
Eigene Constraints definieren

 • Die Standard-Constraints können um eigene erweitert
   werden, z.B.:
      – Gültige Pos...
Zusammengesetzte Constraints

 • Drei Constraints für Validierung des Nummernschilds
 • Andere Entitäten mit gleichem Attr...
Zusammengesetzte Constraints
 @NotNull
 @Size(min = 2, max = 14)
 @CheckCase(CaseMode.UPPER)
 private String licensePlate;...
Zusammengesetzte Constraints
 @NotNull
 @Size(min = 2, max = 14)
 @CheckCase(CaseMode.UPPER)
 private String licensePlate;...
Zusammengesetzte Constraints

 • Rückgabe einer einzigen Constraint-Verletzung per
   @ReportAsSingleViolation:

 @NotNull...
XML-Konfiguration: validation.xml
<?xml version="1.0" encoding="UTF­8"?>
<validation­config
  xmlns="http://jboss.org/xml/...
XML-Konfiguration: Constraint-Mappings
 <?xml version="1.0" encoding="UTF­8"?>
 <constraint­mappings 
   xmlns="http://jbo...
Bootstrapping
 //1. Default­Factory
 Validator validator = 
     Validation.buildDefaultValidatorFactory().getValidator();...
Integration mit anderen APIs

 • JPA 2
      – Validierung vor Insert, Update (& Delete)
      – Kein Nachladen aus der DB...
07.04.2010   Bean Validation API   /29
Neues in Hibernate Validator 4.1

 • Annotation Processor: Constraintprüfung zur Compile-Zeit
 • Neue Constraints
      – ...
07.04.2010   Bean Validation API   /29
Fragen & Antworten




             ?!
07.04.2010   Bean Validation API       28/29
Referenzen

 • JSR 303: “Bean Validation”:
   http://jcp.org/en/jsr/detail?id=303
 • Hibernate Validator 4.0:
   http://ww...
Upcoming SlideShare
Loading in...5
×

Objektvalidierung mit dem Bean Validation Api

12,076

Published on

Slides meines Vortrags zum Bean Validation API (JSR 303) bei der JUG Hamburg

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
12,076
On Slideshare
0
From Embeds
0
Number of Embeds
35
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Objektvalidierung mit dem Bean Validation Api

  1. 1. Objektvalidierung mit dem Bean Validation API JUG Hamburg – 07.04.2010 Gunnar Morling
  2. 2. Gunnar Morling • Contributor bei Hibernate Validator • Blogger (http://www.gunnarmorling.de/) • Softwarearchitekt/Entwicklungsleiter bei der Otto Group 07.04.2010 Bean Validation API 2/29
  3. 3. Validierung allerorten • String: – nicht null – gültige E-Mail-Adresse oder URL – gültige PLZ • Zahl: – zwischen 0 und 100 – gültige Kreditkartennummer • GUI: Passwort_1 = Passwort_2 • Rechungsdatum nicht null (aber nur dann, wenn Auftrag im Zustand “fakturiert”) 07.04.2010 Bean Validation API 3/29
  4. 4. Das Problem... • Redundante Definition von Constraints • Mögliche Inkonsistenzen • Verschiedene Runtimes, verschiedene Validatoren 07.04.2010 Bean Validation API 4/29
  5. 5. ... und die Lösung • Constraints an zentraler Stelle, eine Runtime • Realisierungsmöglichkeiten: programmatisch vs. deklarativ • Quelle für Constraints in angrenzende Systemen (JavaScript, DDL) 07.04.2010 Bean Validation API 5/29
  6. 6. “Hello, Bean Validation!” public class Car {     @NotNull     private String manufacturer;     @NotNull     @Size(min = 2, max = 14)     private String licensePlate;     @Min(value=2, message="Seat count must be 2 at least.")     private int seatCount;          public Car(String manufacturer, String licencePlate, int seatCount) {         //...     }     //... } • Constraints: Annotationen mit Standard- (u.a. “message”) und spezifischen (z.B. “min”, “max”) Attributen 07.04.2010 Bean Validation API 6/29
  7. 7. JSR 303: “Bean Validation” • JSR 303: – Metamodell: Wie werden Constraints ausgedrückt? – API: Wie werden Constraints ausgewertet? • Spec Lead: Emmanuel Bernard (RedHat) • In allen Anwendungsschichten nutzbar • Teil von Java EE 6, aber auch unter SE nutzbar • Implementierungen: – Hibernate Validator (Referenzimplementierung, Teil von GF v3) – Agimatec Validation – Weitere geplant (z.B. OVal) 07.04.2010 Bean Validation API 7/29
  8. 8. Demo 1: Constraints definieren • Demo 1: – Felder – Properties – Vererbung 07.04.2010 Bean Validation API 8/29
  9. 9. Validierung von Objektgraphen public class Person {     @NotNull     @Size(min=3, max=50)     private String name;     //... } public class Car {     private String manufacturer;     private String licensePlate;     private int seatCount;          @NotNull     private Person driver;     //... } 07.04.2010 Bean Validation API 9/29
  10. 10. Validierung von Objektgraphen public class Person {     @NotNull     @Size(min=3, max=50)     private String name;     //... } public class Car {     private String manufacturer;     private String licensePlate;     private int seatCount;          @NotNull     @Valid     private Person driver;     //... } 07.04.2010 Bean Validation API 9/29
  11. 11. Feldübergreifende Validierung • Validierung mitunter von mehreren Attributen einer Klasse abhängig: public class Car {     private String manufacturer;     private String licensePlate;     @Min(value=2)     private int seatCount;          @NotNull     @NotEmpty     private List<Person> passengers;     //... } 07.04.2010 Bean Validation API 10/29
  12. 12. Feldübergreifende Validierung • Mittels Class-Level-Constraints Zugriff auf alle Attribute einer Klasse möglich: @PassengerCount public class Car {     private String manufacturer;     private String licensePlate;     @Min(value=2)     private int seatCount;          @NotNull     @NotEmpty     private List<Person> passengers;     //... } 07.04.2010 Bean Validation API 10/29
  13. 13. Vordefinierte Constraints • Bestandteil von JSR 303 – @Null, @NotNull – @AssertFalse, @AssertTrue – @Past, @Future – @Min, @Max, @Digits, @DecimalMin, @DecimalMax – @Size, @Pattern – @Valid • Zusätzlich in Hibernate Validator 4.0 – @Email – @Length – @NotEmpty – @Range 07.04.2010 Bean Validation API 11/29
  14. 14. Constraints auswerten • javax.validation.Validator: Car car = new Car(null, "DD­AB­123", 4);      Validator validator =      Validation.buildDefaultValidatorFactory().getValidator(); //Objekt validieren Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car);      //Property validieren constraintViolations = validator.validateProperty(car, "licensePlate");      //Wert validieren constraintViolations =      validator.validateValue(Car.class, "licensePlate", "DD­AB­123"); 07.04.2010 Bean Validation API 12/29
  15. 15. javax.validation.ConstraintViolation Car car = new Car("Morris", "DD­AB­123", 1); Validator validator =  Validation.buildDefaultValidatorFactory().getValidator(); Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car); assertEquals(1, constraintViolations.size()); ConstraintViolation<Car> violation = constraintViolations.iterator().next(); assertEquals(car, violation.getRootBean()); assertEquals("seatCount",      violation.getPropertyPath().iterator().next().getName()); assertEquals(1, violation.getInvalidValue()); assertEquals("Seat count must be 2 at least.", violation.getMessage()); assertEquals(Min.class,     violation.getConstraintDescriptor().getAnnotation().annotationType()); 07.04.2010 Bean Validation API 13/29
  16. 16. Validierungsgruppen • Erfordernis, nur Teilmengen der Constraints zu prüfen: – Objektlebenszyklus – Wizards – Nutzerrolle • Repräsentation in Form von Interfaces (Vererbungsbe- ziehungen, typsicher): •    public interface MyValidationGroup {} • Zuordnung von Constraints zu Gruppen: – Parameter “groups” – Ohne Zuordnung: javax.validation.groups.Default 07.04.2010 Bean Validation API 14/29
  17. 17. Validierungsgruppen – Beispiel public class Order {     @NotNull @Size(min = 10, max = 10)     @Pattern(regexp = "ON[0­9]*")     private String orderNumber;     @Valid @NotNull @Size(min = 1, max = 50)     private List<OrderLine> orderLines;     @NotNull @Past     private Date orderDate;     @NotNull @Past     private Date invoiceDate;     // ... } 07.04.2010 Bean Validation API 15/29
  18. 18. Validierungsgruppen – Beispiel public class Order {     public interface AfterProcessing {}     @NotNull @Size(min = 10, max = 10) @Pattern(regexp = "ON[0­9]*")     private String orderNumber;     @Valid @NotNull @Size(min = 1, max = 50)     private List<OrderLine> orderLines;     @NotNull @Past     private Date orderDate;     @NotNull(groups=AfterProcessing.class) @Past(groups=AfterProcessing.class)     private Date invoiceDate;          // ... } Validator validator = ...; Order order = ...; validator.validate(order, AfterProcessing.class); 07.04.2010 Bean Validation API 15/29
  19. 19. @GroupSequence • Festlegung von Ausführungsreihenfolgen: – Prüfung sehr teuer (CPU, externe Services etc.) – Prüfung von Constraints erfordert validen Basiszustand @GroupSequence({Default.class, AfterProcessing.class}) public interface Complete {} • • Festlegung der Default-Gruppe: @GroupSequence({Order.class, AfterProcessing.class}) public class Order {     // ... } 07.04.2010 Bean Validation API 16/29
  20. 20. Eigene Constraints definieren • Die Standard-Constraints können um eigene erweitert werden, z.B.: – Gültige Postleitzahl – Quersumme einer Auftragsnummer mod 10 = 0 – Event.startDate < Event.endDate • Was wird benötigt: – Constraint-Annotation – Validator(en) – Fehlertext ➔ Demo 2 07.04.2010 Bean Validation API 17/29
  21. 21. Zusammengesetzte Constraints • Drei Constraints für Validierung des Nummernschilds • Andere Entitäten mit gleichem Attribut? @NotNull @Size(min = 2, max = 14) @CheckCase(CaseMode.UPPER) private String licensePlate; 07.04.2010 Bean Validation API 18/29
  22. 22. Zusammengesetzte Constraints @NotNull @Size(min = 2, max = 14) @CheckCase(CaseMode.UPPER) private String licensePlate; @NotNull @Size(min = 2, max = 14) @CheckCase(CaseMode.UPPER) @Constraint(validatedBy={}) @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface ValidLicensePlate {     String message() default "{de.jughh.bv.ValidLicensePlate.message}";     Class<?>[] groups() default {};     Class<? extends Payload>[] payload() default {}; } 07.04.2010 Bean Validation API 19/29
  23. 23. Zusammengesetzte Constraints @NotNull @Size(min = 2, max = 14) @CheckCase(CaseMode.UPPER) private String licensePlate; @NotNull @Size(min = 2, max = 14) @CheckCase(CaseMode.UPPER) @Constraint(validatedBy={}) @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface ValidLicensePlate {     String message() default "{de.jughh.bv.ValidLicensePlate.message}";     Class<?>[] groups() default {};     Class<? extends Payload>[] payload() default {}; } @ValidLicensePlate private String licensePlate; 07.04.2010 Bean Validation API 19/29
  24. 24. Zusammengesetzte Constraints • Rückgabe einer einzigen Constraint-Verletzung per @ReportAsSingleViolation: @NotNull @Size(min = 2, max = 14) @CheckCase(CaseMode.UPPER) @ReportAsSingleViolation @Constraint(validatedBy={}) @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface ValidLicensePlate {     String message() default "{de.jughh.bv.ValidLicensePlate.message}";     Class<?>[] groups() default {};     Class<? extends Payload>[] payload() default {}; } 07.04.2010 Bean Validation API 20/29
  25. 25. XML-Konfiguration: validation.xml <?xml version="1.0" encoding="UTF­8"?> <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                                            validation­configuration­1.0.xsd">          <constraint­validator­factory>       de.jughh.bv.MyConstraintValidatorFactory     </constraint­validator­factory>     <message­interpolator>       de.jughh.bv.MyMessageInterpolator     </message­interpolator>     <constraint­mapping>       META­INF/validation/car­constraints.xml     </constraint­mapping>     <constraint­mapping>...</constraint­mapping>     <property name="de.jughh.bv.validation.logging">WARN</property> </validation­config> 07.04.2010 Bean Validation API 21/29
  26. 26. XML-Konfiguration: Constraint-Mappings <?xml version="1.0" encoding="UTF­8"?> <constraint­mappings    xmlns="http://jboss.org/xml/ns/javax/validation/mapping"   xmlns:xsi="http://www.w3.org/2001/XMLSchema­instance"   xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping                                                 validation­mapping­1.0.xsd">   <default­package>de.jughh.bv.domain</default­package>   <bean class="Car" ignore­annotations="false">     <field name="licensePlate">       <constraint annotation="javax.validation.constraint.Size">         <message>Size of license plate is limited</message>         <groups>           <value>de.jughh.bv.LightValidation</value>         </groups>         <element name="max">10</element>       </constraint>     </field>   </bean> </constraint­mappings> 07.04.2010 Bean Validation API 22/29
  27. 27. Bootstrapping //1. Default­Factory Validator validator =      Validation.buildDefaultValidatorFactory().getValidator(); //2. Angepasste Factory Configuration<?> configuration = Validation.byDefaultProvider().configure();      ValidatorFactory validatorFactory = configuration     .messageInterpolator(         new MyMessageInterpolator(             configuration.getDefaultMessageInterpolator()))     .constraintValidatorFactory(         new MyConstraintValidatorFactory(             configuration.getDefaultConstraintValidatorFactory()))     .ignoreXmlConfiguration()     .buildValidatorFactory();      Validator validator = validatorFactory.getValidator(); //3. Providerspezifische Konfiguration HibernateValidatorConfiguration configuration =      Validation.byProvider(HibernateValidator.class).configure(); 07.04.2010 Bean Validation API 23/29
  28. 28. Integration mit anderen APIs • JPA 2 – Validierung vor Insert, Update (& Delete) – Kein Nachladen aus der DB – Berücksichtigung von Constraints für DDL • JSF 2 – Autom. Validierung aller gebundenen Properties – Wichtig: javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL = true • Java EE 6 – Injektion von ValidatorFactory und Validator:     @Resource     private ValidatorFactory validatorFactory;     @Resource     private Validator validator; 07.04.2010 Bean Validation API 24/29
  29. 29. 07.04.2010 Bean Validation API /29
  30. 30. Neues in Hibernate Validator 4.1 • Annotation Processor: Constraintprüfung zur Compile-Zeit • Neue Constraints – @CreditCardNumber – @NotBlank – @URL – @ScriptAssert: • @ScriptAssert(lang = "jexl", script = "_this.startDate < _this.endDate") public class CalendarEvent { •     private Date startDate; •     private Date endDate; •     //constructor, getter, setter ... } RBL • 07.04.2010 Bean Validation API 26/29
  31. 31. 07.04.2010 Bean Validation API /29
  32. 32. Fragen & Antworten ?! 07.04.2010 Bean Validation API 28/29
  33. 33. Referenzen • JSR 303: “Bean Validation”: http://jcp.org/en/jsr/detail?id=303 • Hibernate Validator 4.0: http://www.hibernate.org/subprojects/validator.html • Hibernate Validator Reference Guide: http://docs.jboss.org/hibernate/stable/validator/reference/ en/html/ • Forum zu Hibernate Validator: https://forum.hibernate.org/viewforum.php?f=9 • Musings of a programming Addict – Artikel zu BV: http://musingsofaprogrammingaddict.blogspot.com/search/ label/Bean%20Validation 07.04.2010 Bean Validation API 29/29

×