Spring MVC – Formulaires et validations (par la norme JSR 303 – Bean Validation)

Cette article traite des formulaires et de leurs validations dans Spring MVC.
Pour ce faire, nous allons continuer sur la base de l'exemple détaillé dans mon article précédent
Les différentes étapes à suivre sont les suivantes:

  • Mise en place de formulaire
  • Validation

Mise en place de formulaire

L'utilisation de la taglib form de Spring pour la mise en place de formulaire permet de faire un mapping entre le formulaire HTML et le formulaire Java.
L'objet Java doit être contenu dans le Model sous la clef correspondant à l'attribut "modelAttribute". Ensuite, chaque balise du formulaire devra correspondre à un champ de l'objet Java. Ces champs seront appelé via l'attribut "path" des taglibs.
Cette taglib est incluse dans la dépendance Spring web.

Avant toute chose, on va ajouter un pattern d'écoute à la Servlet Spring MVC dans le web.xml

    <servlet-mapping>
	       <servlet-name>dispatcher</servlet-name>
             <url-pattern>/formulaires/*</url-pattern>
    </servlet-mapping>

Création d'un formulaire HTML

Le formulaire contient 2 champs : noms & prénoms.

    <%@ page language="java" contentType="text/html;charset=UTF-8" info="TestMVC"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/transitional.dtd">
    <html lang="fr">
         <head><title>TestMVC</title>/head>
         <body style="background-color:#FFFFFF">
                <form:form modelAttribute="premierFormulaire" method="POST" action="${pageContext.request.contextPath}/formulaires/validation">
                       <table width="550px" border="0" cellspacing="0" cellpadding="0">
                              <tr>
                                <td width="63%">Nom</td>
                                <td width="37%"><form:input path="nom" /></td>
                              </tr>
                              <tr>     
                                <td>Pr&eacute;nom</td>
                                <td><form:input path="prenom" /></td>
                              </tr>
                             <tr>	
                             		<td>Email</td>
                             		<td><form:input path="email" /></td>
                             </tr>
                              <tr>    
                                <td colspan="2"><input type="submit" value="Validez" /></td>
                              </tr>
                       </table>
                     </form:form>
              <center></center>
         </body>
    </html>

Création du formulaire Java correspondant

On crée un objet Java ayant les 2 mêmes champs. Cet objet est un simple Java Bean.

    package fr.netapsys.test.form;
    public class TestForm {
        private String nom;
        private String prenom;
        private String email;
        /**
         * Getter for parameter nom.
         * @return the nom
         */
        public String getNom() {
            return nom;
        }
        /**
         * Setter for parameter nom.
         * @param nom the nom to set
         */
        public void setNom(String nom) {
            this.nom = nom;
        }
        /**
         * Getter for parameter prenom.
         * @return the prenom
         */
        public String getPrenom() {
            return prenom;
        }
        /**
         * Setter for parameter prenom.
         * @param prenom the prenom to set
         */
        public void setPrenom(String prenom) {
            this.prenom = prenom;
        }
        /**
        * Getter for parameter email.
        * @return the email
        */
        public String getEmail() {
            return email;
        }
        /**
         * Setter for parameter email.
         * @param email the email to set
         */
        public void setEmail(String email) {
            this.email = email;
        }
    }

Création du contrôleur

Après avoir créé un objet Java avec l'annotation @Controller, il faut créer 2 méthodes:

  • la première pour accéder à la page du formulaire
  • la seconde pour après la soumission du formulaire

Accès au formulaire

Cette méthode sert à initialiser le formulaire et à le mettre dans le model afin que la taglib puisse l'afficher.

    @RequestMapping(value = "/question", method = RequestMethod.GET)
    public String questionnaire(final Model model) {
       final TestForm form = new TestForm();
       model.addAttribute("premierFormulaire", form);
       return "fomulaires/form";
    }

Soumission

