Skip to content

6. HTML Forms

So far, we have used a single form containing only two input fields. Here, we propose to create and process a form using standard graphical components (radio buttons, checkboxes, input fields, combo boxes, lists).

6.1. The application views

The application will have only two views. The first displays a blank form:

VUE 1 - form

Image

This first view, named formulaire.jsp, will allow us to implement various tags from the struts-html library. The user fills out the form:

Image

The [Envoyer] button provides confirmation of the entered values. This will be the second view:

Image

This second view will allow us to use two other Struts tag libraries: struts-bean and struts-logic. The link [Retour au formulaire] allows us to return to the form as it was filled out. We are then taken back to the first view.

6.2. The application architecture

  • The form (view 1) will be represented by a dynamic Struts object named dynaFormulaire, a subclass of DynaActionForm. It will be displayed by the view formulaire.jsp.
  • The Struts action InitFormulaireAction will be responsible for retrieving the data required to display the form
  • The completed form will be processed by action ForwardAction, which will simply redirect the request to the second view, confirmation.jsp. This view will be responsible for displaying the form values.

6.3. Application Configuration

6.3.1. The server.xml file

The application context will be named /form2. We will therefore add the following line to the Tomcat file server.xml:

    <Context path="/formulaire2" docBase="e:/data/serge/web/struts/formulaire2" />

Once this is done, we may need to restart Tomcat so that it takes the new context into account. We can verify its validity by requesting URL http://localhost:8080/formulaire2:

Image

6.3.2. The web.xml file

The application's configuration file web.xml will be as follows:

<?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>

Compared to the web.xml configuration files we’ve already seen, we’re making a few changes:

  • We are introducing two new tag libraries: struts-bean and struts-logic. They will be used in the confirmation.jsp view. The formulaire.jsp view, on the other hand, will use the struts-html library.

6.3.3. The struts-config.xml file

The struts-config.xml file will be as follows:

<?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>

It contains three main sections:

  • form declarations in the <form-beans> section
  • the declaration of actions in the <action-mappings> section
  • the declaration of the resource file in <message-resources>

6.3.4. The application's form objects (beans)

The objects used to represent the application’s HTML forms are objects of type ActionForm or derived types (DynaActionForm, DynaValidatorForm, ...). They are called beans because their construction follows the rules of JavaBeans. There is only one form bean in our application, called dynaFormulaire and of a type derived from DynaActionForm. It will be used in the following situations:

  • to contain the data needed to display view #1
  • retrieve the values from the form in view #1 when the user submits it (submit)
  • contain the data required to display view #2

The structure of the dynaFormulaire bean is closely linked to the form in view #1. Let’s examine it:

No.
Type HTML
Role
1
<input name="opt" type="radio" value="yes">
<input name="opt" type="radio" value="no">
group of radio buttons linked together (same name)
2
<input name="chk1" type="radio" value="on">
<input name="chk2" type="radio" value="on">
<input name="chk3" type="radio" value="on">
groups of checkboxes
(not the same name)
3
<input type="text" name="champSaisie" >
an input field
4
<input type="password" name="mdp">
a password field
5
<textarea name="boiteSaisie">...</textarea>
a multi-line input field
6
<select name="combo" size="1">..</select>
a combo box
7
<select name="listeSimple" size="3">..</select>
a single-select list
8
<select name="listeMultiple" size="3" multiple>..</select>
a multiple-select list
9
<input type="button" value="Clear"
onclick='clearList("simpleList")'>
button to deselect
selected items in listeSimple (7)
10
<input type="button" value="Clear"
onclick='clearList("multipleList")'>
button to deselect
the selected items in listeMultiple (8)
11
<input type="submit" value="Submit">
submit button on the form
12
<input type="hidden" name="secret" value="...">
a hidden field

Let's distinguish several cases:

  1. The dynaFormulaire object is used to hold the values from the HTML form above, which will be submitted via the [Envoyer] button. It must therefore have the same fields as in the HTML form. The field type is determined by the following rule:
  • if the HTML field provides only one value, then the dynaFormulaire field will be of type java.lang.String
  • if the field HTML provides multiple values, then the field dynaFormulaire will be of type java.lang.String[]

In the HTML form above, only the listeMultiple field can be associated with multiple values (those selected by the user). Therefore, an initial definition of the dynaFormulaire object would be as follows:

        <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>            

How will dynaFormulaire be populated with the values from the HTML form sent by the web client?

