La validation de données est un travail nécessaire et critique mais bien souvent rébarbatif, du fait notamment de la duplication des règles (bases de données, server-side, client-side). L'arrivée de la JSR-303 Bean Validation, emmenée par Emmanuel Bernard, apporte une standardisation bienvenue à cette problématique incontournable de toute application de gestion. Nous vous proposons donc une solution pour Wicket en intégrant cette JSR !
L'intégration est livrée sur GoogleCode dans le projet wicket-jsr303-validators. Des tests unitaires couvrant un bon nombre de cas sont fournis, mais si vous constatez que certains de vos use-cases spécifiques ne sont pas supportés, n'hésitez pas à nous en faire part sur le bugtracker, le but étant de contribuer ce code s'il prouve son utilité.
Qu'est-ce que la JSR 303 Bean Validation ?
La spécification JSR-303 fournit une API ainsi qu'un modèle de méta-données, permettant la validation des JavaBeans. Ces méta-données de validation s'appliquent une fois pour toute sous forme d'annotations sur les propriétés d'un bean métier. Ainsi, ce même modèle est utilisable par toutes les couches d'une application ce qui facilite grandement le travail et réduit la redondance de code.
Que contient la librairie Wicket JSR-303 Validators ?
La librairie Wicket JSR-303 Validators s'appuie sur l'API de la JSR-303, afin de fournir une validation simplifiée des données reçues via un formulaire. Elle est compatible Java >= 1.5 et Wicket >= 1.4.
Cette validation est disponible via deux Validateurs :
BeanPropertyValidatorimplémenteIValidator. S'ajoute à un FormComponent de typetext. Il permet de valider une propriété annotée avec des méta-données de validation.JSR303FormValidatorimplémenteIFormValidator. Peut être ajouté à un objetFormafin de valider tout sesFormComponents. Le validateur sous-jacent étant unBeanPropertyValidator.
Attention, pour le moment ces validateurs ne supportent que les formulaires dont le modèle est un CompoundPropertyModel, nous verrons pourquoi dans les exemples qui suivent.
La librairie supporte :
- Validation sur tout le formulaire ou des composants seuls
- Validation des annotations placées sur les champs d'un JavaBean
- Les annotations héritées des super classes et interfaces
- Validation de graphe d'objets avec l'annotation
@Valid - Validation par Group et séquences de validation avec l'annotation
@GroupSequence
Bientôt supporté :
- Validation avec les annotations appliquées sur les accesseurs ?
- La customisation des messages d'erreurs (custom message interpolator ?), resource bundle wicket
- Ajout de la validation côté client avec la librairie javascript Yav
- Class level validation ?
- Autres modèles que AbstractPropertyModel
- Autres composants de formulaire que AbstractTextComponent ?
Exemple(s) d'utilisation
Voyons dès à présent comment utiliser cette librairie dans un projet concret. Nous avons bien évidemment besoin de la librairie Wicket-JSR303-Validators. Après l'avoir téléchargée à partir du GoogleCode, vous pouvez l'installer dans votre repository maven à l'aide de cette commande :
$ mvn install:install-file -Dfile=/chemin/vers/wicket-jsr303-validators-1.0-SNAPSHOT.jar \
-DgroupId=com.zenika.wicket.contrib \
-DartifactId=wicket-jsr303-validators \
-Dversion=1.0-SNAPSHOT -Dpackaging=jar
Ajoutons les dépendances nécessaires dans notre pom :
- La librairie Wicket JSR303 Validators
- Une implémentation de la JSR-303, nous avons choisi ici l'implémentation de référence Hibernate Validator 4.0
<dependency> <groupId>com.zenika.wicket.contrib</groupId> <artifactId>wicket-jsr303-validators</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.0.2.GA</version> </dependency>
L'API javax.validation (JSR-303) n'est pour le moment pas disponible sur le repository maven par défaut. On peut en revanche la récupérer à partir du repository JBoss, tout comme son implémentation hibernate-validator.
<repository> <id>repository.jboss.org</id> <name>JBoss Maven Repository</name> <url>http://repository.jboss.com/maven2/</url> </repository>
La validation aura lieu uniquement sur des propriétés de JavaBean annotées avec les contraintes fournies par la JSR303. Voici un exemple d'objet métier que nous pouvons utiliser.
public class Person implements Serializable { private static final long serialVersionUID = 1L; @Min(value = 18) private int age; @Size(min = 2, max = 255) private String firstName; @NotNull @Size(min = 2, max = 255) private String lastName; public int getAge() { return age; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public void setAge(int age) { this.age = age; } public void setFirstName(String firstName) { this.firstName = firstName; } public void setLastName(String lastName) { this.lastName = lastName; } @Override public String toString() { return "Person [age=" + age + ", firstName=" + firstName + ", lastName=" + lastName + "]"; } }
Les annotations que nous avons placées s'expliquent d'elles-mêmes.
Voyons maintenant comment ajouter la validation correspondante du côté de wicket.
public class HomePage extends WebPage { private static final long serialVersionUID = 1L; private static final Logger LOG = LoggerFactory.getLogger(HomePage.class); /** * Constructor that is invoked when page is invoked without a session. * * @param parameters * Page parameters */ 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") { private static final long serialVersionUID = 1L; @Override public void onSubmit() { LOG.info("Submitted " + personForm.getDefaultModelObjectAsString()); personForm.info("Submitted " + personForm.getDefaultModelObjectAsString()); } }); personForm.add(new JSR303FormValidator()); add(personForm); add(new FeedbackPanel("feedback")); } }
Notre page fournit un formulaire d'ajout d'objets Person. Il suffit simplement d'ajouter à ce dernier un JSR303FormValidator pour que la validation correspondant aux annotations vues précédemment s'opère.
Attention, nous avons besoin d'un CompoundPropertyModel pour notre formulaire. En effet, ceci est nécessaire pour l'API de la JSR-303 qui gère l'accès aux propriétés du bean grâce à la reflection.
N'oubliez pas d'ajouter un FeedbackPanel qui permet de fournir des explications sur les erreurs de soumission du formulaire à votre utilisateur.
Voici le markup associé à cette page :
<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" > <head> <title>Wicket JSR303 Validators</title> </head> <body> <strong>Person Form</strong> <br/><br/> <form wicket:id="personForm"> <label>First Name : </label> <input type="text" wicket:id="firstName" /><br /> <label>Last Name : </label> <input type="text" wicket:id="lastName" /><br /> <label>Age : </label> <input type="text" wicket:id="age" /><br /> <input type="submit" wicket:id="submit" /> </form> <div wicket:id="feedback"></div> </body> </html>
Nous pouvons maintenant tester maintenant le formulaire :
$ mvn jetty:run
Conclusion
Comme précisé précédemment, n'hésitez pas à nous adresser tout retour sur le suivi.


Commentaires
Bonjour,
J'aimerai savoir si une version release de cette librairie est prévue et si le support (correction des éventuels bugs) et toujours d'actualité car le projet à l'air à l'arrêt pour le moment (cf activité sur http://code.google.com/p/wicket-jsr...)
Merci d'avance pour votre réponse.
Tom