Créer une annotation et un validateur dans Spring

Personnaliser la gestion de validations

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

JSR-303 et Hibernate ne fournissent que les validateurs universels. Ils trouveront leur place dans la plupart de cas où il faut vérifier une chaîne de caractères ou un chiffre. Cependant, certaines situations peuvent nécessiter la vérification plus spécifique au domaine d'activité du système développé.

Dans cette partie on concevra notre propre validateur qui utilisera une annotation. On pourra la placer au niveau d'une classe pour vérifier si deux champs sont égaux.

Créer une annotation et un validateur sous Spring

Parfois il arrivent des situations où on doit nécessairement implémenter une validation spéciale qui ne se trouve pas dans les packages fournis (ni dans Hibernate, ni dans JSR-303). Dans ces cas-là on doit créer nos propres validateurs, composés d'une annotation et d'une classe qui implémente javax.validation.ConstraintValidator.

On remarque l'utilisation d'une telle validation dans la situation de vérification si les deux mots de passes introduits par un utilisateurs sont égaux. Dans le but de s'assurer que c'est bien le cas, on concevra l'annotation @IsEqualLocally avec un validateur IsEqualLocallyValidator. Regardons d'abord l'élément de la classe Subscriber qui nécessite une telle spécialité :

@Entity
@Table(name = "subscriber")
@IsEqualLocally(firstValue = "password", secondValue = "passwordRepeated",  message = "Both passwords must be equal", groups = {SubscriberRegisterCheck.class, SubscriberPasswordCheck.class})
// ...
public class Subscriber extends ParentEntity implements Serializable {
    // ...
}

On remarque immédiatement que l'annotation en question ne se trouve plus avant le getter pour la valeur qui nous intéresse. Elle est désormais placée avant la déclaration de la classe. C'est le seul moyen pour pouvoir récupérer les valeurs des attributs spécifiés dans les paramètres firstValue et secondValue.

Maintenant, quand on a découvert la spécificité du problème, on va passer à l'annotation et son validateur :

afficher le code

L'interface de validation contient deux champs String qui déterminent quelles propriétés d'un objet doivent être comparées. Elle ne fait rien d'autre. Contrairement à IsEqualLocallyValidator qui exécute toute la logique de vérification.

Tout d'abord il initialise le contexte d'exécution en attribuant des valeurs passées dans l'annotation à ses attributs non définis (firstValue et secondValue).

Ensuite il passe à la méthode isValid() qui, comme son nom indique, vérifie la cohérence des données. Elle retourne true si aucune erreur n'est trouvée. Dans le cas contraire, false est retourné. Pour valider les deux valeurs qui peuvent être issues des classes différentes, on emploie BeanUtils faisant partie du projet Apache Commons BeanUtils. Il permet de retrouver les valeurs des propriétés d'une classe. Cette dernière est dans notre cas représentée par le premier paramètre passé à la méthode isValid - Object value.

Après une telle implémentation, le développeur n'a plus rien à faire. Sa spécification est automatiquement exécutée par Spring, soit via l'annotation @Valid, soit via @Validated.

Bartosz KONIECZNY Validation

Une question ? Une remarque ?

*

*

Un conseil Symfony1

Comment appeler un helper dans l'action ?

L'une des méthodes pour utiliser un view helper dans l'action est: sfProjectConfiguration::getActive()->loadHelpers(array("mon_helper")); mon_helper();