opt
the opt field will receive the value "yes" if the HTML <input type="radio" name="opt" value="yes"> field has been checked, the value "no" if the field <input type="radio" name="opt" value="no"> has been checked.
chk1
the chk1 field will receive the value "on" if the field HTML <input name="chk1" type="radio" value="1"> has been checked, otherwise nothing. In the latter case, the chk1 field will retain its previous value.
chk2
same
chk3
same
champSaisie
The field champSaisie will receive the text entered by the user in the field HTML <input type="text" name="champSaisie">. This text may be an empty string.
mdp
The "mdp" field will receive the text entered by the user in the field HTML <input type="password" name="mdp">. This text may be an empty string.
boiteSaisie
The boiteSaisie field will receive the text entered by the user in the HTML field <textarea name="boiteSaisie">...</textarea>. This text forms a single string, consisting of the lines typed by the user, separated from one another by the character sequence "\r\n". The resulting text may be an empty string.
combo
The combo field will receive the option selected by the user in the HTML field <select name="combo" size="1">..</select>. The selected option is the one that appears in the combo box. If the selected option HTML is of the type <option value="XX">YY</option>, the combo box will receive the value "XX". If the selected option HTML is of the type <option>YY</option>, the combo box will receive the value "YY".
listeSimple
the listeSimple field will receive the option selected by the user in the HTML field <select name="listeSimple" size="..">..</select> if there is one. If there is none, the listeSimple field will not receive any value and will retain its previous value. The value actually assigned to the listeSimple field follows the rules specified for the combo box.
listeMultiple
the field listeMultiple of type String[] will receive the options selected by the user in the field HTML <select name="listeMultiple" size=".." multiple>..</select> if any. If there are none, the array listeMultiple will not receive any values and its content will remain unchanged. The values actually assigned to the listeMultiple array follow the rules specified for the combo box.
secret
The secret field will receive the value XX from the HTML field <input type="hidden" name="secret" value="XX">. This text may optionally be an empty string.
  1. The dynaFormulaire object is used to provide the initial content for view #1. The values of the preceding fields will be used for the following purposes:
opt
must have the value "yes" or "no" so that the browser knows which radio button to select
chk1
if chk1 has the value "on", the checkbox will be checked; otherwise, it will not be
chk2
same
chk3
same
champSaisie
The field value will be displayed in the input field champSaisie
mdp
the field value will be displayed in the password entry field
boiteSaisie
The field value will be displayed in the input field boiteSaisie
combo
The value of this field indicates which combo box item should be selected when the form is displayed
listeSimple
same
listeMultiple
The values in table listeMultiple indicate which items in the multiple-select list should be selected when the form is displayed
secret
The value of the field will be assigned to the value attribute of the secret field HTML.

View No. 1 requires additional information:

  • the list of values to display in the drop-down list
  • the list of values to display in the list listeSimple
  • the list of values to display in the list listeMultiple

There are several ways to provide this information to the view. Arrays placed in the request passed to the view would, for example, do the trick. Here, we place these arrays in the dynaFormulaire bean:

        <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>            

The dynaFormulaire form will be initialized by the /init action, which will call an object derived from Action named InitFormulaireAction. This object will be responsible for creating the three arrays needed to display the three lists and placing them in the dynaFormulaire bean. The configuration file gives this bean a scope equal to the session. This means that the Struts controller will place this bean in the session. We will therefore not need to regenerate it between request-response cycles. Consequently, the /init action will be called only once.

  1. The dynaFormulaire object is also used to provide the content for view #2. This view simply displays the values.

6.3.5. Application Actions

Actions are handled by objects of type Action or derived types. Actions are configured within the <action-mappings> tags:

    <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>

Note that there isn’t always a form associated with an action. This is the case, above, with the /affiche action. Before detailing each action, let’s review how the action-form pair works within an <action> tag:

  • An action begins with a request from a web client and ends with the sending of a response page. This is the client-server web request-response cycle. The request is received by the Struts controller of type ActionServlet or a derived type. This controller also sends the response.
  • The form bean of type ActionForm or a derived type is created if it does not already exist. The controller checks whether it can find an object named name in the scope specified by scope. If so, it uses it. If not, it creates it and places it in the scope specified by scope, associated with the attribute specified by name.

In the example of the /init action, for instance, the controller will call request.getSession().getAttribute("dynaFormulaire") to determine whether dynaFormulaire has already been created or not. If not, it will create it and add it to the session using a statement like request.getSession().setAttribute("dynaFormulaire", new DynaFormulaire(...)).

  • The controller will also look for an Action object of the type specified by the type attribute. If it does not find one, it creates it; otherwise, it uses it.
  • The reset method of the form bean will be called. This bean, except during its initial creation, is reused. It therefore contains data that you may want to "clean up." This is done in the reset method of the ActionForm bean or its derived class.
  • If the action is the target of a submitted form, then the form values found in the client request are copied into the fields of the same name in the form bean. Note that the reset method was called before this copying.
  • If the configuration specifies the attribute validate="true", the validate method of the form bean will be called. This method must then validate the bean’s data. This validation usually occurs only when the form has just received new data via a posted form and you want to verify the validity of that data. This method returns any list of errors to the controller in a ActionErrors object.
  • If the ActionErrors object is not empty, the controller displays the view specified by the action’s input attribute.
  • If data validation is not requested or if it was successful, the controller executes the `execute` method of the `Action` object or derived class associated with the current action. It is within this method that the web client’s request is processed. The `execute` method returns a `ActionForward` object indexed by string keys. These keys are those declared by the forward tags of the configured action. In our example, the /init action has a single forward tag. It associates the key "afficherFormulaire" with the view formulaire.jsp.
  • The controller displays the view associated with the received key. This view may actually be an action, in which case the previous process is repeated.

