6. Formulaires HTML
Jusqu'à maintenant, nous avons utilisé un unique formulaire ne comprenant que deux champs de saisie. Nous nous proposons ici de créer et traiter un formulaire utilisant les composants graphiques usuels (boutons radio, cases à cocher, champs de saisie, combobox, listes).
6.1. Les vues de l'application
L'application n'aura que deux vues. La première présente un formulaire vierge :
VUE 1 - formulaire

Cette première vue appelée formulaire.jsp nous permettra de mettre en oeuvre différentes balises de la bibliothèque struts-html. L'utilisateur remplit le formulaire :

Le bouton [Envoyer] permet d'avoir une confirmation des valeurs saisies. Ce sera la deuxième vue :

Cette deuxième vue nous permettra d'utiliser deux autres bibliothèques de balises struts-bean et struts-logic. Le lien [Retour au formulaire] nous permet de retrouver le formulaire tel que l'on l'a rempli. On retrouve alors la première vue.
6.2. L'architecture de l'application
![]() |
- le formulaire (vue 1) sera représenté par un objet Struts dynamique appelé dynaFormulaire de type dérivé de DynaActionForm. Il sera affiché par la vue formulaire.jsp.
- l'action Struts InitFormulaireAction aura pour but d'acquérir les données nécessaires à l'affichage du formulaire
- le formulaire rempli sera traité par une action ForwardAction qui se contera de rediriger la requête vers la seconde vue confirmation.jsp. Celle-ci se chargera d'afficher les valeurs du formulaire.
6.3. La configuration de l'application
6.3.1. Le fichier server.xml
Le contexte de l'application s'appellera /formulaire2. On ajoutera donc la ligne suivante dans le fichier server.xml de Tomcat :
Ceci fait, nous relançons éventuellement Tomcat afin qu'il prenne en compte le nouveau contexte. Nous pouvons vérifier la validité de celui-ci en demandant l'URL http://localhost:8080/formulaire2 :

