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èresEn 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".