The /init action

        <action
          path="/init"
            name="dynaFormulaire"
            validate="false" 
            scope="session"
          type="istia.st.struts.formulaire.InitFormulaireAction"
      >
            <forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
        </action>
  • The /init action normally occurs once during the first request-response cycle when the user requests the URL http://localhost:8080/form2/init.do
  • the dynaFormulaire object is created or recycled. It is retrieved (recycling) or placed (creation) in the session as specified by the scope attribute.
  • Its reset method is called. What should it do? Normally, the fields of the ActionForm object are reset to their default values. However, in this case, we will not do so, because the dynaFormulaire object is placed in the session (scope="session"). The fields of dynaFormulaire must therefore retain their values. What are these values when the dynaFormulaire object is initially created? There are two cases:
  • the field has an initial value specified in the configuration file:
            <form-property name="opt" type="java.lang.String" initial="non"/>

In this case, the Struts controller will create this field with this initial value.

  • the field has no initial value specified in the configuration: Java’s initialization rules apply. Generally, numeric fields will have the value zero, strings will have the empty string, and other objects will have the value null.

Let’s look at the initial configuration of 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>            

The initial values of the fields in dynaFormulaire after its creation will be as follows:

Field
Initial Value
opt
"no"
chk1, chk2, chk3
empty string
champSaisie
empty string
password
empty string
boiteSaisie
empty string
combo
empty string
listeSimple
empty string
listeMultiple
array of empty strings
secret
"xxx"
comboValues, singleList, multipleList
array of empty strings
  • One might imagine that the reset method of dynaFormulaire assigns values to the three arrays that populate the three lists in the formulaire.jsp view. This would be possible here because the data in these three arrays is generated arbitrarily. However, the most common scenario is that this data comes from the application model, the M in MVC. Here, we will take a middle ground—to keep the example simple—by having these values generated by the action InitFormulaireAction, and thus by the C of MVC.
  • There is no requirement to write a reset method in dynaFormulaire, since the class ActionForm from which it derives has such a method that does nothing (no initializations).
  • Once the reset method of dynaFormulaire is called, the controller checks the validate attribute of the action. Here, it has the value "false". The validate method of dynaFormulaire will not be called.
  • The InitFormulaireAction object is created or recycled if it already existed, and its execute method is launched. This method will assign arbitrary values to the three arrays of dynaFormulaire: valeursCombo, valeursListeSimple, and valeursListeMultiple. The method returns a ActionForward with the key "afficherFormulaire".
  • The controller displays the view /vues/formulaire.jsp, which was associated with the key "afficherFormulaire" by a forward tag from the /init action.

The /confirmation action

      <action
          path="/confirmation"
            name="dynaFormulaire"
            validate="false" 
            scope="session"
          parameter="/vues/confirmation.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
  • The /confirmation action occurs when the user clicks the [Envoyer] button on view #1. The browser then "posts" the form filled out by the user to the Struts controller.
  • The dynaFormulaire object is retrieved from the session
  • its reset method is called. Once it has been called, the Struts controller will copy the values of the form fields posted by the client into the fields of the same name in dynaFormulaire. Let’s review the list of fields in the latter and see how this copying works:
Field
Associated HTML code
Field value
after copying the form values
opt
<input type="radio" name="opt" value="yes">Yes
<input type="radio" name="opt" value="no" checked="checked">No
- "yes" or "no" depending on the selected radio button
chk1
<input type="checkbox" name="chk1" value="on">
- "on" if the chk1 checkbox has been checked
- retains its previous value if the chk1 checkbox has not been checked
chk2
<input type="checkbox" name="chk2" value="on">
- "on" if the chk2 checkbox has been checked
- retains its previous value if the chk2 checkbox has not been checked
chk3
<input type="checkbox" name="chk2" value="on">
- "on" if the chk3 checkbox has been checked
- retains its previous value if the chk3 checkbox has not been checked
champSaisie
<input type="text" name="champSaisie" value="">
- value entered by the user in champSaisie
password
<input type="password" name="mdp" value="">
- value entered by the user in mdp
boiteSaisie
<textarea name="boiteSaisie"></textarea>
- value entered by the user in boiteSaisie
combo
<select name="combo">...</select>
- value selected by the user in combo
listeSimple
<select name="listeSimple" size="3">...</select>
- value selected by the user in listeSimple
listeMultiple
<select name="listeMultiple" multiple="multiple" size="5">
- array of strings containing the values selected by the user in listeMultiple
secret
<input type="hidden" name="secret" value="xxx">
- "xxx".

We encounter an issue with fields that do not necessarily receive a value in the request sent by the browser. This applies to checkboxes chk1 through chk3 and the two lists listeSimple and listeMultiple. In this case, these fields retain their previous values, those acquired during the previous request-response cycle.

