Bean Validation - Cours v 1.1

Laurent Guérin
Laurent GuérinJava Architect - Telosys project leader à Sogeti
Java
Bean Validation API
Université de Nantes
&
Ecole des Mines de Nantes
Laurent Guérin / V 1.1 / Janvier 2014
@ltguerin
Introduction
Introduction
La validation des données est indispensable dans
toute application. Elle peut intervenir à différents
niveaux :
Couche de présentation (informations saisies par
l’utilisateur)
Couche métier
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 3
Couche de persistance (conformité avec les contraintes
définies dans la base de données, … )
Etc…
Bean Validation propose un framework normalisé
(spécification Java, JSR,… ) pour valider les
informations portées par les Java Beans (et les
paramètres de méthodes dans la version 1.1)
Introduction
Les contraintes/rêgles de validation sont définies dans
le code source du bean à valider.
Elles sont exprimées par des « annotations » qui
peuvent être appliquées à différents niveaux :
Attribut
Méthode (getter/setter)
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 4
Méthode (getter/setter)
Classe
Elles peuvent aussi être définies dans un fichier XML
Un objet « validator » va ensuite vérifier que toutes
les contraintes du bean sont respectées
Il est possible d’étendre le framework en créant des
contraintes personnalisées
Exemples
public class Car {
@NotNull
private String manufacturer;
@NotNull
@Size(min = 2, max = 14)
private String licensePlate;
@Min(2)
private int seatCount;
...
public class Person {
@Min(1)
private int id ;
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 5
...
} @NotNull @Size(min=1, max=30)
private String name ;
@Min(0)
private int age ;
@NotNull @DecimalMin("1500.00")
@DecimalMax("99999.99")
private BigDecimal salary ;
...
}
Bean Validation 1.0
JSR-303
Bean Validation version 1.0
Spécification lancée en 2006 et finalisée en 2009
JSR-303
cf : https://jcp.org/en/jsr/detail?id=303
Fait partie de Java EE 6
Cf : http://docs.oracle.com/javaee/6/tutorial/doc/
Utilisé notamment pour les validation dans JSF ( Java
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 7
Utilisé notamment pour les validation dans JSF ( Java
Server Faces )
Packages « javax.validation.* »
Spécification et implémentations
Bean Validation 1.0
Specification
API
JSR 303
Application
Java EE 6
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 8
Hibernate
Validator
Apache
Bean Validation
Implémentations
( R.I. )
http://bval.apache.org/http://hibernate.org/validator/
Les annotations de la JSR-303
Annotation Applicable aux types…
@Null
@NotNull Object
@Min
@Max
BigDecimal, BigInteger,
byte, short, int, long (+ Wrappers)
@DecimalMin
@DecimalMax
BigDecimal, BigInteger, String
byte, short, int, long (+ Wrappers)
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 9
byte, short, int, long (+ Wrappers)
@Size String, Collection, Map, Array
@Digits BigDecimal, BigInteger, String
byte, short, int, long (+ Wrappers)
@Past
@Future java.util.Date, java.util.Calendar
@Pattern String
@AssertTrue
@AssertFalse Boolean, boolean
Exemples
@NotNull
String username;
@Null
String unusedString;
@AssertTrue
boolean isActive;
@AssertFalse
boolean isUnsupported;
Objets ( vérification Null / Not Null )
Booléens ( vérification True/False )
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 10
boolean isActive; boolean isUnsupported;
@Size(min=2, max=240)
String message;
@Size(min=12)
String name;
Taille ( vérification mini/maxi )
@Size(min=1, max=10)
List<Element> elements;
@Size(max=100)
LinkedList<String> words;
Exemples
@Past
Date dateNaissance;
@Future
Date nextMeeting;
Dates ( vérification date du passé ou du futur )
Nombres ( vérification valeur mini/maxi )
@Min(0)
@Max(140)
private int age ;
@DecimalMin("5.00")
@DecimalMax("30.00")
BigDecimal discount;
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 11
@Digits(integer=6, fraction=2)
BigDecimal price;
// 'integer' : maximum integral digits for the number
// 'fraction' : maximum fractional digits for the number
@Pattern(regexp="(d{3})d{3}-d{4}")
String phoneNumber;
Chaînes de caractères ( vérification / expression régulière )
Nombres décimaux ( vérification « xxxx.xx »)
@NotEmpty // Ni null, ni vide
String firstName;
@NotBlank // Ni null, ni composé de “blancs”
Contraintes spécifiques Hibernate
NB : L’implémentation Hibernate Validator fournit des annotations
supplémentaires qui ne font pas partie de la spécification officielle.
Cf package « org.hibernate.validator.constraints »
Exemples :
NB : L’utilisation de
ces annotations
induit une adhérence
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 12
@NotBlank // Ni null, ni composé de “blancs”
String lastName;
@Email
String email ;
@CreditCardNumber // N° de carte de crédit (Luhn checksum)
@Length(min=2, max=12) // Longueur entre min et max
@ModCheck // “Mod 10” ou “Mod 11” checksum algorithm
@Range(min=2, max=12) // Valeur entre min et max
@SafeHtml(whitelistType=, additionalTags=) // => librairie Jsoup
@ScriptAssert(lang=, script=, alias=)
@URL(protocol=, host=, port=,...) // URL valide
induit une adhérence
à Hibernate !
Remarques
@Min(1) @DecimalMin("0.2")
int value;
Toutes les contraintes sont évaluées,
même si elles sont incohérentes ou contradictoires
Si value=0 : 2 violations détectées
@Min(3) @Max(2)
int value;
Toujours 1 violation détectée
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 13
Si une contrainte n’est pas applicable au type Exception
@Past // Pour une date
int value;
javax.validation.UnexpectedTypeException
No validator could be found for type: xxxxx@Pattern(regexp=".+@.+.[a-z]+")
int value;
Validation d’un graphe d’objets
public class Car {
@NotNull
@Valid
private Person driver;
Lorsque des objets sont imbriqués, il faut utiliser l’annotation
@Valid pour valider l’objet référencé
public class Person {
@Min(1)
« driver » ne doit pas être « null »
et l’instance de Person doit être « valid »
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 14
private Person driver;
public Car(Person driver) {
this.driver = driver;
}
//getters & setters ...
}
@Min(1)
private int id;
@NotNull
private String name;
//getters & setters ...
}
@NotNull
@Valid
private List<Person> passengers = new ArrayList<Person>();
Egalement applicable pour les collections
Utilisation
du « Validator »
Objet « Validator »
Les annotations (@NotNull, @Size, etc) ne font que
déclarer des contraintes
Ces contraintes sont vérifiées par un moteur de
validation : un objet qui implémente l’interface
« Validator »
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 16
Ce « Validator » est généralement embarqué dans
l’environnement d’exécution, il est utilisé pour valider
les beans au moment opportun
Objet « Validator »
Validator est utilisé par
Les « containers » ou les « frameworks » qui gèrent le
cycle de vie des objets
Les environnements capables d’intercepter des appels de
méthodes (AOP, … ) et donc de déclencher une validation
lors de l’invocation d’une méthode
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 17
Objet « Validator »
Pour tester unitairement la validation des beans,
il faut récupérer une instance de « Validator » et invoquer
ses méthodes de validation.
Le « Validator » est fabriqué par « ValidatorFactory ».
ValidatorFactory validatorFactory =
Validation.buildDefaultValidatorFactory() ;
Validator validator = validatorFactory.getValidator();
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 18
L’appel de la méthode « validate » renvoie une
liste de « ConstraintViolation »:
Validator validator = validatorFactory.getValidator();
//--- Création et initialisation du bean
Author author = new Author();
author.setId(1);
//--- Validation du bean
Set<ConstraintViolation<Author>> constraintViolations =
validator.validate(author);
Objet « Validator »
Il est possible de ne valider que certaines propriétés d’un
bean avec validateProperty(…)
//--- Création et initialisation du bean
Author author = new Author();
author.setId(1);
//--- Validation des propriétés du bean
Set<ConstraintViolation<Author>> errors ;
errors = validator.validateProperty( author, "id" );
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 19
errors = validator.validateProperty( author, "id" );
errors = validator.validateProperty( author, "firstName" );
//--- Contraintes définies dans une classe
BeanDescriptor desc = validator.getConstraintsForClass(Author.class)
Récupération de la description des contraintes d’une classe :
//--- Si la valeur de l’attribut était...
validator.validateValue( Author.class, "firstName", "Foo" )
Situation de test pour une valeur d’une propriété (attribut) :
Exemple JUnit
public class AuthorValidTest {
private final static Validator validator =
Validation.buildDefaultValidatorFactory().getValidator();
@Test
public void testAuthor() {
Author author = new Author();
author.setId(1);
Set<ConstraintViolation<Author>> constraintViolations =
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 20
Set<ConstraintViolation<Author>> constraintViolations =
validator.validate(author);
print (constraintViolations);
}
private <T> void print( Set<ConstraintViolation<T>> errors ) {
for ( ConstraintViolation<T> cv : errors ) {
System.out.println(" . " + cv.getPropertyPath()
+ " (in " + cv.getRootBeanClass().getSimpleName()
+ ") " + cv.getMessage() );
}
}
Gestion des messages
d’erreur
Messages d’erreurs
Toutes les contraintes prédéfinies ont un message
par défaut disponible dans plusieurs langues.
Par exemple, Hibernate Validator affiche des
messages en français ou en anglais.
Chaque contrainte est identifiée par une « clé ».
A cette clé est associé un message (Java properties)
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 22
A cette clé est associé un message (Java properties)
Le message par défaut peut être forcé pour chaque
utilisation d’une annotation.
Exemple :
@NotNull(message = "Le nom ne doit pas être null" )
String nom;
@Min(value=0, message= "L’age ne peut pas être < 0" )
int age;
Messages d’erreurs
Les valeurs de l’annotation peuvent être insérées
dans le message en utilisant la notation {variable}
Exemple :
Les messages par défaut sont définis dans le fichier
@Min(value=0, message="L’age doit être au minimum {value} " )
int age;
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 23
Les messages par défaut sont définis dans le fichier
« ValidationMessages.properties ».
Ce fichier est utilisé par « MessageInterpolator »
(interface) qui va rechercher le fichier des messages
1) à la racine du ClassPath
2) dans le JAR de l’implémentation
( ex « org.hibernate.validator » pour Hibernate Validator )
Messages d’erreurs
Extrait du fichier des messages d’Hibernate Validator
javax.validation.constraints.AssertFalse.message =
must be false
javax.validation.constraints.AssertTrue.message =
must be true
javax.validation.constraints.DecimalMax.message =
must be less than or equal to {value}
javax.validation.constraints.DecimalMin.message =
must be greater than or equal to {value}
javax.validation.constraints.Digits.message =
Fichier
ValidationMessages.properties
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 24
javax.validation.constraints.Digits.message =
numeric value out of bounds
(<{integer} digits>.<{fraction} digits> expected)
javax.validation.constraints.Future.message =
must be in the future
javax.validation.constraints.Max.message =
must be less than or equal to {value}
javax.validation.constraints.Min.message =
must be greater than or equal to {value}
javax.validation.constraints.Past.message =
must be in the past
javax.validation.constraints.Pattern.message =
must match "{regexp}"
javax.validation.constraints.Size.message =
size must be between {min} and {max}
Création de contraintes
spécifiques
Contraintes spécifiques
Certaines règles de validation nécessitent de définir
des contraintes spécifiques
( « custom constraints » ).
Elles peuvent être positionnées à différents niveaux
Champ (attribut ) « field-level constraint »
Classe « class-level constraint »
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 26
Classe « class-level constraint »
(validation globale d’une instance)
Pour créer une « custom constraint » il faut …
1) créer l’ annotation qui définit la contrainte
2) créer le « validator » qui va vérifier la contrainte
3) définir un message d’erreur par défaut
Custom Constraint 1 : « field level »
Exemple 1 :
création d’une contrainte qui vérifie qu’une chaîne de
caractères est bien
en « upper case » ou « lower case »…
=> « field-level »
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 27
@CheckCase(value=CaseMode.LOWER)
private String firstName;
@CheckCase(value=CaseMode.UPPER)
private String lastName;
Utilisation attendue :
Custom Constraint 1 - Annotation
public enum CaseMode {
UPPER,
LOWER;
}
@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy =
CheckCaseValidator.class)
@Documented
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 28
@Documented
public @interface CheckCase {
String message() default "{org.demo.constraints.checkcase}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
CaseMode value();
}
Clé dans le
fichier des messages
Custom Constraint 1 - Validator
public class CheckCaseValidator
implements
ConstraintValidator<CheckCase, String> {
private CaseMode caseMode;
@Override
public void initialize( CheckCase constraintAnnotation ) {
this.caseMode = constraintAnnotation.value(); // MAJUS/MINUS
}
Valide des instances
de « String »
Contrainte
« CheckCase »
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 29
@Override
public boolean isValid(String object, // objet à valider
ConstraintValidatorContext constraintContext) {
if (object == null) return true; // considéré comme valide
if (caseMode == CaseMode.UPPER) // test MAJUS. ou MINUS.
return object.equals(object.toUpperCase());
else
return object.equals(object.toLowerCase());
}
}
Custom Constraint 1 - Message
org.demo.constraints.checkcase = Invalid case, must be {value}
Fichier « ValidationMessages.properties »
situé à la racine du ClassPath
Pour gérer l’internationalisation des messages et avoir par
exemple des messages en français,
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 30
exemple des messages en français,
créer un fichier « ValidationMessages_fr.properties »
org.demo.constraints.checkcase = Controle MINUSCULE/MAJUSCULE invalide
Custom Constraint 2 : « class level »
Exemple 2 :
création d’une contrainte qui vérifie la validité d’une
instance de la classe « Person »
=> « class-level »
Utilisation attendue :
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 31
@PersonValidation // Class-level validation
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String firstName;
private String lastName;
[...]
}
Utilisation attendue :
Custom Constraint 2 - Annotation
@Documented
@Constraint(validatedBy = PersonValidator.class)
@Target({ElementType.TYPE}) // Annotation for a CLASS
@Retention(RetentionPolicy.RUNTIME)
public @interface PersonValidation {
String message() default "{org.demo.constraints.person}";
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 32
Class<?>[] groups() default {};
Class<?>[] payload() default {};
// Pas d’autre info (pas de "value")
}
Custom Constraint 2 - Validator
public class PersonValidator
implements ConstraintValidator<PersonValidation, Person> {
@Override
public void initialize(PersonValidation constraint) {
// Rien à faire ici
}
@Override
Valide des instances
de « Person »
Validation de la contrainte
« PersonValidation »
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 33
@Override
public boolean isValid( Person person,
ConstraintValidatorContext context) {
// Validation des différens champs de l’instance
if ( person.getId() < 1 ) return false ;
if ( person.getId() > 99999 ) return false ;
if ( person.getFirstName() == null ) return false ;
if ( person.getFirstName().length() < 1 ) return false ;
// etc...
return true;
}
Bean Validation 1.1
JSR-349
Bean Validation version 1.1
Spécification approuvée début 2013
JSR-349
cf : https://jcp.org/en/jsr/detail?id=349
Fait partie de Java EE 7
Cf :
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 35
Cf :
https://blogs.oracle.com/theaquarium/entry/java_ee_7_pla
tform_completes
Implémentation de référence :
« Hibernate Validator »
Cf http://hibernate.org/validator/
JSR-349 : Quoi de neuf ?
Meilleure intégration avec :
JPA
CDI
JAX-RS
JSF
2 nouveaux packages
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 36
2 nouveaux packages
avec notamment la classe
« ValidateOnExecution »
Validation des paramètres d’une méthode
Utilisation de « EL » pour les messages
Les annotations servant à définir les contraintes
sont les mêmes qu’en JSR-303 (pas de changement)
Validation lors de l’appel de méthodes
public class MyBean {
private String name;
Les annotations peuvent aussi être utilisées pour contrôler
la validité des paramètres passés à des méthodes ou des
constructeurs, ainsi que les valeurs renvoyées.
Exemples :
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 37
public MyBean( @NotNull String name ) {
this.name = name;
}
@Size(min = 3)
public String updateName(
@NotNull @Size(min = 1) String firstName,
@NotNull @Size(min = 1) String lastName) {
name = firstName + " " + lastName;
return name;
}
}
Validation lors de l’appel de méthodes
// Valider les paramètres simples d’une méthode
public User createUser ( @NotNull String name,
@Past Date birthDate ) {
...
}
// Valider des paramètres de type “bean” (objet spécifique)
Exemples :
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 38
// Valider des paramètres de type “bean” (objet spécifique)
public Order createOrder (..., @Valid User user) {
...
}
// Valider le “résultat” (retour) d’une méthode
@NotNull
public Employee getEmployee() { // Ne doit pas renvoyer null
...
}
Annotation « @ValidateOnExecution »
Permet d’indiquer quelles méthodes doivent être validées lors
de l’exécution (méthodes ou constructeurs).
Elle peut être placée au niveau de la classe et/ou
au niveau des méthodes/constructeurs
Si l’annotation @ValidateOnExecution est présente
elle définit explicitement les règles de validation à appliquer
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 39
elle définit explicitement les règles de validation à appliquer
(quelles méthodes,
quels types de méthodes, ...)
Si elle n’est pas présente, c’est la configuration de
« bean validation » qui s’applique.
La configuration est définie à partir …
• du fichier « META-INF/validation.xml » s’il existe
• de la configuration par défaut (cf JavaDoc)
ALL, CONSTRUCTORS, GETTER_METHODS,
NON_GETTER_METHODS, IMPLICIT, NONE
Validation des appels de méthodes
Principe de fonctionnement :
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 40
Exemples
public class OrderService {
boolean isValidCustomer( @NotNull String customerCode) {
[...]
}
@ValidateOnExecution
@Min(0)
Dans un service avec « @ValidateOnExecution »
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 41
@Min(0)
Integer getBacklog() {
[...]
}
@ValidateOnExecution(type=NONE)
Order placeOrder( @NotNull String customerCode,
@Valid Item item, int quantity) {
[...]
}
}
Utilisation
dans Java EE et dans
les frameworks Java
Adoption de la JSR-303
Bean Validation est utilisé dans
Certains composants standards de Java EE (de + en +),
par exemple :
JSF (JavaServer Faces) – Web
Jersey (RI de JAX-RS) – REST
JPA – Persistance
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 43
Et dans de nombreux frameworks Java,
notamment :
Spring MVC
Wicket
Tapestry
Bean Validation / JPA
Author author = new Author() ;
author.setId(1);
author.setFirstName("Joe");
public class Author {
@Min(1) @Max(99999)
private int id;
@NotNull @Size(min=1, max=20 )
private String firstName;
[...]
}
JPA valide le Bean lors
de l’invocation des
méthodes de persistance
Si bean invalide Exception
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 44
author.setFirstName("Joe");
EntityManager em = .. ;
try {
em.persist(author); // Validation du bean par JPA
}
catch (ConstraintViolationException exception) {
Set<ConstraintViolation<?>> constraintsViolations =
exception.getConstraintViolations();
int n = constraintsViolations.size();
}
Bean Validation / Jersey (REST / JAX-RS )
@Path("/")
class MyResourceClass {
@POST
@Consumes("application/x-www-form-urlencoded")
public void registerUser(
@NotNull @FormParam("firstName") String firstName,
@NotNull @FormParam("lastName") String lastName,
@Email @FormParam("email") String email) {
...
}
}
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 45
@Path("/")
class MyResourceClass {
@Email
@ValidateOnExecution
public String getEmail() {
return email;
}
}
}
@Path("/")
class MyResourceClass {
@POST
@Consumes("application/xml")
public void registerUser(
@Valid User user) {
...
}
}
Bean Validation / Spring MVC
Depuis la version 3.0 Spring MVC supporte
intégralement la JSR-303
Exemples :
import javax.validation.Validator ;
@Service
public class MyService {
@Autowired
Injection d’un « Validator »
dans un service
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 46
@Controller
public class MyController {
@RequestMapping("/foo", method=RequestMethod.POST)
public void processFoo( @Valid Foo foo ) {...}
@Autowired
private Validator validator;
Validation des données d’un
formulaire dans « Controller »
Bean Validation / Wicket
Par ajout d’un « JSR303FormValidator »
public class HomePage extends WebPage {
public HomePage(final PageParameters parameters) {
Person person = new Person();
final Form<Person> personForm = new Form<Person>("personForm",
new CompoundPropertyModel<Person>(person) );
personForm.add(new TextField<String>("firstName"));
personForm.add(new TextField<String>("lastName"));
personForm.add(new TextField<Integer>("age"));
personForm.add(new Button("submit") {
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 47
personForm.add(new Button("submit") {
@Override
public void onSubmit() {
personForm.info("Submitted " +
personForm.getDefaultModelObjectAsString());
}
});
personForm.add( new JSR303FormValidator() );
add(personForm);
add(new FeedbackPanel("feedback"));
}
}
Nécessite un
« CompoundPropertyModel »
pour l’accès aux propriétés
du bean par réflexion
Annexes
Dépendances Maven / BeanValidation 1.0
<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>
Bean Validation 1.0.0
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 49
<artifactId>hibernate-validator</artifactId>
<version>4.3.1.Final</version>
</dependency>
http://mvnrepository.com/artifact/javax.validation/validation-api/
http://mvnrepository.com/artifact/org.hibernate/hibernate-validator
http://mvnrepository.com/artifact/org.apache.bval
Hibernate 4.3.1
( last Bean Validation 1.0
compatible version )
Dépendances Maven / BeanValidation 1.1
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.2.Final</version>
</dependency>
Hibernate 5.0.2
Bean Validation 1.1.0
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 50
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>com.sun.el</groupId>
<artifactId>el-ri</artifactId>
<version>1.0</version>
</dependency>
Hibernate 5.0.2
(R.I. for Bean Validation 1.1)
Expression Language
Liens
Tutoriel Java EE 7
http://docs.oracle.com/javaee/7/tutorial/doc/partbeanvalidation.htm
Guides de référence Hibernate Validator
https://docs.jboss.org/hibernate/validator/4.3/reference/en-US/html/
https://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html/
JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 51
Conférences et présentations
http://fr.slideshare.net/reza_rahman/whats-new-with-bean-validation-in-java-
ee-7
http://fr.slideshare.net/openwms/jsr303-bean-validation-api-3415687
FIN
1 sur 52

Recommandé

Conférence sur les annotations Java par Olivier Croisier (Zenika) au Paris JUG par
Conférence sur les annotations Java par Olivier Croisier (Zenika) au Paris JUGConférence sur les annotations Java par Olivier Croisier (Zenika) au Paris JUG
Conférence sur les annotations Java par Olivier Croisier (Zenika) au Paris JUGZenika
3.8K vues62 diapositives
Introduction à JPA (Java Persistence API ) par
Introduction à JPA  (Java Persistence API )Introduction à JPA  (Java Persistence API )
Introduction à JPA (Java Persistence API )Daniel Rene FOUOMENE PEWO
3.4K vues29 diapositives
JUnit & Mockito, first steps par
JUnit & Mockito, first stepsJUnit & Mockito, first steps
JUnit & Mockito, first stepsRenato Primavera
8.5K vues55 diapositives
Formation JPA Avancé / Hibernate gratuite par Ippon 2014 par
Formation JPA Avancé / Hibernate gratuite par Ippon 2014Formation JPA Avancé / Hibernate gratuite par Ippon 2014
Formation JPA Avancé / Hibernate gratuite par Ippon 2014Ippon
19.9K vues294 diapositives
What Is Java | Java Tutorial | Java Programming | Learn Java | Edureka par
What Is Java | Java Tutorial | Java Programming | Learn Java | EdurekaWhat Is Java | Java Tutorial | Java Programming | Learn Java | Edureka
What Is Java | Java Tutorial | Java Programming | Learn Java | EdurekaEdureka!
2.3K vues50 diapositives
Junit par
JunitJunit
JunitFAROOK Samath
6.9K vues52 diapositives

Contenu connexe

Tendances

Introduction à spring boot par
Introduction à spring bootIntroduction à spring boot
Introduction à spring bootAntoine Rey
17.8K vues19 diapositives
Langage C# par
Langage C#Langage C#
Langage C#Jean-Baptiste Vigneron
4K vues30 diapositives
Authentication and Authorization in Asp.Net par
Authentication and Authorization in Asp.NetAuthentication and Authorization in Asp.Net
Authentication and Authorization in Asp.NetShivanand Arur
12.7K vues20 diapositives
Examen 2011 exo 4 par
Examen 2011 exo 4Examen 2011 exo 4
Examen 2011 exo 4cheikhany ejiwen
3.7K vues10 diapositives
Jsf 110530152515-phpapp01 par
Jsf 110530152515-phpapp01Jsf 110530152515-phpapp01
Jsf 110530152515-phpapp01Eric Bourdet
1.2K vues175 diapositives
Exception handling par
Exception handlingException handling
Exception handlingAnna Pietras
949 vues20 diapositives

Tendances(20)

Introduction à spring boot par Antoine Rey
Introduction à spring bootIntroduction à spring boot
Introduction à spring boot
Antoine Rey17.8K vues
Authentication and Authorization in Asp.Net par Shivanand Arur
Authentication and Authorization in Asp.NetAuthentication and Authorization in Asp.Net
Authentication and Authorization in Asp.Net
Shivanand Arur12.7K vues
Jsf 110530152515-phpapp01 par Eric Bourdet
Jsf 110530152515-phpapp01Jsf 110530152515-phpapp01
Jsf 110530152515-phpapp01
Eric Bourdet1.2K vues
Java Tutorial | Java Programming Tutorial | Java Basics | Java Training | Edu... par Edureka!
Java Tutorial | Java Programming Tutorial | Java Basics | Java Training | Edu...Java Tutorial | Java Programming Tutorial | Java Basics | Java Training | Edu...
Java Tutorial | Java Programming Tutorial | Java Basics | Java Training | Edu...
Edureka!2.9K vues
Java Persistence API (JPA) Step By Step par Guo Albert
Java Persistence API (JPA) Step By StepJava Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By Step
Guo Albert29.4K vues
Microservices Security par Aditi Anand
Microservices SecurityMicroservices Security
Microservices Security
Aditi Anand150 vues
Modificateurs d'accès en java par Mohamed Bah
Modificateurs d'accès en javaModificateurs d'accès en java
Modificateurs d'accès en java
Mohamed Bah378 vues
Modern API Security with JSON Web Tokens par Jonathan LeBlanc
Modern API Security with JSON Web TokensModern API Security with JSON Web Tokens
Modern API Security with JSON Web Tokens
Jonathan LeBlanc3.7K vues
Java 8 Lambda Built-in Functional Interfaces par Ganesh Samarthyam
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
Ganesh Samarthyam3.2K vues
Hacking Jenkins par Miro Cupak
Hacking JenkinsHacking Jenkins
Hacking Jenkins
Miro Cupak1.8K vues

Similaire à Bean Validation - Cours v 1.1

Les dessous du framework spring par
Les dessous du framework springLes dessous du framework spring
Les dessous du framework springAntoine Rey
11.9K vues29 diapositives
Workshop Spring 3 - Tests et techniques avancées du conteneur Spring par
Workshop Spring  3 - Tests et techniques avancées du conteneur SpringWorkshop Spring  3 - Tests et techniques avancées du conteneur Spring
Workshop Spring 3 - Tests et techniques avancées du conteneur SpringAntoine Rey
8K vues21 diapositives
2 par
22
2Fatma Riahi
830 vues49 diapositives
Les tests en PHP par
Les tests en PHPLes tests en PHP
Les tests en PHPJean-Philippe Chateau
434 vues11 diapositives
AFUP Aix/Marseille - 16 mai 2017 - Open API par
AFUP Aix/Marseille - 16 mai 2017 - Open APIAFUP Aix/Marseille - 16 mai 2017 - Open API
AFUP Aix/Marseille - 16 mai 2017 - Open APIRomain Cambien
525 vues13 diapositives
Présentation nouveauté java7 par
Présentation nouveauté java7Présentation nouveauté java7
Présentation nouveauté java7Cynapsys It Hotspot
1.1K vues40 diapositives

Similaire à Bean Validation - Cours v 1.1(20)

Les dessous du framework spring par Antoine Rey
Les dessous du framework springLes dessous du framework spring
Les dessous du framework spring
Antoine Rey11.9K vues
Workshop Spring 3 - Tests et techniques avancées du conteneur Spring par Antoine Rey
Workshop Spring  3 - Tests et techniques avancées du conteneur SpringWorkshop Spring  3 - Tests et techniques avancées du conteneur Spring
Workshop Spring 3 - Tests et techniques avancées du conteneur Spring
Antoine Rey8K vues
AFUP Aix/Marseille - 16 mai 2017 - Open API par Romain Cambien
AFUP Aix/Marseille - 16 mai 2017 - Open APIAFUP Aix/Marseille - 16 mai 2017 - Open API
AFUP Aix/Marseille - 16 mai 2017 - Open API
Romain Cambien525 vues
Liferay france symposium 2012 - montée de version d’une instance liferay par Sébastien Le Marchand
Liferay france symposium 2012 - montée de version d’une instance liferayLiferay france symposium 2012 - montée de version d’une instance liferay
Liferay france symposium 2012 - montée de version d’une instance liferay
Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit... par fdussert
Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...
Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...
fdussert2.4K vues
Présentation de JavaServer Faces par JS Bournival
Présentation de JavaServer FacesPrésentation de JavaServer Faces
Présentation de JavaServer Faces
JS Bournival1.9K vues
Arquillian : Tester sur terre et dans les nuages par Alexis Hassler
Arquillian : Tester sur terre et dans les nuagesArquillian : Tester sur terre et dans les nuages
Arquillian : Tester sur terre et dans les nuages
Alexis Hassler1.6K vues
Concevoir, développer et sécuriser des micro-services avec Spring Boot par DNG Consulting
Concevoir, développer et sécuriser des micro-services avec Spring BootConcevoir, développer et sécuriser des micro-services avec Spring Boot
Concevoir, développer et sécuriser des micro-services avec Spring Boot
DNG Consulting2.7K vues

Plus de Laurent Guérin

Microservices-DDD-Telosys-Devoxx-FR-2022 par
Microservices-DDD-Telosys-Devoxx-FR-2022Microservices-DDD-Telosys-Devoxx-FR-2022
Microservices-DDD-Telosys-Devoxx-FR-2022Laurent Guérin
203 vues44 diapositives
My web application in 20 minutes with Telosys par
My web application in 20 minutes with Telosys My web application in 20 minutes with Telosys
My web application in 20 minutes with Telosys Laurent Guérin
353 vues21 diapositives
Telosys project booster Paris Open Source Summit 2019 par
Telosys project booster Paris Open Source Summit 2019Telosys project booster Paris Open Source Summit 2019
Telosys project booster Paris Open Source Summit 2019Laurent Guérin
5.9K vues23 diapositives
Telosys tutorial - Code generation for a Python web application based on Bott... par
Telosys tutorial - Code generation for a Python web application based on Bott...Telosys tutorial - Code generation for a Python web application based on Bott...
Telosys tutorial - Code generation for a Python web application based on Bott...Laurent Guérin
1.9K vues22 diapositives
MQTT avec Mosquitto et Paho - DevFest Brest 2019 par
MQTT avec Mosquitto et Paho - DevFest Brest 2019MQTT avec Mosquitto et Paho - DevFest Brest 2019
MQTT avec Mosquitto et Paho - DevFest Brest 2019Laurent Guérin
755 vues56 diapositives
MQTT avec Mosquitto et Paho - Laurent Guerin - JUG Nantes Nov 2018 par
MQTT avec Mosquitto et Paho - Laurent Guerin - JUG Nantes Nov 2018MQTT avec Mosquitto et Paho - Laurent Guerin - JUG Nantes Nov 2018
MQTT avec Mosquitto et Paho - Laurent Guerin - JUG Nantes Nov 2018Laurent Guérin
1.2K vues48 diapositives

Plus de Laurent Guérin(14)

Microservices-DDD-Telosys-Devoxx-FR-2022 par Laurent Guérin
Microservices-DDD-Telosys-Devoxx-FR-2022Microservices-DDD-Telosys-Devoxx-FR-2022
Microservices-DDD-Telosys-Devoxx-FR-2022
Laurent Guérin203 vues
My web application in 20 minutes with Telosys par Laurent Guérin
My web application in 20 minutes with Telosys My web application in 20 minutes with Telosys
My web application in 20 minutes with Telosys
Laurent Guérin353 vues
Telosys project booster Paris Open Source Summit 2019 par Laurent Guérin
Telosys project booster Paris Open Source Summit 2019Telosys project booster Paris Open Source Summit 2019
Telosys project booster Paris Open Source Summit 2019
Laurent Guérin5.9K vues
Telosys tutorial - Code generation for a Python web application based on Bott... par Laurent Guérin
Telosys tutorial - Code generation for a Python web application based on Bott...Telosys tutorial - Code generation for a Python web application based on Bott...
Telosys tutorial - Code generation for a Python web application based on Bott...
Laurent Guérin1.9K vues
MQTT avec Mosquitto et Paho - DevFest Brest 2019 par Laurent Guérin
MQTT avec Mosquitto et Paho - DevFest Brest 2019MQTT avec Mosquitto et Paho - DevFest Brest 2019
MQTT avec Mosquitto et Paho - DevFest Brest 2019
Laurent Guérin755 vues
MQTT avec Mosquitto et Paho - Laurent Guerin - JUG Nantes Nov 2018 par Laurent Guérin
MQTT avec Mosquitto et Paho - Laurent Guerin - JUG Nantes Nov 2018MQTT avec Mosquitto et Paho - Laurent Guerin - JUG Nantes Nov 2018
MQTT avec Mosquitto et Paho - Laurent Guerin - JUG Nantes Nov 2018
Laurent Guérin1.2K vues
Meetup python-bottle-telosys-2018-lgu-v1.0 par Laurent Guérin
Meetup python-bottle-telosys-2018-lgu-v1.0Meetup python-bottle-telosys-2018-lgu-v1.0
Meetup python-bottle-telosys-2018-lgu-v1.0
Laurent Guérin520 vues
DevOps MeetUp NL - Docker (Oct 2014) par Laurent Guérin
DevOps MeetUp NL - Docker (Oct 2014)DevOps MeetUp NL - Docker (Oct 2014)
DevOps MeetUp NL - Docker (Oct 2014)
Laurent Guérin2.3K vues
Devoxx 2011 - Scaffolding with Telosys par Laurent Guérin
Devoxx 2011 - Scaffolding with TelosysDevoxx 2011 - Scaffolding with Telosys
Devoxx 2011 - Scaffolding with Telosys
Laurent Guérin1.7K vues
Open World Forum 2009 Migration With Telosys par Laurent Guérin
Open World Forum 2009 Migration With TelosysOpen World Forum 2009 Migration With Telosys
Open World Forum 2009 Migration With Telosys
Laurent Guérin1K vues
Solutions Linux Développement Rapide Java par Laurent Guérin
Solutions Linux Développement Rapide JavaSolutions Linux Développement Rapide Java
Solutions Linux Développement Rapide Java
Laurent Guérin1K vues

Bean Validation - Cours v 1.1

  • 1. Java Bean Validation API Université de Nantes & Ecole des Mines de Nantes Laurent Guérin / V 1.1 / Janvier 2014 @ltguerin
  • 3. Introduction La validation des données est indispensable dans toute application. Elle peut intervenir à différents niveaux : Couche de présentation (informations saisies par l’utilisateur) Couche métier JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 3 Couche de persistance (conformité avec les contraintes définies dans la base de données, … ) Etc… Bean Validation propose un framework normalisé (spécification Java, JSR,… ) pour valider les informations portées par les Java Beans (et les paramètres de méthodes dans la version 1.1)
  • 4. Introduction Les contraintes/rêgles de validation sont définies dans le code source du bean à valider. Elles sont exprimées par des « annotations » qui peuvent être appliquées à différents niveaux : Attribut Méthode (getter/setter) JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 4 Méthode (getter/setter) Classe Elles peuvent aussi être définies dans un fichier XML Un objet « validator » va ensuite vérifier que toutes les contraintes du bean sont respectées Il est possible d’étendre le framework en créant des contraintes personnalisées
  • 5. Exemples public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) private String licensePlate; @Min(2) private int seatCount; ... public class Person { @Min(1) private int id ; JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 5 ... } @NotNull @Size(min=1, max=30) private String name ; @Min(0) private int age ; @NotNull @DecimalMin("1500.00") @DecimalMax("99999.99") private BigDecimal salary ; ... }
  • 7. Bean Validation version 1.0 Spécification lancée en 2006 et finalisée en 2009 JSR-303 cf : https://jcp.org/en/jsr/detail?id=303 Fait partie de Java EE 6 Cf : http://docs.oracle.com/javaee/6/tutorial/doc/ Utilisé notamment pour les validation dans JSF ( Java JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 7 Utilisé notamment pour les validation dans JSF ( Java Server Faces ) Packages « javax.validation.* »
  • 8. Spécification et implémentations Bean Validation 1.0 Specification API JSR 303 Application Java EE 6 JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 8 Hibernate Validator Apache Bean Validation Implémentations ( R.I. ) http://bval.apache.org/http://hibernate.org/validator/
  • 9. Les annotations de la JSR-303 Annotation Applicable aux types… @Null @NotNull Object @Min @Max BigDecimal, BigInteger, byte, short, int, long (+ Wrappers) @DecimalMin @DecimalMax BigDecimal, BigInteger, String byte, short, int, long (+ Wrappers) JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 9 byte, short, int, long (+ Wrappers) @Size String, Collection, Map, Array @Digits BigDecimal, BigInteger, String byte, short, int, long (+ Wrappers) @Past @Future java.util.Date, java.util.Calendar @Pattern String @AssertTrue @AssertFalse Boolean, boolean
  • 10. Exemples @NotNull String username; @Null String unusedString; @AssertTrue boolean isActive; @AssertFalse boolean isUnsupported; Objets ( vérification Null / Not Null ) Booléens ( vérification True/False ) JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 10 boolean isActive; boolean isUnsupported; @Size(min=2, max=240) String message; @Size(min=12) String name; Taille ( vérification mini/maxi ) @Size(min=1, max=10) List<Element> elements; @Size(max=100) LinkedList<String> words;
  • 11. Exemples @Past Date dateNaissance; @Future Date nextMeeting; Dates ( vérification date du passé ou du futur ) Nombres ( vérification valeur mini/maxi ) @Min(0) @Max(140) private int age ; @DecimalMin("5.00") @DecimalMax("30.00") BigDecimal discount; JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 11 @Digits(integer=6, fraction=2) BigDecimal price; // 'integer' : maximum integral digits for the number // 'fraction' : maximum fractional digits for the number @Pattern(regexp="(d{3})d{3}-d{4}") String phoneNumber; Chaînes de caractères ( vérification / expression régulière ) Nombres décimaux ( vérification « xxxx.xx »)
  • 12. @NotEmpty // Ni null, ni vide String firstName; @NotBlank // Ni null, ni composé de “blancs” Contraintes spécifiques Hibernate NB : L’implémentation Hibernate Validator fournit des annotations supplémentaires qui ne font pas partie de la spécification officielle. Cf package « org.hibernate.validator.constraints » Exemples : NB : L’utilisation de ces annotations induit une adhérence JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 12 @NotBlank // Ni null, ni composé de “blancs” String lastName; @Email String email ; @CreditCardNumber // N° de carte de crédit (Luhn checksum) @Length(min=2, max=12) // Longueur entre min et max @ModCheck // “Mod 10” ou “Mod 11” checksum algorithm @Range(min=2, max=12) // Valeur entre min et max @SafeHtml(whitelistType=, additionalTags=) // => librairie Jsoup @ScriptAssert(lang=, script=, alias=) @URL(protocol=, host=, port=,...) // URL valide induit une adhérence à Hibernate !
  • 13. Remarques @Min(1) @DecimalMin("0.2") int value; Toutes les contraintes sont évaluées, même si elles sont incohérentes ou contradictoires Si value=0 : 2 violations détectées @Min(3) @Max(2) int value; Toujours 1 violation détectée JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 13 Si une contrainte n’est pas applicable au type Exception @Past // Pour une date int value; javax.validation.UnexpectedTypeException No validator could be found for type: xxxxx@Pattern(regexp=".+@.+.[a-z]+") int value;
  • 14. Validation d’un graphe d’objets public class Car { @NotNull @Valid private Person driver; Lorsque des objets sont imbriqués, il faut utiliser l’annotation @Valid pour valider l’objet référencé public class Person { @Min(1) « driver » ne doit pas être « null » et l’instance de Person doit être « valid » JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 14 private Person driver; public Car(Person driver) { this.driver = driver; } //getters & setters ... } @Min(1) private int id; @NotNull private String name; //getters & setters ... } @NotNull @Valid private List<Person> passengers = new ArrayList<Person>(); Egalement applicable pour les collections
  • 16. Objet « Validator » Les annotations (@NotNull, @Size, etc) ne font que déclarer des contraintes Ces contraintes sont vérifiées par un moteur de validation : un objet qui implémente l’interface « Validator » JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 16 Ce « Validator » est généralement embarqué dans l’environnement d’exécution, il est utilisé pour valider les beans au moment opportun
  • 17. Objet « Validator » Validator est utilisé par Les « containers » ou les « frameworks » qui gèrent le cycle de vie des objets Les environnements capables d’intercepter des appels de méthodes (AOP, … ) et donc de déclencher une validation lors de l’invocation d’une méthode JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 17
  • 18. Objet « Validator » Pour tester unitairement la validation des beans, il faut récupérer une instance de « Validator » et invoquer ses méthodes de validation. Le « Validator » est fabriqué par « ValidatorFactory ». ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory() ; Validator validator = validatorFactory.getValidator(); JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 18 L’appel de la méthode « validate » renvoie une liste de « ConstraintViolation »: Validator validator = validatorFactory.getValidator(); //--- Création et initialisation du bean Author author = new Author(); author.setId(1); //--- Validation du bean Set<ConstraintViolation<Author>> constraintViolations = validator.validate(author);
  • 19. Objet « Validator » Il est possible de ne valider que certaines propriétés d’un bean avec validateProperty(…) //--- Création et initialisation du bean Author author = new Author(); author.setId(1); //--- Validation des propriétés du bean Set<ConstraintViolation<Author>> errors ; errors = validator.validateProperty( author, "id" ); JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 19 errors = validator.validateProperty( author, "id" ); errors = validator.validateProperty( author, "firstName" ); //--- Contraintes définies dans une classe BeanDescriptor desc = validator.getConstraintsForClass(Author.class) Récupération de la description des contraintes d’une classe : //--- Si la valeur de l’attribut était... validator.validateValue( Author.class, "firstName", "Foo" ) Situation de test pour une valeur d’une propriété (attribut) :
  • 20. Exemple JUnit public class AuthorValidTest { private final static Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); @Test public void testAuthor() { Author author = new Author(); author.setId(1); Set<ConstraintViolation<Author>> constraintViolations = JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 20 Set<ConstraintViolation<Author>> constraintViolations = validator.validate(author); print (constraintViolations); } private <T> void print( Set<ConstraintViolation<T>> errors ) { for ( ConstraintViolation<T> cv : errors ) { System.out.println(" . " + cv.getPropertyPath() + " (in " + cv.getRootBeanClass().getSimpleName() + ") " + cv.getMessage() ); } }
  • 22. Messages d’erreurs Toutes les contraintes prédéfinies ont un message par défaut disponible dans plusieurs langues. Par exemple, Hibernate Validator affiche des messages en français ou en anglais. Chaque contrainte est identifiée par une « clé ». A cette clé est associé un message (Java properties) JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 22 A cette clé est associé un message (Java properties) Le message par défaut peut être forcé pour chaque utilisation d’une annotation. Exemple : @NotNull(message = "Le nom ne doit pas être null" ) String nom; @Min(value=0, message= "L’age ne peut pas être < 0" ) int age;
  • 23. Messages d’erreurs Les valeurs de l’annotation peuvent être insérées dans le message en utilisant la notation {variable} Exemple : Les messages par défaut sont définis dans le fichier @Min(value=0, message="L’age doit être au minimum {value} " ) int age; JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 23 Les messages par défaut sont définis dans le fichier « ValidationMessages.properties ». Ce fichier est utilisé par « MessageInterpolator » (interface) qui va rechercher le fichier des messages 1) à la racine du ClassPath 2) dans le JAR de l’implémentation ( ex « org.hibernate.validator » pour Hibernate Validator )
  • 24. Messages d’erreurs Extrait du fichier des messages d’Hibernate Validator javax.validation.constraints.AssertFalse.message = must be false javax.validation.constraints.AssertTrue.message = must be true javax.validation.constraints.DecimalMax.message = must be less than or equal to {value} javax.validation.constraints.DecimalMin.message = must be greater than or equal to {value} javax.validation.constraints.Digits.message = Fichier ValidationMessages.properties JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 24 javax.validation.constraints.Digits.message = numeric value out of bounds (<{integer} digits>.<{fraction} digits> expected) javax.validation.constraints.Future.message = must be in the future javax.validation.constraints.Max.message = must be less than or equal to {value} javax.validation.constraints.Min.message = must be greater than or equal to {value} javax.validation.constraints.Past.message = must be in the past javax.validation.constraints.Pattern.message = must match "{regexp}" javax.validation.constraints.Size.message = size must be between {min} and {max}
  • 26. Contraintes spécifiques Certaines règles de validation nécessitent de définir des contraintes spécifiques ( « custom constraints » ). Elles peuvent être positionnées à différents niveaux Champ (attribut ) « field-level constraint » Classe « class-level constraint » JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 26 Classe « class-level constraint » (validation globale d’une instance) Pour créer une « custom constraint » il faut … 1) créer l’ annotation qui définit la contrainte 2) créer le « validator » qui va vérifier la contrainte 3) définir un message d’erreur par défaut
  • 27. Custom Constraint 1 : « field level » Exemple 1 : création d’une contrainte qui vérifie qu’une chaîne de caractères est bien en « upper case » ou « lower case »… => « field-level » JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 27 @CheckCase(value=CaseMode.LOWER) private String firstName; @CheckCase(value=CaseMode.UPPER) private String lastName; Utilisation attendue :
  • 28. Custom Constraint 1 - Annotation public enum CaseMode { UPPER, LOWER; } @Target( { METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = CheckCaseValidator.class) @Documented JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 28 @Documented public @interface CheckCase { String message() default "{org.demo.constraints.checkcase}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; CaseMode value(); } Clé dans le fichier des messages
  • 29. Custom Constraint 1 - Validator public class CheckCaseValidator implements ConstraintValidator<CheckCase, String> { private CaseMode caseMode; @Override public void initialize( CheckCase constraintAnnotation ) { this.caseMode = constraintAnnotation.value(); // MAJUS/MINUS } Valide des instances de « String » Contrainte « CheckCase » JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 29 @Override public boolean isValid(String object, // objet à valider ConstraintValidatorContext constraintContext) { if (object == null) return true; // considéré comme valide if (caseMode == CaseMode.UPPER) // test MAJUS. ou MINUS. return object.equals(object.toUpperCase()); else return object.equals(object.toLowerCase()); } }
  • 30. Custom Constraint 1 - Message org.demo.constraints.checkcase = Invalid case, must be {value} Fichier « ValidationMessages.properties » situé à la racine du ClassPath Pour gérer l’internationalisation des messages et avoir par exemple des messages en français, JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 30 exemple des messages en français, créer un fichier « ValidationMessages_fr.properties » org.demo.constraints.checkcase = Controle MINUSCULE/MAJUSCULE invalide
  • 31. Custom Constraint 2 : « class level » Exemple 2 : création d’une contrainte qui vérifie la validité d’une instance de la classe « Person » => « class-level » Utilisation attendue : JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 31 @PersonValidation // Class-level validation public class Person implements Serializable { private static final long serialVersionUID = 1L; private int id; private String firstName; private String lastName; [...] } Utilisation attendue :
  • 32. Custom Constraint 2 - Annotation @Documented @Constraint(validatedBy = PersonValidator.class) @Target({ElementType.TYPE}) // Annotation for a CLASS @Retention(RetentionPolicy.RUNTIME) public @interface PersonValidation { String message() default "{org.demo.constraints.person}"; JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 32 Class<?>[] groups() default {}; Class<?>[] payload() default {}; // Pas d’autre info (pas de "value") }
  • 33. Custom Constraint 2 - Validator public class PersonValidator implements ConstraintValidator<PersonValidation, Person> { @Override public void initialize(PersonValidation constraint) { // Rien à faire ici } @Override Valide des instances de « Person » Validation de la contrainte « PersonValidation » JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 33 @Override public boolean isValid( Person person, ConstraintValidatorContext context) { // Validation des différens champs de l’instance if ( person.getId() < 1 ) return false ; if ( person.getId() > 99999 ) return false ; if ( person.getFirstName() == null ) return false ; if ( person.getFirstName().length() < 1 ) return false ; // etc... return true; }
  • 35. Bean Validation version 1.1 Spécification approuvée début 2013 JSR-349 cf : https://jcp.org/en/jsr/detail?id=349 Fait partie de Java EE 7 Cf : JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 35 Cf : https://blogs.oracle.com/theaquarium/entry/java_ee_7_pla tform_completes Implémentation de référence : « Hibernate Validator » Cf http://hibernate.org/validator/
  • 36. JSR-349 : Quoi de neuf ? Meilleure intégration avec : JPA CDI JAX-RS JSF 2 nouveaux packages JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 36 2 nouveaux packages avec notamment la classe « ValidateOnExecution » Validation des paramètres d’une méthode Utilisation de « EL » pour les messages Les annotations servant à définir les contraintes sont les mêmes qu’en JSR-303 (pas de changement)
  • 37. Validation lors de l’appel de méthodes public class MyBean { private String name; Les annotations peuvent aussi être utilisées pour contrôler la validité des paramètres passés à des méthodes ou des constructeurs, ainsi que les valeurs renvoyées. Exemples : JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 37 public MyBean( @NotNull String name ) { this.name = name; } @Size(min = 3) public String updateName( @NotNull @Size(min = 1) String firstName, @NotNull @Size(min = 1) String lastName) { name = firstName + " " + lastName; return name; } }
  • 38. Validation lors de l’appel de méthodes // Valider les paramètres simples d’une méthode public User createUser ( @NotNull String name, @Past Date birthDate ) { ... } // Valider des paramètres de type “bean” (objet spécifique) Exemples : JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 38 // Valider des paramètres de type “bean” (objet spécifique) public Order createOrder (..., @Valid User user) { ... } // Valider le “résultat” (retour) d’une méthode @NotNull public Employee getEmployee() { // Ne doit pas renvoyer null ... }
  • 39. Annotation « @ValidateOnExecution » Permet d’indiquer quelles méthodes doivent être validées lors de l’exécution (méthodes ou constructeurs). Elle peut être placée au niveau de la classe et/ou au niveau des méthodes/constructeurs Si l’annotation @ValidateOnExecution est présente elle définit explicitement les règles de validation à appliquer JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 39 elle définit explicitement les règles de validation à appliquer (quelles méthodes, quels types de méthodes, ...) Si elle n’est pas présente, c’est la configuration de « bean validation » qui s’applique. La configuration est définie à partir … • du fichier « META-INF/validation.xml » s’il existe • de la configuration par défaut (cf JavaDoc) ALL, CONSTRUCTORS, GETTER_METHODS, NON_GETTER_METHODS, IMPLICIT, NONE
  • 40. Validation des appels de méthodes Principe de fonctionnement : JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 40
  • 41. Exemples public class OrderService { boolean isValidCustomer( @NotNull String customerCode) { [...] } @ValidateOnExecution @Min(0) Dans un service avec « @ValidateOnExecution » JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 41 @Min(0) Integer getBacklog() { [...] } @ValidateOnExecution(type=NONE) Order placeOrder( @NotNull String customerCode, @Valid Item item, int quantity) { [...] } }
  • 42. Utilisation dans Java EE et dans les frameworks Java
  • 43. Adoption de la JSR-303 Bean Validation est utilisé dans Certains composants standards de Java EE (de + en +), par exemple : JSF (JavaServer Faces) – Web Jersey (RI de JAX-RS) – REST JPA – Persistance JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 43 Et dans de nombreux frameworks Java, notamment : Spring MVC Wicket Tapestry
  • 44. Bean Validation / JPA Author author = new Author() ; author.setId(1); author.setFirstName("Joe"); public class Author { @Min(1) @Max(99999) private int id; @NotNull @Size(min=1, max=20 ) private String firstName; [...] } JPA valide le Bean lors de l’invocation des méthodes de persistance Si bean invalide Exception JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 44 author.setFirstName("Joe"); EntityManager em = .. ; try { em.persist(author); // Validation du bean par JPA } catch (ConstraintViolationException exception) { Set<ConstraintViolation<?>> constraintsViolations = exception.getConstraintViolations(); int n = constraintsViolations.size(); }
  • 45. Bean Validation / Jersey (REST / JAX-RS ) @Path("/") class MyResourceClass { @POST @Consumes("application/x-www-form-urlencoded") public void registerUser( @NotNull @FormParam("firstName") String firstName, @NotNull @FormParam("lastName") String lastName, @Email @FormParam("email") String email) { ... } } JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 45 @Path("/") class MyResourceClass { @Email @ValidateOnExecution public String getEmail() { return email; } } } @Path("/") class MyResourceClass { @POST @Consumes("application/xml") public void registerUser( @Valid User user) { ... } }
  • 46. Bean Validation / Spring MVC Depuis la version 3.0 Spring MVC supporte intégralement la JSR-303 Exemples : import javax.validation.Validator ; @Service public class MyService { @Autowired Injection d’un « Validator » dans un service JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 46 @Controller public class MyController { @RequestMapping("/foo", method=RequestMethod.POST) public void processFoo( @Valid Foo foo ) {...} @Autowired private Validator validator; Validation des données d’un formulaire dans « Controller »
  • 47. Bean Validation / Wicket Par ajout d’un « JSR303FormValidator » public class HomePage extends WebPage { public HomePage(final PageParameters parameters) { Person person = new Person(); final Form<Person> personForm = new Form<Person>("personForm", new CompoundPropertyModel<Person>(person) ); personForm.add(new TextField<String>("firstName")); personForm.add(new TextField<String>("lastName")); personForm.add(new TextField<Integer>("age")); personForm.add(new Button("submit") { JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 47 personForm.add(new Button("submit") { @Override public void onSubmit() { personForm.info("Submitted " + personForm.getDefaultModelObjectAsString()); } }); personForm.add( new JSR303FormValidator() ); add(personForm); add(new FeedbackPanel("feedback")); } } Nécessite un « CompoundPropertyModel » pour l’accès aux propriétés du bean par réflexion
  • 49. Dépendances Maven / BeanValidation 1.0 <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> Bean Validation 1.0.0 JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 49 <artifactId>hibernate-validator</artifactId> <version>4.3.1.Final</version> </dependency> http://mvnrepository.com/artifact/javax.validation/validation-api/ http://mvnrepository.com/artifact/org.hibernate/hibernate-validator http://mvnrepository.com/artifact/org.apache.bval Hibernate 4.3.1 ( last Bean Validation 1.0 compatible version )
  • 50. Dépendances Maven / BeanValidation 1.1 <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.0.2.Final</version> </dependency> Hibernate 5.0.2 Bean Validation 1.1.0 JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 50 </dependency> <dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>2.2.4</version> </dependency> <dependency> <groupId>com.sun.el</groupId> <artifactId>el-ri</artifactId> <version>1.0</version> </dependency> Hibernate 5.0.2 (R.I. for Bean Validation 1.1) Expression Language
  • 51. Liens Tutoriel Java EE 7 http://docs.oracle.com/javaee/7/tutorial/doc/partbeanvalidation.htm Guides de référence Hibernate Validator https://docs.jboss.org/hibernate/validator/4.3/reference/en-US/html/ https://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html/ JAVA – Bean Validation API ( Laurent Guérin / v 1.1 / www.laurent-guerin.fr ) 51 Conférences et présentations http://fr.slideshare.net/reza_rahman/whats-new-with-bean-validation-in-java- ee-7 http://fr.slideshare.net/openwms/jsr303-bean-validation-api-3415687
  • 52. FIN