Cette méthode permet de lire le contenu du formulaire. Le formulaire est récupéré dans la méthode via l'annotation "@ModelAttribute" qui prend en paramètre le nom du "modelattribute" de la taglib "form".
A noter que l'URI d'écoute ne fonctionne que si la requête HTTP est de type POST

    @RequestMapping(value = "/validation", method = RequestMethod.POST)
   public String validation(@ModelAttribute("premierFormulaire") final TestForm testForm, final Model model) { 
       model.addAttribute("retour", testForm.getPrenom() + " " + testForm.getNom());
       return "fomulaires/result";
   }

Validation

Certes une validation des paramètres dans un validateur ou dans une méthode du formulaire est possible mais elle ne correspondra à aucune norme ou standard.
La norme JSR 303, ou Bean Validation, permet de mettre en place cette standardisation. Pour plus d'information, aller sur le site suivant: http://jcp.org/en/jsr/detail?id=303
Elle présente notamment les avantages suivants:

  • Bean Validation
  • Utilisation de métadonnées via des annotations
  • Valable avec Spring 3.x

Dépendances à ajouter au projet

Outre la dépendance de validation, il est impératif d'ajouter une dépendance sur une implémentation de la norme.
Le choix le plus courant est d'ajouter la dépendance Hibernate validation.

   <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>
   	<version>4.1.0.Final</version>
   </dependency>

Annotation du formulaire

L'ajout de contraintes sur le formulaire se fait via des annotations.
Ici, nous ajoutons les 3 champs comme obligatoires et pour l'email, nous allons ajouter un pattern de validation.
Bon nombre d'autres contraintes sont faisables, n'hésitez pas à les découvrir et à les utiliser.

La classe TestForm devient tel que suit:

   package fr.netapsys.test.form;
   import javax.validation.constraints.NotNull;
   import javax.validation.constraints.Pattern;
   import javax.validation.constraints.Size;
   public class TestForm {
       @NotNull
       @Size(min = 1)
       private String nom;
       @NotNull
       @Size(min = 1)
       private String prenom;
       @NotNull
       @Size(min = 1)
       @Pattern(regexp = "^a-zA-Z+a-zA-Z0-9\\._-*a-zA-Z0-9@a-zA-Z0-9a-zA-Z0-9\\._-*a-zA-Z0-9+\\.a-zA-Z{2,4}$")
       private String email;
       /**
        * Getter for parameter nom.
        * @return the nom
        */
       public String getNom() {
           return nom;
       }
     /**
        * Setter for parameter nom.
        * @param nom the nom to set
        */
       public void setNom(String nom) {
           this.nom = nom;
       }
       /**
        * Getter for parameter prenom.
        * @return the prenom
        */
       public String getPrenom() {
           return prenom;
       }
       /**
        * Setter for parameter prenom.
        * @param prenom the prenom to set
        */
       public void setPrenom(String prenom) {
           this.prenom = prenom;
       }
       /**
        * Getter for parameter email.
        * @return the email
        */
       public String getEmail() {
           return email;
       }
       /**
        * Setter for parameter email.
        * @param email the email to set
        */
       public void setEmail(String email) {
           this.email = email;
       }
   }

Il est également possible d'y ajouter des messages d'erreur en "dur" ou dans des fichiers de ressources.

Modification du contrôleur

Dans la méthode du contrôleur, il suffit:

  • d'ajouter en paramètre d'entrée l'attribut final BindingResult bindingResult
  • d'ajouter au paramètre d'entrée à valider l'annotation @Valid
   @RequestMapping(value = "/validation", method = RequestMethod.POST)
   public String validation(@ModelAttribute("premierFormulaire") @Valid final TestForm testForm,
           final BindingResult bindingResult, final Model model) {
       //On teste s'il y a une erreur
       if (bindingResult.hasErrors()) {
            //Traitement de l'erreur
       }
   ...
   }

Conclusion

La mise en œuvre de formulaire de leur validation est aisée avec Spring MVC et la norme JSR 303.
L'ensemble des éléments décrits ici est accessible via un micro projet que vous pourrez télécharger ci-dessous.
Projet de Test
L'archive du projet

Une fois votre projet installé sur un serveur d'application, il suffit de lancer l'URL suivante http://localhost:8080/test-mvc/formations/question

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.