Let’s consider the checkbox chk1, for example, and assume that in the previous request-response cycle, the user had checked this box. The browser then sent the information chk1="on" in the parameter string of its request. The server therefore assigned the value "on" to the chk1 field of dynaFormulaire. Now suppose that in the current cycle, the user does not check the chk1 checkbox. In this case, in the parameter string of the new request, the browser does not send something like chk1="off" but sends nothing. As a result, the chk1 field in dynaFormulaire will retain its "on" value and thus have a value that does not reflect that of the form validated by the user. We will use the reset method of dynaFormulaire to resolve this issue. In this method, we will set the three fields chk1, chk2, and chk3 to "off". In our example with chk1, either the user:

  • checks the chk1 checkbox. Then the browser sends the information chk1="on" and the chk1 field in dynaFormulaire will change to "on"
  • do not check the chk1 box. In that case, the browser does not send a value for the chk1 field, which will retain its previous "off" value. In both cases, the value stored in the chk1 field of dynaFormulaire is correct.

The issue is similar for the two lists listeSimple and listeMultiple. If no option has been selected from these lists, they will not be included in the query parameters and will therefore retain their previous values. In the reset method of dynaFormulaire, we will reset listeSimple to an empty string and listeMultiple to an array of strings of length 0.

  • Once the reset method of dynaFormulaire is called, the controller copies the information sent to it in the client request back into the fields of dynaFormulaire
  • A ForwardAction object is created or recycled, and its execute method is called. ForwardAction is a predefined class that returns a ActionForward object pointing to the view defined by the action’s “parameter” attribute, in this case /vues/confirmation.jsp.
  • The controller sends this view. The cycle is complete.

The action /displays

      <action
          path="/affiche"
          parameter="/vues/formulaire.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
  • The /display action is triggered by clicking the [Retour vers le formulaire] link in view #2.
  • Here, there is no form associated with the action. We therefore proceed immediately to executing the execute method of a ForwardAction object, which will return a ActionForward object pointing to the view /vues/formulaire.jsp.

6.3.6. The application's message file

The third section of the struts-config.xml file is the message file:

        <message-resources 
          parameter="ApplicationResources"
            null="false"
      />    

The file ApplicationResources.properties is located in WEB-INF/classes. It will be empty. Even though it is empty, it must still be declared in the configuration file; otherwise, the struts-bean tag library, which we will discuss later, will generate an error. This library is used by the view confirmation.jsp.

6.4. The view code

6.4.1. The formulaire.jsp view

Remember that this view is displayed in two cases:

  • when the /init action is called during the first request-response cycle
  • when the /affiche action is called during subsequent cycles

The code for the formulaire.jsp view is as follows:

<%@ 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>

This JSP page uses tags from the struts-html library. Remember that to use a tag library, you must:

  • declare it in the application's web.xml file using a <tag-lib> tag
  <taglib>
      <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
  </taglib>
  • Place the code for this library somewhere in the application directory tree, here WEB-INF/struts-html.tld
  • Declare the use of this library at the beginning of the JSP pages that use it:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

The formulaire.jsp view uses tags that we will now explain:

