Messages d'erreur

Affichage des erreurs de validation dans Spring

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

Moyen le plus simple de gestion des messages d'erreur consiste à les mettre dans le code ou dans un fichier externe. Cependant, cette approche est inadaptée à la situation où l'on doit afficher les messages différents en fonction de la langue de l'utilisateur. Dans cet article on configurera un bean validator, dont le but sera, entre autres, de nous faciliter la gestion des messages d'erreur en fonction de la préférence de l'utilisateur.

Regardons d'abord comment notre fichier de contexte a changé :

<mvc:annotation-driven validator="validator" />

<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource">
  <property name="basenames">
    <list>
        <value>/WEB-INF/i18n/ValidationMessages</value>
        <value>/WEB-INF/i18n/messages</value>
        <value>/WEB-INF/i18n/application</value>
    </list>
  </property>
  <property name="defaultEncoding" value="UTF-8"/>
  <property name="fallbackToSystemLocale" value="false"/>
</bean>

<!-- Configure JSR-303 validation --> 
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
  <property name="validationMessageSource" ref="messageSource"/>
</bean>
On commence par le bas. Le bean dont l'identifiant est validator, doit nous permettre à gérer la validation JSR-303. Une propriété y est spécifiée : validationMessageSource. Il s'agit de l'implémentation de l'interface org.springframework.context.MessageSource qui va se charger de retourner les messages d'erreur traduits. Si cette propriété n'est pas renseignée, Spring va chercher le fichier ValidationMessages.properties placé dans le classpath de l'application. Concernant cette implémentation du MessageSource, elle se trouve dans le bean identifié par messageSource. Son rôle consiste à accéder à des fichiers de messages dynamiquement, en fonction de la Locale de l'application. On aborde ce fragment plus en détail dans l'article consacré à l'i18n dans Spring. Le troisième fragment est là pour indiquer à Spring d'utiliser un validateur dans son modèle MVC. Grâce à lui, Spring sait quel validateur doit être utilisé pour les annotations @Valid ou @Validated. Il s'agit ici d'une configuration globale, qui s'applique à tous les contrôleurs (annotés avec @Controller). Regardons maintenant comment a changé notre code qui gère désormais la traduction des messages d'erreur :
public class Subscriber extends ParentEntity implements Serializable {

    @NotEmpty(message = "{error.login.empty}", groups = SubscriberRegisterCheck.class)
    @Size(min = 1, max = 20, message = "{error.login.length}", groups = SubscriberRegisterCheck.class)
    @Pattern(regexp = "([A-Za-z0-9]+)", message = "{error.login.char}", groups = SubscriberRegisterCheck.class)
    @UniqueRecordDb(column = "login", query = "SELECT s FROM Subscriber s WHERE login = :login", parameter = "login", message = "{error.login.used}", groups = SubscriberRegisterCheck.class)
    @Column(name = "login_su")
    public String getLogin() {
        return login;
    }
    // ...
}
Les codes d'erreur sont donc spécifiés entre crochets ({}). Leur représentation dans le fichier est la suivante :
error.login.empty = Le login ne peut pas être vide
error.login.used = Ce login est déjà utilisé par un autre utilisateur
error.login.char = Le login peut être composé uniquement de chiffres et de lettres
error.login.length = Le login doit avoir entre {min} et {max} caractères
En ce qui concerne les messages retournés par un validateur personnalisé, les codes ne doivent pas être compris entre crochets, comme le montre cet exemple :
public class BookFormValidator implements Validator  {

    public void validate(Object obj, Errors errors) {
        BookForm bookForm = (BookForm) obj;
        
        if (bookForm.getCategoriesChecked() == null || bookForm.getCategoriesChecked().size() == 0) {
            errors.rejectValue("categoriesChecked", "error.book.categoriesEmpty", "Check at least one category");
        }
        // ...
    }
}

En ce qui concerne le contenu des messages, il faut faire très attention à des apostrophes. Ils sont utilisés pour échapper les crochets. Si l'on écrit par exemple "Mon texte '{crochet'}", on verra sur l'écran "Mon texte crochet". Pareil si l'on spécifie le message "L'adresse est incorrecte". On verra alors "Ladresse est incorrecte". Pour pouvoir afficher le message correcte, il faut échapper l'apostrophe à son tour, comme suit : "L\''adresse est incorrecte".

Bartosz KONIECZNY Validation

Une question ? Une remarque ?

*

*

Un conseil JavaScript

Comment supprimer un élément du tableau JavaScript ?

PHP a sa méthode unset() pour supprimer un élément du tableau. JavaScript n'est guère plus compliqué. Pour supprimer n'importe quel élément il suffit d'utiliser l'opérateur delete :

delete myArray[key];
On peut également utiliser la méthode pop() qui va automatiquement supprimer le dernier élément de notre Array(). On peut également enlever le premier élément du tableau en utilisant shift().