6.3.2. Le fichier web.xml
Le fichier de configuration web.xml de l'application sera le suivant :
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
</web-app>
Vis à vis des fichiers de configuration web.xml déjà rencontrés nous apportons quelques modifications :
- nous introduisons deux nouvelles bibliothèques de balises struts-bean et struts-logic. Elles seront utilisées dans la vue confirmation.jsp. La vue formulaire.jsp utilisera, elle, la bibliothèque struts-html.
6.3.3. Le fichier struts-config.xml
Le fichier struts-config.xml sera lui le suivant :
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans>
<form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
<form-property name="opt" type="java.lang.String" initial="non"/>
<form-property name="chk1" type="java.lang.String"/>
<form-property name="chk2" type="java.lang.String"/>
<form-property name="chk3" type="java.lang.String"/>
<form-property name="champSaisie" type="java.lang.String" initial=""/>
<form-property name="mdp" type="java.lang.String" initial=""/>
<form-property name="boiteSaisie" type="java.lang.String" initial=""/>
<form-property name="combo" type="java.lang.String"/>
<form-property name="listeSimple" type="java.lang.String"/>
<form-property name="listeMultiple" type="java.lang.String[]"/>
<form-property name="secret" type="java.lang.String" initial="xxx"/>
<form-property name="valeursCombo" type="java.lang.String[]" />
<form-property name="valeursListeSimple" type="java.lang.String[]" />
<form-property name="valeursListeMultiple" type="java.lang.String[]"/>
</form-bean>
</form-beans>
<action-mappings>
<action
path="/confirmation"
name="dynaFormulaire"
validate="false"
scope="session"
parameter="/vues/confirmation.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
<action
path="/init"
name="dynaFormulaire"
validate="false"
scope="session"
type="istia.st.struts.formulaire.InitFormulaireAction"
>
<forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
</action>
<action
path="/affiche"
parameter="/vues/formulaire.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
</action-mappings>
<message-resources
parameter="ApplicationResources"
null="false"/>
</struts-config>
On y retrouve les trois grandes sections :
- la déclaration des formulaires dans la section <form-beans>
- la déclaration des actions dans la section <action-mappings>
- la déclaration du fichier de ressources dans <message-ressources>
6.3.4. Les objets (beans) formulaires de l'application
Les objets utilisés pour représenter les formulaires HTML de l'application sont des objets de type ActionForm ou dérivé (DynaActionForm, DynaValidatorForm, ...). On les appelle des beans parce que leur construction suit les règles des JavaBeans. Il n'y a qu'un bean formulaire dans notre application., appelé dynaFormulaire et de type dérivé de DynaActionForm. Il sera utilisé dans les situations suivantes :
- contenir les données nécessaires à l'affichage de la vue n° 1
- récupérer les valeurs du formulaire de la vue n°1 lorsque l'utilisateur va le valider (submit)
- contenir les données nécessaires à l'affichage de la vue n° 2
La structure du bean dynaFormulaire est intimement lié au formulaire de la vue n° 1. Etudions celui-ci :
![]() |
N° | Type HTML | Rôle |
<input name="opt" type="radio" value="oui"> <input name="opt" type="radio" value="non"> | groupe de boutons radio liés entre-eux (même nom) | |
<input name="chk1" type="radio" value="on"> <input name="chk2" type="radio" value="on"> <input name="chk3" type="radio" value="on"> | groupes de cases à cocher indépendantes (pas le même nom) | |
<input type="text " name="champSaisie" > | un champ de saisie | |
<input type="password " name="mdp" > | un champ mot de passe | |
<textarea name="boiteSaisie">...</textarea> | un champ de saisie multi-lignes | |
<select name="combo" size="1">..</select> | un combo | |
<select name="listeSimple" size="3">..</select> | une liste à sélection unique | |
<select name="listeMultiple" size="3" multiple>..</select> | une liste à sélection multiple | |
<input type="button" value="Effacer" onclick='effacerListe("listeSimple")'> | bouton permettant de désélectionner les éléments sélectionnés dans listeSimple (7) | |
<input type="button" value="Effacer" onclick='effacerListe("listeMultiple")'> | bouton permettant de désélectionner les éléments sélectionnés dans listeMultiple (8) | |
<input type="submit" value="Envoyer"> | bouton submit du formulaire | |
<input type="hidden" name="secret" value="..."> | un champ caché |
Distinguons plusieurs cas :
- l'objet dynaFormulaire est utilisé pour contenir les valeurs du formulaire HTML ci-dessus qui sera posté par le bouton [Envoyer]. Il faut donc qu'il ait les mêmes champs que dans le formulaire HTML. Le type du champ est fixé par la règle suivante :
- si le champ HTML ne fournit qu'une valeur, alors le champ de dynaFormulaire sera de type java.lang.String
- si le champ HTML fournit plusieurs valeurs, alors le champ de dynaFormulaire sera de type java.lang.String[]
Dans le formulaire HTML ci-dessus, seul le champ listeMultiple est susceptible d'être associé à plusieurs valeurs (celles sélectionnées par l'utilisateur). Donc une première définition de l'objet dynaFormulaire serait la suivante :
<form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
<form-property name="opt" type="java.lang.String" initial="non"/>
<form-property name="chk1" type="java.lang.String"/>
<form-property name="chk2" type="java.lang.String"/>
<form-property name="chk3" type="java.lang.String"/>
<form-property name="champSaisie" type="java.lang.String" initial=""/>
<form-property name="mdp" type="java.lang.String" initial=""/>
<form-property name="boiteSaisie" type="java.lang.String" initial=""/>
<form-property name="combo" type="java.lang.String"/>
<form-property name="listeSimple" type="java.lang.String"/>
<form-property name="listeMultiple" type="java.lang.String[]"/>
<form-property name="secret" type="java.lang.String" initial="xxx"/>
</form-bean>
Comment se fera le remplissage de dynaFormulaire avec les valeurs du formulaire HTML envoyées par le client web ?
le champ opt recevra la valeur "oui" si le champ HTML <input type="radio" name="opt" value="oui"> a été coché, la valeur "non" si c'est le champ <input type="radio" name="opt" value="non"> qui a été coché. | |
le champ chk1 recevra la valeur "on" si le champ HTML <input name="chk1" type="radio" value="1"> a été coché, rien sinon. Dans ce dernier cas, le champ chk1 conservera sa précédente valeur. | |
idem | |
idem | |
le champ champSaisie recevra le texte mis par l'utilisateur dans le champ HTML <input type="text" name="champSaisie">. Ce texte peut être éventuellement la chaîne vide. | |
le champ mdp recevra le texte mis par l'utilisateur dans le champ HTML <input type="password" name="mdp">. Ce texte peut être éventuellement la chaîne vide. | |
le champ boiteSaisie recevra le texte mis par l'utilisateur dans le champ HTML <textarea name="boiteSaisie">...</textarea>. Ce texte forme une seule chaîne de caractères, formée des lignes tapées par l'utilisateur séparées les unes des autres par la séquence de caractères "\r\n". Le texte obtenu peut être éventuellement la chaîne vide. | |
le champ combo recevra l'option sélectionnée par l'utilisateur dans le champ HTML <select name="combo" size="1">..</select>. L'option sélectionnée est celle qui apparaît dans le combo. Si l'option HTML sélectionnée est du type <option value="XX">YY</option>, le champ combo recevra la valeur "XX". Si l'option HTML sélectionnée est du type <option>YY</option>, le champ combo recevra la valeur "YY". | |
le champ listeSimple recevra l'option sélectionnée par l'utilisateur dans le champ HTML <select name="listeSimple" size="..">..</select> s'il y en a une. S'il n'y en a pas, le champ listeSimple ne recevra aucune valeur et gardera sa valeur précédente. La valeur affectée réellement au champ listeSimple suit les règles indiquées pour le combo. | |
le champ listeMultiple de type String[] recevra les options sélectionnées par l'utilisateur dans le champ HTML <select name="listeMultiple" size=".." multiple>..</select> s'il y en a. S'il n'y en a pas, le tableau listeMultiple ne recevra aucune valeur et son contenu restera inchangé. Les valeurs affectées réellement au tableau listeMultiple suivent les règles indiquées pour le combo. | |
le champ secret recevra la valeur XX du champ HTML <input type="hidden" name="secret" value="XX">. Ce texte peut être éventuellement la chaîne vide. |
- l'objet dynaFormulaire est utilisé pour donner le contenu initial de la vue n° 1. Les valeurs des champs précédents seront utilisées aux fins suivantes :
devra avoir la valeur "oui" ou "non" pour que le navigateur sache quel bouton radio cocher | |
si chk1 a la valeur "on" la case à cocher sera cochée sinon elle ne le sera pas | |
idem | |
idem | |
la valeur du champ sera affichée dans la zone de saisie champSaisie | |
la valeur du champ sera affichée dans la zone de saisie mdp | |
la valeur du champ sera affichée dans la zone de saisie boiteSaisie | |
la valeur de ce champ indique quel élément du combo doit être sélectionné à l'affichage du formulaire | |
idem | |
les valeurs du tableau listeMultiple indiquent quels éléments de la liste multiple doivent être sélectionnés à l'affichage du formulaire | |
la valeur du champ sera affectée à l'attribut value du champ HTML secret. |
La vue n° 1 a besoin d'autres informations :
- la liste des valeurs à afficher dans la liste combo
- la liste des valeurs à afficher dans la liste listeSimple
- la liste des valeurs à afficher dans la liste listeMultiple
Il existe plusieurs façons de fournir ces informations à la vue. Des tableaux placés dans la requête passée à la vue feraient par exemple l'affaire. Ici, nous plaçons ces tableaux dans le bean dynaFormulaire :
<form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
...
<form-property name="valeursCombo" type="java.lang.String[]" />
<form-property name="valeursListeSimple" type="java.lang.String[]" />
<form-property name="valeursListeMultiple" type="java.lang.String[]"/>
</form-bean>
Le formulaire dynaFormulaire sera initialisé par l'action /init qui fera appel à un objet dérivé de Action appelé InitFormulaireAction. C'est cet objet qui se chargera de créer les trois tableaux nécessaires à l'affichage des trois listes et de les mettre dans le bean dynaFormulaire. Le fichier de configuration donne à ce bean une portée égale à la session. Ceci entraîne que le contrôleur Struts placera ce bean dans la session. Nous n'aurons ainsi pas besoin de le régénérer entre deux cycles demande-réponse. Aussi l'action /init ne sera-t-elle appelée qu'une fois.
- l'objet dynaFormulaire est également utilisé pour donner le contenu de la vue n° 2. Celle-ci se contente d'en afficher les valeurs.
6.3.5. Les actions de l'application
Les actions sont assurées par des objets de type Action ou dérivé. La configuration des actions est faite à l'intérieur des balises <action-mappings> :
<action-mappings>
<action
path="/confirmation"
name="dynaFormulaire"
validate="false"
scope="session"
parameter="/vues/confirmation.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
<action
path="/init"
name="dynaFormulaire"
validate="false"
scope="session"
type="istia.st.struts.formulaire.InitFormulaireAction"
>
<forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
</action>
<action
path="/affiche"
parameter="/vues/formulaire.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
</action-mappings>
Notons qu'il n'y a pas toujours un formulaire associé à une action. C'est le cas, ci-dessus, de l'action /affiche. Avant de détailler chaque action, rappelons le fonctionnement du couple action-formulaire associé au sein d'une balise <action> :
- une action commence avec une requête d'un client web et se termine par l'envoi d'une page réponse. C'est le cycle demande-réponse du client-serveur web. La requête est reçue par le contrôleur Struts de type ActionServlet ou dérivé. C'est aussi ce contrôleur qui envoie la réponse.
- le bean du formulaire de type ActionForm ou dérivé est créé s'il n'existe pas déjà. Le contrôleur regarde s'il peut trouver un objet de nom name dans la portée indiquée par scope. Si oui, il l'utilise. Si non, il le crée et le met dans la portée indiquée par scope, associé à l'attribut indiqué par name.
Dans l'exemple de l'action /init par exemple, le contrôleur fera un request.getSession().getAttribute("dynaFormulaire") pour savoir si dynaFormulaire a déjà été créé ou non. Si ce n'est pas le cas, il le créera et le mettra dans la session par une instruction du genre request.getSession().setAttribute("dynaFormulaire",new DynaFormulaire(...)).
- le contrôleur va également chercher un objet Action du type indiqué par l'attribut type. S'il ne trouve pas, il le crée, sinon il l'utilise.
- la méthode reset du bean formulaire va être appelée. Celui-ci, sauf lors de sa création initiale, est recyclé. Il contient alors des données qu'on peut vouloir "nettoyer". C'est dans la méthode reset du bean ActionForm ou dérivé que l'on fera cela.
- si l'action est la cible d'un formulaire posté, alors les valeurs du formulaire qui se trouvent dans la requête du client sont copiées dans les champs de même nom du bean formulaire. On notera que la méthode reset a été appelée avant cette recopie.
- si la configuration précise l'attribut validate="true", la méthode validate du bean formulaire sera appelée. Celle-ci doit alors vérifier les données du bean. Cette vérification n'a lieu le plus souvent que lorsque le formulaire vient de recevoir de nouvelles données via un formulaire posté et qu'on veut vérifier la validité de ces données. Cette méthode rend au contrôleur une éventuelle liste d'erreurs dans un objet ActionErrors.
- si l'objet ActionErrors est non vide, le contrôleur fait afficher la vue précisée par l'attribut input de l'action.
- si la validation des données n'est pas demandée ou si elle s'est bien passée, le contrôleur fait exécuter la méthode execute de l'objet de type Action ou dérivé associé à l'action en cours. C'est dans cette méthode que la demande du client web est traitée. La méthode execute renvoie un objet ActionForward indexé par des clés de type chaîne de caractères. Ces clés sont celles déclarées par les balises forward de l'action configurée. Dans notre exemple, l'action /init a une seule balise forward. Elle associe la clé "afficherFormulaire" à la vue formulaire.jsp.
- le contrôleur fait afficher la vue à laquelle est associée la clé reçue. Cette vue peut être en fait une action, auquel cas le processus précédent est répété.
L'action /init
<action
path="/init"
name="dynaFormulaire"
validate="false"
scope="session"
type="istia.st.struts.formulaire.InitFormulaireAction"
>
<forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
</action>
- l'action /init a lieu normalement une fois lors du 1er cycle demande-réponse lorsque l'utilisateur demande l'URL http://localhost:8080/formulaire2/init.do
- l'objet dynaFormulaire est créé ou recyclé. Il est récupéré (recyclage) ou placé (création) dans la session comme le demande l'attribut scope.
- sa méthode reset est appelée. Que doit-elle faire ? Normalement, on remet les champs de l'objet ActionForm à des valeurs par défaut. Seulement ici, nous ne le ferons pas, car l'objet dynaFormulaire est placé dans la session (scope="session"). Les champs de dynaFormulaire doivent donc garder leurs valeurs. Quelles sont celles-ci lors de la création initiale de l'objet dynaFormulaire ? Il y a deux cas :
- le champ a une valeur initiale indiquée dans le fichier de configuration :
Dans ce cas, le contrôleur Struts créera ce champ avec cette valeur initiale.
- le champ n'a pas de valeur initiale par configuration : les règles d'initialisation de Java s'appliquent. En général, les champs numériques auront la valeur zéro, les chaînes de caractères auront pour valeur la chaîne vide, les autres objets ayant la valeur null.
Regardons la configuration initiale de dynaFormulaire :
<form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
<form-property name="opt" type="java.lang.String" initial="non"/>
<form-property name="chk1" type="java.lang.String"/>
<form-property name="chk2" type="java.lang.String"/>
<form-property name="chk3" type="java.lang.String"/>
<form-property name="champSaisie" type="java.lang.String" initial=""/>
<form-property name="mdp" type="java.lang.String" initial=""/>
<form-property name="boiteSaisie" type="java.lang.String" initial=""/>
<form-property name="combo" type="java.lang.String"/>
<form-property name="listeSimple" type="java.lang.String"/>
<form-property name="listeMultiple" type="java.lang.String[]"/>
<form-property name="secret" type="java.lang.String" initial="xxx"/>
<form-property name="valeursCombo" type="java.lang.String[]" />
<form-property name="valeursListeSimple" type="java.lang.String[]" />
<form-property name="valeursListeMultiple" type="java.lang.String[]"/>
</form-bean>
Les valeurs initiales des champs de dynaFormulaire après sa création seront les suivantes :
Champ | Valeur initiale |
"non" | |
chaîne vide | |
chaîne vide | |
chaîne vide | |
chaîne vide | |
chaîne vide | |
chaîne vide | |
tableau de chaînes vides | |
"xxx" | |
tableau de chaînes vides |
- on pourrait imaginer que la méthode reset de dynaFormulaire donne des valeurs aux trois tableaux devant alimenter les trois listes de la vue formulaire.jsp. Ce serait possible ici car les données de ces trois tableaux sont générées de façon arbitraire. Néanmoins, le cas le plus usuel est que ces données proviennent du modèle de l'application, le M de MVC. Ici, nous prendrons une position intermédiaire, pour ne pas compliquer l'exemple, en faisant générer ces valeurs par l'action InitFormulaireAction donc par le C de MVC.
- il n'y a pas obligation d'écrire une méthode reset à dynaFormulaire, la classe ActionForm dont elle dérive ayant une telle méthode qui ne fait rien (pas d'initialisations).
- une fois la méthode reset de dynaFormulaire appelée, le contrôleur regarde l'attribut validate de l'action. Ici, il a la valeur "false". La méthode validate de dynaFormulaire ne sera pas appelée.
- l'objet InitFormulaireAction est créé ou recyclé s'il existait déjà et sa méthode execute lancée. C'est elle qui va affecter des valeurs arbitraires aux trois tableaux de dynaFormulaire : valeursCombo, valeursListeSimple et valeursListeMultiple. La méthode rend un ActionForward de clé "afficherFormulaire".
- le contrôleur fait afficher la vue /vues/formulaire.jsp qui a été associée à la clé "afficherFormulaire" par une balise forward de l'action /init.
L'action /confirmation
<action
path="/confirmation"
name="dynaFormulaire"
validate="false"
scope="session"
parameter="/vues/confirmation.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
- l'action /confirmation a lieu lorsque l'utilisateur appuie sur le bouton [Envoyer] de la vue n° 1. Le navigateur "poste" alors au contrôleur Struts le formulaire rempli par l'utilisateur.
- l'objet dynaFormulaire est pris dans la session
- sa méthode reset est appelée. Une fois qu'elle aura été appelée, le contrôleur Struts va copier les valeurs des champs du formulaire posté par le client dans les champs de même nom de dynaFormulaire. Reprenons la liste des champs de ce dernier et voyons comment s'opère cette recopie :
Champ | Code HTML associé | Valeur du champ après recopie des valeurs du formulaire |
<input type="radio" name="opt" value="oui">Oui <input type="radio" name="opt" value="non" checked="checked">Non | - "oui" ou "non" selon le bouton radio coché | |
<input type="checkbox" name="chk1" value="on"> | - "on" si la case chk1 a été cochée - garde sa précédente valeur si la case chk1 n'a pas été cochée | |
<input type="checkbox" name="chk2" value="on"> | - "on" si la case chk2 a été cochée - garde sa précédente valeur si la case chk2 n'a pas été cochée | |
<input type="checkbox" name="chk2" value="on"> | - "on" si la case chk3 a été cochée - garde sa précédente valeur si la case chk3 n'a pas été cochée | |
<input type="text" name="champSaisie" value=""> | - valeur tapée par l'utilisateur dans champSaisie | |
<input type="password" name="mdp" value=""> | - valeur tapée par l'utilisateur dans mdp | |
<textarea name="boiteSaisie"></textarea> | - valeur tapée par l'utilisateur dans boiteSaisie | |
<select name="combo">...</select> | - valeur sélectionnée par l'utilisateur dans combo | |
<select name="listeSimple" size="3">...</select> | - valeur sélectionnée par l'utilisateur dans listeSimple | |
<select name="listeMultiple" multiple="multiple" size="5"> | - tableau de chaînes contenant les valeurs sélectionnées par l'utilisateur dans listeMultiple | |
<input type="hidden" name="secret" value="xxx"> | - "xxx". |
On a une difficulté avec les champs qui ne reçoivent pas forcément une valeur dans la requête envoyée par le navigateur. C'est le cas des cases à cocher chk1 à chk3 et des deux listes listeSimple et listeMultiple. Dans ce cas, ces champs gardent leur valeur précédente, celles acquises au cours du cycle demande-réponse précédent.
Raisonnons sur la case à cocher chk1 par exemple et supposons que dans le précédent cycle demande-réponse, l'utilisateur avait coché cette case. Le navigateur avait alors envoyé dans la chaîne de paramètres de sa requête l'information chk1="on". Le constructeur a donc affecté la valeur "on" au champ chk1 de dynaFormulaire. Supposons maintenant que dans le cycle en cours, l'utilisateur ne coche pas la case chk1. Dans ce cas, dans la chaîne de paramètres de la nouvelle requête, le navigateur n'envoie pas quelque chose comme chk1="off" mais n'envoie rien. Du coup, le champ chk1 de dynaFormulaire va garder sa valeur "on" et donc avoir une valeur qui ne reflète pas celle du formulaire validé par l'utilisateur. On utilisera la méthode reset de dynaFormulaire pour résoudre ce problème. On mettra dans cette méthode les trois champs chk1, chk2, chk3 à "off". Dans notre exemple de chk1, soit l'utilisateur :
- coche la case chk1. Alors le navigateur envoie l'information chk1="on" et le champ chk1 de dynaFormulaire va passer à "on"
- ne coche pas la case chk1. Alors le navigateur n'envoie pas de valeur pour le champ chk1 qui va garder sa précédente valeur "off". Dans les deux cas, la valeur enregistrée dans le champ chk1 de dynaFormulaire est correcte.
Le problème est analogue pour les deux listes listeSimple et listeMultiple. Si aucune option n'a été sélectionnée dans ces listes, elles ne seront pas présentes dans les paramètres de la requête et vont donc conserver leurs valeurs précédentes. Dans la méthode reset de dynaFormulaire, nous ré-initialiserons listeSimple avec une chaîne de caractères vide et listeMultiple avec un tableau de chaînes de longueur 0.
- une fois la méthode reset de dynaFormulaire appelée, le contrôleur recopie dans les champs de dynaFormulaire les informations qui lui ont été envoyées dans la requête du client
- un objet ForwardAction est créé ou recyclé et sa méthode execute appelée. ForwardAction est une classe prédéfinie qui rend un objet ActionForward pointant sur la vue définie par l'attribut "parameter" de l'action, ici /vues/confirmation.jsp.
- le contrôleur envoie cette vue. Le cycle est terminé.
L'action /affiche
<action
path="/affiche"
parameter="/vues/formulaire.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
- l'action /affiche est déclenchée par activation du lien [Retour vers le formulaire] de la vue n° 2.
- ici il n'y a pas de formulaire associée à l'action. On passe donc tout de suite à l'exécution de la méthode execute d'un objet ForwardAction qui va rendre un objet ActionForward pointant sur la vue /vues/formulaire.jsp.
6.3.6. Le fichier de messages de l'application
La troisième section du fichier struts-config.xml est celui du fichier des messages :
Le fichier ApplicationResources.properties est placé dans WEB-INF/classes. Il sera vide. Même vide, il doit cependant être déclaré dans le fichier de configuration sinon la bibliothèquede balises struts-bean que nous verrons un peu plus loin génère une erreur. Cette bibliothèque est utilisée par la vue confirmation.jsp.
6.4. Le code des vues
6.4.1. La vue formulaire.jsp
Rappelons que cette vue est affichée dans deux cas :
- à l'appel de l'action /init lors du 1er cycle demande-réponse
- à l'appel de l'action /affiche lors des cycles suivants
Le code de la vue formulaire.jsp est le suivant :
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<title>formulaire</title>
</head>
<body background='<html:rewrite page="/images/standard.jpg"/>'>
<h3>Formulaire Struts</h3>
<hr>
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
<table border="0">
<tr>
<td>bouton radio</td>
<td>
<html:radio name="dynaFormulaire" property="opt" value="oui">Oui</html:radio>
<html:radio name="dynaFormulaire" property="opt" value="non">Non</html:radio>
</td>
</tr>
<tr>
<td>Cases à cocher</td>
<td>
<html:checkbox name="dynaFormulaire" property="chk1">1</html:checkbox>
<html:checkbox name="dynaFormulaire" property="chk2">2</html:checkbox>
<html:checkbox name="dynaFormulaire" property="chk3">3</html:checkbox>
</td>
</tr>
<tr>
<td>Champ de saisie</td>
<td>
<html:text name="dynaFormulaire" property="champSaisie" />
</td>
</tr>
<tr>
<td>Mot de passe</td>
<td>
<html:password name="dynaFormulaire" property="mdp" />
</td>
</tr>
<tr>
<td>Boîte de saisie multilignes</td>
<td>
<html:textarea name="dynaFormulaire" property="boiteSaisie" />
</td>
</tr>
<tr>
<td>Combo</td>
<td>
<html:select name="dynaFormulaire" property="combo">
<html:options name="dynaFormulaire" property="valeursCombo"/>
</html:select>
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td>Liste à sélection unique</td>
</tr>
<tr>
<td>
<input type="button" value="Effacer" onclick="this.form.listeSimple.selectedIndex=-1"/>
</td>
</tr>
</table>
<td>
<html:select name="dynaFormulaire" property="listeSimple" size="3">
<html:options name="dynaFormulaire" property="valeursListeSimple"/>
</html:select>
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td>Liste à sélection multiple</td>
</tr>
<tr>
<td>
<input type="button" value="Effacer" onclick="this.form.listeMultiple.selectedIndex=-1"/>
</td>
</tr>
</table>
</td>
<td>
<html:select name="dynaFormulaire" property="listeMultiple" size="5" multiple="true">
<html:options name="dynaFormulaire" property="valeursListeMultiple"/>
</html:select>
</td>
</tr>
</table>
<html:hidden name="dynaFormulaire" property="secret"/>
<br>
<hr>
<html:submit>Envoyer</html:submit>
</html:form>
</body>
</html>
Cette page JSP utilise des balises provenant de la bibliothèque struts-html. Rappelons que pour utiliser une bibliothèque de balises, il faut :
- la déclarer dans le fichier web.xml de l'application avec une balise <tag-lib>
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
- placer le code de cette bibliothèque quelque-part dans l'arborescence de l'application, ici WEB-INF/struts-html.tld
- déclarer l'utilisation de cette bibliothèque au début des pages JSP qui l'utilisent :
La vue formulaire.jsp utilise des balises que nous expliquons maintenant :
<body background="<html:rewrite page="/images/standard.jpg"/>"> | |||
la balise html:rewrite permet de s'affranchir du nom de l'application dans des URL. Elle a un attribut :
Ainsi ci-dessus, si on décide d'appeler l'application formulaire3, le code de l'attribut background n'a pas à être réécrit. La balise html:rewrite génèrera le nouveau code HTML background="/formulaire3/images/standard.jpg" |
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire"> | |||||||
la balise html:form permet de générer la balise HTML form. Elle a plusieurs attributs :
On voit que par défaut, le code HTML généré utilise la méthode POST. Dans ce même code HTML, l'URL de l'action a été réécrite pour être préfixée par le nom de l'application et suffixée par .do. |
<html:radio name="dynaFormulaire" property="opt" value="oui">Oui</html:radio> | |||||||
la balise html:radio sert à générer la balise HTML <input type="radio" ...>. Elle admet divers attributs :
Le texte entre la balise de début et de fin est le texte qui sera affiché à côté du bouton radio. |
<html:checkbox name="dynaFormulaire" property="chk1">1</html:checkbox> | |||||||
la balise html:checkbox sert à générer la balise HTML <input type="checkbox" ...>. Elle admet divers attributs :
Le texte entre la balise de début et de fin est le texte qui sera affiché à côté de la case à cocher. |
<html:text name="dynaFormulaire" property="champSaisie" /> | |||||||
la balise html:text sert à générer la balise HTML <input type="text" ...>. Elle admet divers attributs :
|
<html:password name="dynaFormulaire" property="mdp" /> | |
la balise html:password sert à générer la balise HTML <input type="password" ...>. Elle admet divers attributs : |
<html:textarea name="dynaFormulaire" property="boiteSaisie" /> | |||||||
la balise html:textarea sert à générer la balise HTML <textarea>...</textarea>. Elle admet divers attributs :
|
<html:select name="dynaFormulaire" property="combo">....</html:select> | |||||||
la balise html:select sert à générer la balise HTML <select>...</select>. Elle admet divers attributs :
|
<html:select name="dynaFormulaire" property="combo"> <html:options name="dynaFormulaire" property="valeursCombo"/> </html:select> | |||||
la balise html:options sert à générer les balises HTML <option>...</option> à l'intérieur d'une balise HTML <select>. Il y a diverses façons de préciser comment trouver les valeurs de remplissage du select. Ici, nous avons utilisé les attributs name et property :
|
Les deux autres listes sont générées de façon analogue à la précédente :
<html:select name="dynaFormulaire" property="listeSimple" size="3">
<html:options name="dynaFormulaire" property="valeursListeSimple"/>
</html:select>
Ci-dessus, on précise un attribut size différent de 1 pour avoir une liste au lieu d'un combo.
<html:select name="dynaFormulaire" property="listeMultiple" size="5" multiple="true">
<html:options name="dynaFormulaire" property="valeursListeMultiple"/>
</html:select>
Ci-dessus, on précise l'attribut multiple="true" pour avoir une liste à sélection multiple.
<html:hidden name="dynaFormulaire" property="secret"/> | |||||
la balise html:hidden sert à générer la balise HTML <input type="hidden" ...>.
|
Pour bien comprendre le lien entre la vue formulaire.jsp et le bean dynaFormulaire qui la représente en mémoire, il faut se rappeler que le bean dynaFormulaire s'utilise à la fois en lecture et écriture :
![]() |
La requête a lieu lorsque l'utilisateur clique sur le bouton [Envoyer] du formulaire. Le navigateur "poste" alors le formulaire HTML à l'action /confirmation. Nous avons déjà expliqué ce qui se passait alors et notamment que les champs de dynaFormulaire allaient recevoir les valeurs des champs de même nom du formulaire HTML.
Que se passe-t-il lorsque le contrôleur demande l'affichage de la vue formulaire.jsp en réponse à une requête ? Reconsidérons les balises une à une :
<body background="<html:rewrite page="/images/standard.jpg"/>"> | |
génère le code HTML |
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire"> ... </html:form> | |
génère le code HTML |
<html:radio name="dynaFormulaire" property="opt" value="oui">Oui</html:radio> <html:radio name="dynaFormulaire" property="opt" value="non">Non</html:radio> | |
Si le champ opt de dynaFormulaire vaut "oui", génère le code HTML |
<html:checkbox name="dynaFormulaire" property="chk1">1</html:checkbox> <html:checkbox name="dynaFormulaire" property="chk2">2</html:checkbox> <html:checkbox name="dynaFormulaire" property="chk3">3</html:checkbox> | |
Si les champs chk1 et chk3 de dynaFormulaire valent "on" et si le champ chk2 vaut "off", génère le code HTML |
<html:text name="dynaFormulaire" property="champSaisie" /> | |
si le champ champSaisie vaut "ceci est un essai", génère le code HTML |
<html:password name="dynaFormulaire" property="mdp" /> | |
si le champ mdp vaut "azerty", génère le code HTML |
<html:password name="dynaFormulaire" property="mdp" /> | |
si le champ mdp vaut "azerty", génère le code HTML |
<html:password name="dynaFormulaire" property="mdp" /> | |
si le champ mdp vaut "azerty", génère le code HTML |
<html:select name="dynaFormulaire" property="combo"> <html:options name="dynaFormulaire" property="valeursCombo"/> </html:select> | |
si le champ combo vaut "combo2", génère le code HTML |
<html:select name="dynaFormulaire" property="listeSimple" size="3"> <html:options name="dynaFormulaire" property="valeursListeSimple"/> </html:select> | |
si le champ listeSimple vaut "simple1", génère le code HTML |
<html:select name="dynaFormulaire" property="listeMultiple" size="5" multiple="true"> <html:options name="dynaFormulaire" property="valeursListeMultiple"/> </html:select> | |
si le champ listeMultiple est le tableau {"multiple0","multiple2"}, génère le code HTML |
<html:hidden name="dynaFormulaire" property="secret"/> | |
si le champ secret a la valeur "xxx", génère le code HTML |
<html:submit>Envoyer</html:submit> | |
génère le code HTML |
La dernière chose à expliquer est le code javascript inclus dans la page JSP et lié aux deux boutons [Effacer] qui désélectionnent les éléments sélectionnés dans les listes listeSimple et listeMultiple :
<input type="button" value="Effacer" onclick="this.form.listeSimple.selectedIndex=-1"/>
<input type="button" value="Effacer" onclick="this.form.listeMultiple.selectedIndex=-1"/>
La balise
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
donne naissance au code HTML suivant :
Pour comprendre le code Javascript lié aux boutons [Effacer], rappelons comment sont désignés les différents éléments d'un document web au sein d'un code Javascript exploitant ce document :
Donnée | Signification |
désigne la totalité du document web | |
désigne la collection des formulaires définis dans le document | |
désigne le formulaire n° i du document | |
désigne le formulaire <form> ayant l'attribut name égal à "nomFormulaire" | |
désigne le formulaire <form> ayant l'attribut name égal à "nomFormulaire" | |
désigne la collection des éléments membres du formulaire désigné par l'expression [formulaire]. Cette collection comprend toutes les balises <input>, <textarea>, <select> du formulaire désigné. | |
désigne l'élément n° i de [formulaire] | |
désigne l'élément de [formulaire] ayant l'attribut name égal à nomComposant | |
désigne l'élément de [formulaire] ayant l'attribut name égal à nomComposant | |
désigne la valeur du composant [composant] du formulaire [formulaire] lorsque le code HTML de celui-ci peut avoir un attribut value (<input>, <textarea>) | |
désigne l'indice de l'option sélectionnée dans une liste. S'utilise en lecture et écriture. Mettre cette propriété à -1 désélectionne tous les éléments de la liste. | |
désigne le tableau des options associées à une balise <select> | |
désigne l'option n° i de la balise <select> indiquée | |
booléen indiquant si l'option n° i de la balise [select] indiquée est sélectionnée (true) ou non. Peut s'utiliser en lecture et écriture |
Revenons sur le code javascript des deux boutons :
<input type="button" value="Effacer" onclick="this.form.listeSimple.selectedIndex=-1"/>
<input type="button" value="Effacer" onclick="this.form.listeMultiple.selectedIndex=-1"/>
Sur l'événement clic sur le bouton, le code associé à l'attribut "onclick" est exécuté. Ici, c'est un code en ligne. Le plus souvent, on écrit onclick="fonction(...)" où fonction est une fonction définie au sein d'une balise <script language="javascript">...</script>. Que fait le code ci-dessus ? Commentons le code du premier bouton :
désigne le document web dans lequel se trouve le bouton | |
désigne le formulaire dans lequel se trouve le bouton | |
désigne le composant listeSimple du formulaire | |
désigne l'indice de l'option sélectionnée dans listeSimple. Mettre à -1 cette propriété entraîne la désélection de toute option. |
6.4.2. La vue confirmation.jsp
Rappelons que cette vue est affichée à l'issue de l'action /confirmation, c.a.d. après que le formulaire contenu dans la vue formulaire.jsp ait été posté par le client web. Elle a pour seul but d'afficher les valeurs saisies par l'utilisateur. Son code est le suivant :
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html>
<head>
<title>Confirmation</title>
</head>
<body background="<html:rewrite page="/images/standard.jpg"/>">
<h3>Confirmation des valeurs saisies</h3>
<hr/>
<table border="1">
<tr>
<td>Bouton radio</td>
<td><bean:write name="dynaFormulaire" scope="session" property="opt"/></td>
</tr>
<tr>
<td>Case à cocher chk1</td>
<td><bean:write name="dynaFormulaire" scope="session" property="chk1"/></td>
</tr>
<tr>
<td>Case à cocher chk2</td>
<td><bean:write name="dynaFormulaire" scope="session" property="chk2"/></td>
</tr>
<tr>
<td>Case à cocher chk3</td>
<td><bean:write name="dynaFormulaire" scope="session" property="chk3"/></td>
</tr>
<tr>
<td>Champ de saisie</td>
<td><bean:write name="dynaFormulaire" scope="session" property="champSaisie"/></td>
</tr>
<tr>
<td>Mot de passe</td>
<td><bean:write name="dynaFormulaire" scope="session" property="mdp"/></td>
</tr>
<tr>
<td>Boîte de saisie</td>
<td><bean:write name="dynaFormulaire" scope="session" property="boiteSaisie"/></td>
</tr>
<tr>
<td>combo</td>
<td><bean:write name="dynaFormulaire" scope="session" property="combo"/></td>
</tr>
<tr>
<td>liste simple</td>
<td><bean:write name="dynaFormulaire" scope="session" property="listeSimple"/></td>
</tr>
<logic:iterate id="choix" indexId="index" name="dynaFormulaire" property="listeMultiple">
<tr>
<td>liste multiple[<bean:write name="index"/>]</td>
<td><bean:write name="choix"/></td>
</tr>
</logic:iterate>
</table>
<br>
<html:link page="/affiche.do">
Retour au formulaire
</html:link>
</body>
</html>
Nous introduisons ici deux nouvelles bibliothèques de balises : struts-bean et struts-logic. La bibliothèque struts-bean permet d'avoir accès à des objets placés dans la requête, la session ou le contexte de l'application. La bibliothèque struts-logic permet d'introduire de la logique d'exécution au moyen de balises. Ces deux bibliothèques ne sont nullement indispensables. Comme nous l'avons vu, une page JSP peut :
- récupérer des objets dans la requête (request.getAttribute(...)), la session (session.getAttribute(...), ou le contexte de l'application
- inclure des parties dynamiques dans le code HTML au moyen de variables <%= variable %>
- comporter du code Java <% code Java %>
L'inclusion de code Java dans des pages JSP gêne tous ceux qui voudraient une stricte séparation entre logique applicative (code java) et présentation (utilisation de balises). Aussi a-t-on inventé pour eux des bibliothèques de balises.
Nous allons procéder comme pour la vue formulaire.jsp et expliquer chacune des balises présentes dans le code de confirmation.jsp si elles n'ont pas été déjà rencontrées dans la vue formulaire.jsp. Tout d'abord, remarquons que la page commence par déclarer les trois bibliothèques de balises qu'elle va utiliser :
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
Rappelons aussi que ces trois bibliothèques doivent être déclarées dans le fichier web.xml de l'application. Nous commentons maintenant les balises du document formulaire.jsp :
écrit une valeur dans le flux HTML courant. La balise bean:write admet les attributs suivants : name : nom de l'objet à utiliser scope : portée (request, session, context) dans laquelle chercher cet objet property : champ de l'objet désigné par name dont il faut écrire la propriété. Ce champ peut être un objet de tout type. Ce sera la méthode toString de l'objet qui sera utilisée. Ici, la valeur du champ opt de dynaFormulaire est écrite. On aura soit "oui" si l'utilisateur a coché le bouton radio ayant l'attribut value="oui", soit "non" s'il a coché le bouton radio ayant l'attribut value="non" |
écrit la valeur du champ chk1 de dynaFormulaire. On aura soit "on" si l'utilisateur a coché la case, soit "off" sinon. Idem pour chk2, chk3. |
écrit la valeur du champ champSaisie de dynaFormulaire, c'est à dire le texte tapé par l'utilisateur dans ce champ. Idem pour mdp, boiteSaisie. |
écrit la valeur du champ combo de dynaFormulaire. On aura l'attribut value de l'élément <option> sélectionné par l'utilisateur. |
écrit la valeur du champ listeSimple de dynaFormulaire. On aura l'attribut value de l'élément <option> sélectionné par l'utilisateur s'il y en a eu un. Sinon on aura la chaîne vide. |
Ici, nous introduisons des balises de logique. Nous avons affaire à une liste à choix multiple. La valeur du champ listeMultiple de l'objet dynaFormulaire est un tableau de String. En java, nous écririons une boucle. La balise logic:iterate nous permet de faire cette même boucle sans écrire de code Java. La balise logic:iterate a dans l'exemple les attributs suivants : name="dynaFormulaire" : nom de l'objet à utiliser property="listeMultiple" : nom de la propriété qui dans l'objet indiqué par name contient la collection qui va être parcourue dans la boucle. Ici cette collection est le tableau des valeurs sélectionnées dans listeMultiple. Ce tableau peut être vide. id="choix" : identificateur désignant l'élément courant du tableau à chaque tour de boucle. Lors de la 1ère itération, choix représentera listeMultiple[0], à la seconde listeMultiple[1] et ainsi de suite. indexID="index" : identificateur désignant l'indice de l'élément courant du tableau à chaque tour de boucle. Lors de la 1ère itération, index aura la valeur 0, à la seconde la valeur 1 et ainsi de suite. Le code HTML contenu entre les balises <logic:iterate ...> et </logic:iterate> est répété pour chaque élément de la collection désignée par le couple (name,property). La partie dynamique de ce code est le suivant : De ce qui a été dit précédemment, à l'itération n° i (i>=0), le code HTML généré est équivalent au code suivant : |
génère un lien relatif au contexte de l'application, ce qui évite de connaître celui-ci. Le code HTML généré par cette balise est le suivant : |
6.5. Les classes Java
Le fichier de configuration struts-config.xml référence deux classes Java :
<form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
...
<action
path="/init"
name="dynaFormulaire"
validate="false"
scope="session"
type="istia.st.struts.formulaire.InitFormulaireAction"
>
La classe DynaFormulaire est la classe qui contiendra les valeurs de la vue n° 1 formulaire.jsp. La classe InitFormulaireAction est la classe qui traitera les valeurs du formulaire posté par le bouton [Envoyer] de formulaire.jsp.
6.5.1. La classe DynaFormulaire
Pour contenir les valeurs d'un formulaire, un objet de type DynaActionForm est suffisant sauf si on a besoin de redéfinir l'une des méthodes reset ou validate de cette classe. Ici, la méthode validate n'a pas besoin d'être redéfinie puisqu'on ne fait aucune validation de données. Mais la méthode reset a elle besoin d'être redéfinie. En effet, les champs de l'objet DynaFormulaire vont recevoir leurs valeurs du formulaire posté par le client web. Or certains champs peuvent ne pas recevoir de valeur s'ils ne sont pas présents dans la requête. Cela se produit dans les cas suivants :
- une case à cocher qui n'a pas été cochée par l'utilisateur
- une liste de taille supérieure à 1 ou aucune option n'a été sélectionnée
Pour des formulaires ayant ce type de composant, la méthode reset doit
- affecter la valeur "off" au champ associé à la case à cocher
- affecter la chaîne vide au champ associé à une liste à sélection unique
- affecter un tableau de taille nulle de chaînes de caractères au champ associé à une liste à sélection multiple
Ainsi, si ces champs ne reçoivent pas de valeur de la requête, ils conservent la valeur attribuée par reset, valeur qui correspond à l'état du composant dans le formulaire validé par l'utilisateur (case non cochée, liste avec aucun élément sélectionné).
Le code de la classe DynaFormulaire, classe dérivée de DynaActionForm est le suivant :
package istia.st.struts.formulaire;
import org.apache.struts.action.DynaActionForm;
import org.apache.struts.action.ActionMapping;
import javax.servlet.http.HttpServletRequest;
public class DynaFormulaire extends DynaActionForm {
public void reset(ActionMapping mapping, HttpServletRequest request){
// reset des cases à cocher - valeur off
set("chk1","off");
set("chk2","off");
set("chk2","off");
// reset listeSimple - chaîne vide
set("listeSimple","");
// reset listeMultiple - tableau vide
set("listeMultiple",new String[]{});
}
}
6.5.2. La classe InitFormulaireAction
La classe InitFormulaireAction est, dans le fichier struts-config.xml, associée à l'action /init :
<action
path="/init"
name="dynaFormulaire"
validate="false"
scope="session"
type="istia.st.struts.formulaire.InitFormulaireAction"
>
<forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
</action>
L'action /init n'est utilisée qu'une fois lors de la construction initiale de l'objet DynaFormulaire. Elle a pour but de fournir du contenu aux trois listes du formulaire combo, listeSimple, listeMultiple. Ce contenu est fourni sous forme de trois tableaux, propriétés de l'objet dynaFormulaire :
<form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
<form-property name="opt" type="java.lang.String" initial="non"/>
...
<form-property name="valeursCombo" type="java.lang.String[]" />
<form-property name="valeursListeSimple" type="java.lang.String[]" />
<form-property name="valeursListeMultiple" type="java.lang.String[]"/>
</form-bean>
Une fois que les tableaux valeursCombo, valeursListeSimple, valeursListeMultiple auront été initialisés par InitFormulaireAction, ils n'auront plus besoin de l'être. En effet, l'objet dynaFormulaire est placé dans la session et conserve donc sa valeur au fil des cycles demande-réponse. C'est pourquoi l'action /init n'est exécutée qu'une fois. Le code de InitFormulaireAction est le suivant :
package istia.st.struts.formulaire;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class InitFormulaireAction
extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// prépare le formulaire à afficher
// on met les informations nécessaires au formulaire dans son bean
DynaFormulaire formulaire = (DynaFormulaire) form;
formulaire.set("valeursCombo", getValeurs(5, "combo"));
formulaire.set("valeursListeSimple", getValeurs(7, "simple"));
formulaire.set("valeursListeMultiple", getValeurs(10, "multiple"));
// on rend la main
return mapping.findForward("afficherFormulaire");
} //execute
// liste des valeurs du combo
private String[] getValeurs(int taille, String label) {
String[] valeurs = new String[taille];
for (int i = 0; i < taille; i++) {
valeurs[i] = label + i;
}
return valeurs;
}
}
- la classe dérive de la classe Action. C'est obligatoire.
- le contrôleur Struts utilise un objet Action via sa méthode execute. C'est donc elle qu'il faut redéfinir. Cette méthode reçoit les pramètres suivants :
- ActionMapping mapping : un objet représentant la configuration de l'aplication dans struts-config.xml
- ActionForm form : le formulaire associé à l'action s'il y en a un défini dans la configuration de l'action (attribut name de l'action).
- HttpServletRequest request : la requête du client
- HttpServletResponse : la réponse au client
- la classe InitFormulaireAction doit initialiser le formulaire dynaFormulaire. Celui arrive à la méthode execute sous la forme du paramètre ActionForm form. Rappelons que dynaFormulaire est de type DynaFormulaire, classe dérivée de la classe DynaActionForm elle-même dérivée de la classe ActionForm.
- dans la méthode execute, des valeurs sont affectées aux trois champs valeursCombo, valeursListeSimple, valeursListeMultiple grâce à la méthode set de la classe DynaActionForm. Ces valeurs sont des tableaux arbitraires par souci de simplicité. Remarquons que la méthode set affecte une valeur à un champ existant. Elle ne peut pas servir à créer de nouveaux champs. C'est pourquoi, il est nécessaire de définir les trois champs valeursCombo, valeursListeSimple, valeursListeMultiple dans la définition de l'objet dynaFormulaire dans struts-config.xml.
- la méthode execute se termine en renvoyant au contrôleur la clé de la vue à afficher comme réponse au client. Ici, c'est la clé afficherFormulaire qui dans le fichier struts-config.xml a été associée à la vue /vues/formulaire.jsp.
6.6. Déploiement
L'arborescence de l'application est la suivante :
![]() | ![]() |
![]() | ![]() |


Rappelons que le fichier ApplicationResources.properties ci-dessus est nécessaire à la bibliothèque de balises struts-bean. On sait que ce fichier contient les messages de l'application. Ceux-ci sont accessibles à la bibliothèque struts-bean. Ici, notre application ne définit aucun message. Aussi le fichier ApplicationResources.properties existe mais est vide.
6.7. Conclusion
Nous avons détaillé dans cette leçon la façon de gérer les différents composants d'un formulaire HTML. Nous pouvons maintenant utiliser des formulaires complexes dans nos applications Struts.