tag
<body background="<html:rewrite page="/images/standard.jpg"/>">
HTML translation
<body background="/formulaire2/images/standard.jpg">
explanation
The html:rewrite tag allows you to omit the application name in URL. It has one attribute:
page
URL to be rewritten
So, as shown above, if you decide to name the application "form3," the code for the background attribute does not need to be rewritten. The html:rewrite tag will generate the new code HTML
background="/formulaire3/images/standard.jpg"
tag
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
HTML translation
<form name="dynaFormulaire" method="post" action="/formulaire2/confirmation.do">
explanation
The html:form tag generates the HTML form tag. It has several attributes:
action
Struts action to which the form must be posted—must correspond to one of the actions defined in struts-config.xml
name
optional - name of the ActionForm bean or derived bean in which the values of the posted form must be placed or read. If this attribute is missing, the form associated with the action defined by the action attribute is used. This information is found in the configuration file (name attribute of the action).
type
optional - Java class to be instantiated for the form. If this attribute is missing, the class associated with the action defined by the action attribute is used. This information is found in the configuration file (the action’s type attribute).
We can see that by default, the generated code HTML uses the method POST. In this same code HTML, the action’s URL has been rewritten to be prefixed with the application name and suffixed with .do.
tag
<html:radio name="dynaFormulaire" property="opt" value="yes">Yes</html:radio>
HTML translation
<input type="radio" name="opt" value="oui">
explanation
The html:radio tag is used to generate the HTML <input type="radio" ...> tag. It supports various attributes:
name
optional - name of the ActionForm bean or derived bean in which the field value must be placed or read. If this attribute is missing, the form associated with the <html:form> tag is used.
property
name of the field in the form bean associated with the read/write radio button.
value
optional - value to be assigned to the HTML field
The text between the start and end tags is the text that will be displayed next to the radio button.
tag
<html:checkbox name="dynaFormulaire" property="chk1">1</html:checkbox>
HTML translation
<input type="checkbox" name="chk1" value="on">
explanation
The html:checkbox tag is used to generate the HTML <input type="checkbox" ...> tag. It supports various attributes:
name
optional - name of the ActionForm bean or derived bean in which the field value must be placed or read. If this attribute is omitted, the form associated with the <html:form> tag is used.
property
name of the field in the form bean associated with the read-write checkbox.
value
optional - value to be assigned to the HTML field
The text between the start and end tags is the text that will be displayed next to the checkbox.
tag
<html:text name="dynaFormulaire" property="champSaisie" />
HTML translation
<input type="text" name="champSaisie" value="">
explanation
The html:text tag is used to generate the HTML <input type="text" ...> tag. It supports various attributes:
name
optional - name of the ActionForm bean or derived bean in which the field value must be placed or read. If this attribute is missing, the form associated with the <html:form> tag is used.
property
name of the field in the form bean associated with the read-write input field.
value
optional - value to be assigned to the HTML field
tag
<html:password name="dynaFormulaire" property="mdp" />
HTML translation
<input type="password" name="mdp" value="">
explanation
The html:password tag is used to generate the HTML <input type="password" ...> tag. It supports various attributes:
tag
<html:textarea name="dynaFormulaire" property="boiteSaisie" />
HTML translation
<textarea name="boiteSaisie"></textarea>
explanation
The html:textarea tag is used to generate the HTML <textarea>...</textarea> tag. It supports various attributes:
name
optional - name of the ActionForm bean or derived bean in which the field value must be placed or read. If this attribute is missing, the form associated with the <html:form> tag is used.
property
name of the field in the form bean associated with the password field, which is read-write.
value
optional - value to be assigned to the HTML field
tag
<html:select name="dynaFormulaire" property="combo">....</html:select>
HTML translation
<select name="combo">...</select>
explanation
The html:select tag is used to generate the HTML <select>...</select> tag. It supports various attributes:
name
optional - name of the ActionForm bean or derived bean in which the field value must be placed or read. If this attribute is missing, the form associated with the <html:form> tag is used.
property
Name of the field in the form bean associated with the read-write input field.
value
optional - value to assign to the HTML field. The option from the combo box with this value will be selected.
tag
<html:select name="dynaFormulaire" property="combo">
<html:options name="dynaFormulaire" property="valeursCombo"/>
</html:select>
HTML translation
<option value="combo1">combo1</option>
<option value="combo2">combo2</option>

explanation
The html:options tag is used to generate the HTML <option>...</option> within a HTML <select> tag. There are various ways to specify how to find the values to populate the select element. Here, we have used the name and property attributes:
name
optional - name of the ActionForm bean or derived bean in which the field value must be placed or read. If this attribute is missing, the form associated with the <html:form> tag is used.
property
name of the field in the form bean that contains the select values. This must be an array of character strings.

The other two lists are generated in a similar manner to the previous one:

          <html:select name="dynaFormulaire" property="listeSimple" size="3">
            <html:options name="dynaFormulaire" property="valeursListeSimple"/>            
        </html:select>

Above, we specify a size attribute other than 1 to get a list instead of a combo box.

<html:select name="dynaFormulaire" property="listeMultiple" size="5" multiple="true">
        <html:options name="dynaFormulaire" property="valeursListeMultiple"/>                
    </html:select>

Above, we specify the multiple="true" attribute to create a list with multiple selections.

tag
<html:hidden name="dynaFormulaire" property="secret"/>
HTML translation
<input type="hidden" name="secret" value="xxx">
explanation
The html:hidden tag is used to generate the HTML <input type="hidden" ...> tag.
name
optional - name of the ActionForm bean or derived bean in which the field value must be placed or read. If this attribute is missing, the form associated with the <html:form> tag is used.
property
name of the field in the form bean associated with the hidden field. The value "xxx" assigned to the secret field HTML comes from the form definition in the configuration file. An initial value of "xxx" was defined there for the secret field.

To fully understand the relationship between the formulaire.jsp view and the dynaFormulaire bean that represents it in memory, it is important to remember that the dynaFormulaire bean is used for both reading and writing:

The request occurs when the user clicks the [Envoyer] button on the form. The browser then "submits" the HTML form to the /confirmation action. We have already explained what happens then, and in particular that the fields in dynaFormulaire will receive the values of the fields with the same names in the HTML form.

What happens when the controller requests the display of view formulaire.jsp in response to a request? Let’s review the tags one by one:

tag
<body background="<html:rewrite page="/images/standard.jpg"/>">
function
generates the code HTML
<body background="/formulaire2/images/standard.jpg">
tag
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
...
</html:form>
function
generates the code HTML
<form name="dynaFormulaire" method="post" action="/formulaire2/confirmation.do">
tag
<html:radio name="dynaFormulaire" property="opt" value="yes">Yes</html:radio>
<html:radio name="dynaFormulaire" property="opt" value="no">No</html:radio>
function
If the opt field of dynaFormulaire is "yes", generate the code HTML
<input type="radio" name="opt" value="oui" checked="checked">Oui
<input type="radio" name="opt" value="non">Non
tag
<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>
function
If the chk1 and chk3 fields of dynaFormulaire are "on" and the chk2 field is "off", generate the code HTML
<input type="checkbox" name="chk1" value="on" checked="checked">1
<input type="checkbox" name="chk2" value="on">2
<input type="checkbox" name="chk3" value="on" checked="checked">3                                                
tag
<html:text name="dynaFormulaire" property="champSaisie" />
function
if the field champSaisie is "this is a test", generate the code HTML
<input type="text" name="champSaisie" value="ceci est un essai">
tag
<html:password name="dynaFormulaire" property="mdp" />
function
if the password field is "azerty", generate the code HTML
<input type="password" name="mdp" value="azerty">
tag
<html:password name="dynaFormulaire" property="mdp" />
function
if the mdp field is "azerty", generates the code HTML
<input type="password" name="mdp" value="azerty">
tag
<html:password name="dynaFormulaire" property="mdp" />
function
if the mdp field is "azerty", generates the code HTML
<input type="password" name="mdp" value="azerty">
tag
<html:select name="dynaFormulaire" property="combo">
<html:options name="dynaFormulaire" property="valeursCombo"/>
</html:select>
function
if the combo field is "combo2", generates the code HTML
<select name="combo">
    <option value="combo0">combo0</option>
    <option value="combo1">combo1</option>
    <option value="combo2" selected="selected">combo2</option>
    <option value="combo3">combo3</option>
    <option value="combo4">combo4</option>
</select>
tag
<html:select name="dynaFormulaire" property="listeSimple" size="3">
<html:options name="dynaFormulaire" property="valeursListeSimple"/>
</html:select>
function
if the listeSimple field is "simple1", generates the HTML code
<select name="listeSimple" size="3">
    <option value="simple0">simple0</option>
    <option value="simple1" selected="selected">simple1</option>
    <option value="simple2">simple2</option>
...
</select>
tag
<html:select name="dynaFormulaire" property="listeMultiple" size="5" multiple="true">
<html:options name="dynaFormulaire" property="valeursListeMultiple"/>
</html:select>
function
if the listeMultiple field is the array {"multiple0","multiple2"}, generates the HTML code
<select name="listeMultiple" multiple="multiple" size="5">
    <option value="multiple0" selected="selected">multiple0</option>
    <option value="multiple1">multiple1</option>
    <option value="multiple2" selected="selected">multiple2</option>
    <option value="multiple3">multiple3</option>
...
</select>
tag
<html:hidden name="dynaFormulaire" property="secret"/>
function
if the secret field has the value "xxx", generates the code HTML
<input type="hidden" name="secret" value="xxx">
tag
<html:submit>Submit</html:submit>
function
generates the code HTML
<input type="submit" value="Envoyer">

The last thing to explain is the code javascript included in the page JSP and linked to the two buttons [Effacer] that deselect the selected items in the lists listeSimple and listeMultiple:

<input type="button" value="Effacer" onclick="this.form.listeSimple.selectedIndex=-1"/>                                
<input type="button" value="Effacer" onclick="this.form.listeMultiple.selectedIndex=-1"/>

The tag

<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">

generates the following HTML code:

<form name="dynaFormulaire" method="post" action="/formulaire2/confirmation.do">

To understand the Javascript code associated with the [Effacer] buttons, let’s review how the various elements of a web document are designated within a Javascript code that processes this document:

Data
Meaning
document
refers to the entire web document
document.forms
refers to the collection of forms defined in the document
document.forms[i]
refers to form number i in the document
document.forms["nomFormulaire"]
refers to the <form> form with the name attribute equal to "nomFormulaire"
document.nomFormulaire
refers to the form <form> with the attribute name set to "nomFormulaire"
document.[formulaire].elements
refers to the collection of elements belonging to the form designated by the expression [formulaire]. This collection includes all <input>, <textarea>, and <select> tags in the designated form.
document.[formulaire].elements[i]
refers to element number i of [formulaire]
document.[formulaire].elements["nomComposant"]
refers to the element in [formulaire] with the attribute name equal to nomComposant
document.[formulaire]. nomComposant
refers to the element of [formulaire] with the attribute name equal to nomComposant
document.[formulaire].[composant].value
refers to the value of the [composant] component of the [formulaire] form when the HTML code of the form can have a value attribute (<input>, <textarea>)
document.[formulaire].[select].selectedIndex
refers to the index of the option selected in a list. Can be used for reading and writing. Setting this property to -1 deselects all items in the list.
document.[formulaire].[select].options
refers to the array of options associated with a <select> tag
document.[formulaire].[select].options[i]
refers to the i-th option of the specified <select> tag
document.[formulaire].[select].options[i].selected
Boolean indicating whether the option #i of the specified [select] tag is selected (true) or not. Can be used for reading and writing

Let’s revisit the code for the two buttons:

<input type="button" value="Effacer" onclick="this.form.listeSimple.selectedIndex=-1"/>                                
<input type="button" value="Effacer" onclick="this.form.listeMultiple.selectedIndex=-1"/>

When the button is clicked, the code associated with the "onclick" attribute is executed. Here, it is inline code. Most often, we write onclick=&quot;function(...)&quot;, where function is a function defined within a **&lt;script language=&quot;javascript&quot;&gt;...&lt;/script&gt;** tag. What does the code above do? Let’s comment out the code for the first button:

this
refers to the web document in which the button is located
this.form
refers to the form in which the button is located
this.form.listeSimple
refers to the listeSimple component of the form
this.form.listeSimple.selectedIndex
refers to the index of the option selected in listeSimple. Setting this property to -1 deselects all option.

6.4.2. The confirmation.jsp view

Recall that this view is displayed following the /confirmation action, c.a.d, after the form contained in the formulaire.jsp view has been submitted by the web client. Its sole purpose is to display the values entered by the user. Its code is as follows:

<%@ 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>

Here we introduce two new tag libraries: struts-bean and struts-logic. The struts-bean library provides access to objects in the request, session, or application context. The struts-logic library allows you to introduce execution logic using tags. Neither of these libraries is essential. As we have seen, a JSP page can:

  • retrieve objects from the request (request.getAttribute(...)), the session (session.getAttribute(...), or the application context
  • include dynamic parts in the HTML code using variables <%= variable %>
  • contain Java code <% Java code %>

The inclusion of Java code in JSP pages is a source of frustration for anyone who wants a strict separation between application logic (Java code) and presentation (use of tags). That is why tag libraries were created for them.

We will proceed as we did for the formulaire.jsp view and explain each of the tags present in the confirmation.jsp code if they have not already been encountered in the formulaire.jsp view. First, note that the page begins by declaring the three tag libraries it will use:

<%@ 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" %>

Note also that these three libraries must be declared in the application's web.xml file. We will now comment on the tags in the formulaire.jsp document:

tag
<bean:write name="dynaFormulaire" scope="session" property="opt"/>
function
writes a value to the current HTML stream. The bean:write tag supports the following attributes:
name: name of the object to use
scope: scope (request, session, context) in which to search for this object
property: field of the object designated by name whose property is to be written. This field can be an object of any type. The toString method of the object will be used.
Here, the value of the opt field of dynaFormulaire is written. The result will be either "yes" if the user has checked the radio button with the attribute value="yes", or "no" if they have checked the radio button with the attribute value="no"
tag
<bean:write name="dynaFormulaire" scope="session" property="chk1"/>
function
writes the value of the chk1 field from dynaFormulaire. The result will be either "on" if the user has checked the box, or "off" otherwise. The same applies to chk2 and chk3.
tag
<bean:write name="dynaFormulaire" scope="session" property="champSaisie"/>
function
writes the value of the champSaisie field from dynaFormulaire, i.e., the text entered by the user in that field. The same applies to mdp, boiteSaisie.
tag
<bean:write name="dynaFormulaire" scope="session" property="combo"/>
function
writes the value of the combo field dynaFormulaire. This will be the value attribute of the <option> element selected by the user.
tag
<bean:write name="dynaFormulaire" scope="session" property="listeSimple"/>
function
writes the value of the listeSimple field from dynaFormulaire. This will be the value attribute of the <option> element selected by the user, if one was selected. Otherwise, it will be an empty string.
tag
            <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>
function
Here, we introduce logic tags. We are dealing with a multiple-choice list. The value of the listeMultiple field of the dynaFormulaire object is an array of String. In Java, we would write a loop. The logic:iterate tag allows us to perform this same loop without writing Java code. In this example, the logic:iterate tag has the following attributes:
name="dynaFormulaire": name of the object to use
property="listeMultiple": name of the property in the object specified by name that contains the collection to be iterated over in the loop. Here, this collection is the array of values selected in listeMultiple. This array may be empty.
id="choice": an identifier denoting the current element in the array at each iteration of the loop. During the first iteration, choice will represent listeMultiple[0]; during the second, listeMultiple[1]; and so on.
indexID="index": identifier designating the index of the current array element in each loop iteration. During the first iteration, index will have the value 0, during the second the value 1, and so on.
The code HTML contained between the <logic:iterate ...> and </logic:iterate> tags is repeated for each element of the collection designated by the pair (name,property). The dynamic part of this code is as follows:
          <td>liste multiple[<bean:write name="index"/>]</td>
          <td><bean:write name="choix"/></td>
Based on what was stated previously, at iteration number i (i>=0), the generated code HTML is equivalent to the following code:
          <td>liste multiple[<%=i%>]</td>
          <td><%=listeMultiple[i]%></td>
tag
    <html:link page="/affiche.do">
            Retour au formulaire
        </html:link>    
function
generates a link relative to the application context, which eliminates the need to know the context. The HTML code generated by this tag is as follows:
<a href="/formulaire2/affiche.do">Retour au formulaire</a>

6.5. The Java classes

The struts-config.xml configuration file references two Java classes:

        <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"
      >

The DynaFormulaire class is the class that will contain the values from view #1 formulaire.jsp. The InitFormulaireAction class is the class that will process the values of the form submitted by the [Envoyer] button from formulaire.jsp.

6.5.1. The class DynaFormulaire

To hold the values of a form, an object of type DynaActionForm is sufficient unless you need to override one of the reset or validate methods of this class. Here, the validate method does not need to be overridden since no data validation is performed. However, the reset method does need to be overridden. This is because the fields of the DynaFormulaire object will receive their values from the form submitted by the web client. However, some fields may not receive a value if they are not present in the request. This occurs in the following cases:

  • a checkbox that was not checked by the user
  • a list with more than one item, or no option has been selected

For forms containing this type of component, the reset method must

  • set the value "off" for the field associated with the checkbox
  • assign the empty string to the field associated with a single-select list
  • assign an empty array of character strings to the field associated with a multi-select list

Thus, if these fields do not receive a value from the request, they retain the value assigned by reset, which corresponds to the state of the component in the form validated by the user (checkbox unchecked, list with no items selected).

The code for class DynaFormulaire, a subclass of DynaActionForm, is as follows:

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 checkboxes - value off
    set("chk1","off");
    set("chk2","off");
    set("chk2","off");
    // reset listeSimple - empty string
    set("listeSimple","");
     // reset listeMultiple - empty table
    set("listeMultiple",new String[]{});
  }
}

6.5.2. The InitFormulaireAction class

The InitFormulaireAction class is associated with the /init action in the struts-config.xml file:

      <action
          path="/init"
            name="dynaFormulaire"
            validate="false" 
            scope="session"
          type="istia.st.struts.formulaire.InitFormulaireAction"
      >
            <forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
        </action>

The /init action is used only once during the initial construction of the DynaFormulaire object. Its purpose is to populate the three combo boxes in the form: listeSimple and listeMultiple. This content is provided in the form of three arrays, which are properties of the dynaFormulaire object:

        <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>            

Once the arrays valeursCombo, valeursListeSimple, and valeursListeMultiple have been initialized by InitFormulaireAction, they no longer need to be initialized. This is because the dynaFormulaire object is placed in the session and therefore retains its value across request-response cycles. This is why the /init action is executed only once. The code for InitFormulaireAction is as follows:

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 {

     // prepares the form to be displayed

     // we put the information needed for the form in its bean
    DynaFormulaire formulaire = (DynaFormulaire) form;
    formulaire.set("valeursCombo", getValeurs(5, "combo"));
    formulaire.set("valeursListeSimple", getValeurs(7, "simple"));
    formulaire.set("valeursListeMultiple", getValeurs(10, "multiple"));
     // we give back
    return mapping.findForward("afficherFormulaire");
  } //execute

   // list of combo values
  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;
  }
}
  • The class extends the Action class. This is mandatory.
  • The Struts controller uses an Action object via its execute method. Therefore, this is the method that must be redefined. This method receives the following parameters:
    • ActionMapping mapping: an object representing the application configuration in Struts-config.xml
    • ActionForm form: the form associated with the action, if one is defined in the action’s configuration (the action’s name attribute).
    • HttpServletRequest request: the client request
    • HttpServletResponse: the response to the client
  • The InitFormulaireAction class must initialize the dynaFormulaire form. This form is passed to the execute method as the ActionForm form parameter. Note that dynaFormulaire is of type DynaFormulaire, a class derived from the DynaActionForm class, which is itself derived from the ActionForm class.
  • In the execute method, values are assigned to the three fields valeursCombo, valeursListeSimple, and valeursListeMultiple using the set method of the DynaActionForm class. These values are arbitrary arrays for the sake of simplicity. Note that the set method assigns a value to an existing field. It cannot be used to create new fields. This is why it is necessary to define the three fields valeursCombo, valeursListeSimple, and valeursListeMultiple in the definition of the dynaFormulaire object in struts-config.xml.
  • The execute method ends by returning the key of the view to be displayed to the controller as a response to the client. Here, it is the key afficherFormulaire that, in the file struts-config.xml, has been associated with the view /vues/formulaire.jsp.

6.6. Deployment

The application directory structure is as follows:

  

Image

Image

Note that the ApplicationResources.properties file above is required by the struts-bean tag library. We know that this file contains the application’s messages. These are accessible to the struts-bean library. Here, our application does not define any messages. Therefore, the ApplicationResources.properties file exists but is empty.

6.7. Conclusion

In this lesson, we have detailed how to manage the various components of a HTML form. We can now use complex forms in our Struts applications.