Skip to content

4. Utilizzo di moduli dinamici

4.1. Dichiarazione del modulo dinamico

Abbiamo visto che Struts utilizza oggetti ActionForm per memorizzare i valori dei moduli HTML elaborati dai vari servlet dell’applicazione. Per ogni modulo della nostra applicazione, dobbiamo creare una classe derivata da ActionForm. Ciò può diventare rapidamente piuttosto oneroso poiché per ogni campo xx dobbiamo scrivere due metodi: setXx e getXx. Struts ci offre la possibilità di utilizzare moduli

  • la cui struttura è dichiarata nel file struts-config.xml nella sezione <form-beans>
  • e che vengono creati dinamicamente dall’ambiente Struts in base alla struttura dichiarata

Pertanto, la classe utilizzata per memorizzare i valori «nome» e «età» dell’applicazione strutspersonne potrebbe essere definita come segue:

    <form-beans>
        <form-bean name="frmPersonne" type="org.apache.struts.actions.DynaActionForm">
            <form-property name="nom" type="java.lang.String" initial=""/>
            <form-property name="age" type="java.lang.String" initial=""/>
        </form-bean>            
    </form-beans>

Per ogni campo del modulo si definisce un tag <form-property> con due attributi:

  • name: il nome del campo
  • type: il suo tipo Java

Poiché i valori di un modulo inviati da un client web sono stringhe di caratteri, i tipi più comunemente utilizzati sono java.lang.String per i campi con valore singolo e java.lang.String[] per i campi con valori multipli (caselle di controllo con lo stesso nome, elenchi a selezione multipla, ...). Sia la classe DynactionForm che la classe ActionForm dispongono di un metodo validate che non esegue alcuna operazione. Per far sì che verifichi la validità dei parametri del modulo, è necessario derivare la classe e scrivere autonomamente il metodo validate. La dichiarazione del modulo sarà quindi la seguente:

    <form-beans>
        <form-bean name="frmPersonne" type="istia.st.struts.personne.PersonneDynaForm">
            <form-property name="nom" type="java.lang.String" initial=""/>
            <form-property name="age" type="java.lang.String" initial=""/>
        </form-bean>            
    </form-beans>

La classe istia.st.struts.personne.PersonneDynaForm dovrà essere creata da noi.

4.2. Creazione della classe DynaActionForm associata al modulo dinamico

In precedenza abbiamo associato la classe istia.st.struts.personne.PersonneDynaForm al modulo (nome, età). Ora scriviamo questa classe:

package istia.st.struts.personne;

import javax.servlet.http.*;
import org.apache.struts.action.*;

public class PersonneDynaForm extends DynaActionForm {
   // convalida
  public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
    // gestione degli errori
    ActionErrors erreurs = new ActionErrors();
     // il nome non deve essere vuoto
    String nom = (String)this.get("nom");
    if (nom == null || nom.trim().equals("")) {
      erreurs.add("nomvide", new ActionError("personne.formulaire.nom.vide"));
    }
     // l'età non deve essere vuota
    String age = (String)this.get("age");
    if (age == null || age.trim().equals("")) {
      erreurs.add("agevide", new ActionError("personne.formulaire.age.vide"));
    }
    else {
      // l'età deve essere un numero intero positivo
      if (!age.matches("^\\s*\\d+\\s*$")) {
        erreurs.add("ageincorrect", new ActionError("personne.formulaire.age.incorrect", age));
        // viene restituito l'elenco degli errori
      }
    } //if
     // si restituisce l'elenco degli errori
    return erreurs;
  }
}//classe

I punti da tenere presenti sono i seguenti:

  • la classe deriva da DynaActionForm
  • il metodo validate della classe DynaActionForm è stato riscritto. Quando viene eseguito dal controller Struts, viene creato l'oggetto PersonneDynaForm. Esso contiene un dizionario le cui chiavi sono i campi del modulo «nome» e «età» e i cui valori sono i valori di tali campi. Per accedere a un campo all’interno dei metodi di DynaActionForm si utilizza il metodo Object get(String nomDuChamp). Se si desidera assegnare un valore a un campo, è possibile utilizzare il metodo void set(String nomDuChamp, Object valore). Si rimanda alla definizione della classe DynaActionForm per una descrizione completa.
  • Una volta recuperati i valori dei campi nome ed età del modulo, il metodo validate non differisce da quello che era stato scritto quando il modulo era associato a un oggetto ActionForm.

4.3. La nuova classe FormulaireAction

Il file di configurazione definisce la seguente azione /main:

...
    <form-beans>
        <form-bean name="frmPersonne" type="istia.st.struts.personne.PersonneDynaForm">
            <form-property name="nom" type="java.lang.String" initial=""/>
            <form-property name="age" type="java.lang.String" initial=""/>
        </form-bean>            
    </form-beans>
....
      <action
          path="/main"
          name="frmPersonne"
            scope="session"
            validate="true"
            input="/erreurs.do"
          type="istia.st.struts.personne.FormulaireAction"
      >
            <forward name="reponse" path="/reponse.do"/>
        </action>

Questa definizione è la stessa dell'applicazione strutspersonne. L'azione /main viene eseguita da un oggetto di tipo FormulaireAction. Questo oggetto riceveva i valori del modulo frmPersonne in un oggetto di tipo FormulaireBean. Ora li riceve in un oggetto di tipo PersonneDynaForm. È quindi necessario riscrivere la classe:

package istia.st.struts.personne;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import javax.servlet.ServletException;
import istia.st.struts.personne.PersonneDynaForm;

public class FormulaireAction extends Action {

  public ActionForward execute(ActionMapping mapping, ActionForm form,
           HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException {

     // il modulo è valido, altrimenti non saremmo arrivati a questo punto
    PersonneDynaForm formulaire=(PersonneDynaForm)form;
    request.setAttribute("nom",formulaire.get("nom"));
    request.setAttribute("age",formulaire.get("age"));
    return mapping.findForward("reponse");
  }//esegui
}

I punti da tenere presenti sono i seguenti:

  • dobbiamo importare la classe PersonneDynaForm che contiene i dati del modulo per poter accedere alla sua definizione
  • il metodo execute recupera il valore dei parametri del modulo tramite il metodo [DynaActionForm].get.

Per quanto riguarda la classe FormulaireAction dell’applicazione strutspersonne, è cambiato solo il modo di accedere ai valori del modulo.

4.4. Distribuzione e test dell’applicazione strutspersonne1

4.4.1. Creazione del contesto

Abbiamo chiamato strutspersonne1 questa nuova applicazione. Creiamo una nuova definizione nel file <tomcat>\conf\serveur.xml di Tomcat 4.x:

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

Una volta fatto ciò, è necessario riavviare Tomcat. È possibile verificare la validità del contesto richiedendo l’URL:

http://localhost:8080/strutspersonne1/

Image

4.4.2. Le viste

Si copierà la cartella «vues» dell’applicazione strutspersonne nella cartella dell’applicazione strutspersonne1. Infatti, le viste non sono cambiate.

Image

4.4.3. Compilazione delle classi

Dobbiamo creare due classi: PersonneDynaForm e FormulaireAction, dove la seconda utilizza la prima. È possibile crearle e compilarle utilizzando un progetto JBuilder:

Image

4.4.4. La cartella WEB-INF

Copieremo la cartella WEB-INF dall’applicazione strutspersonne nella cartella dell’applicazione strutspersonne1. Alcuni file cambiano:

Image

Il file di configurazione struts-config.xml diventa il seguente:

<?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="frmPersonne" type="istia.st.struts.personne.PersonneDynaForm">
            <form-property name="nom" type="java.lang.String" initial=""/>
            <form-property name="age" type="java.lang.String" initial=""/>
        </form-bean>            
    </form-beans>

    <action-mappings>
      <action
          path="/main"
          name="frmPersonne"
            scope="session"
            validate="true"
            input="/erreurs.do"
          type="istia.st.struts.personne.FormulaireAction"
      >
            <forward name="reponse" path="/reponse.do"/>
        </action>
      <action
          path="/erreurs"
          parameter="/vues/erreurs.personne.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
      <action
          path="/reponse"
          parameter="/vues/reponse.personne.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
      <action
          path="/formulaire"
          parameter="/vues/formulaire.personne.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
    </action-mappings>

    <message-resources parameter="ressources.personneressources"/>    
</struts-config>

Questo file è identico a quello dell'applicazione strutspersonne, ad eccezione della definizione dinamica del modulo (parte evidenziata).

Nella cartella WEB-INF/classes andranno inserite le classi compilate da JBuilder:

Image

Nella cartella WEB-INF\classes\ressources, si inserisce il file dei messaggi. Non è cambiato.

personne.formulaire.nom.vide=<li>Vous devez indiquer un nom</li>
personne.formulaire.age.vide=<li>Vous devez indiquer un age</li>
personne.formulaire.age.incorrect=<li>L'âge [{0}] est incorrect</li>
errors.header=<ul>
errors.footer=</ul>

Image

4.5. Test

Siamo pronti per i test. Di seguito sono riportati alcuni screenshot che il lettore è invitato a riprodurre.

Si richiede l'http://localhost:8080/strutspersonne1/formulaire.do: URL:

Image

Si utilizza il pulsante [Envoyer] senza compilare i campi:

Image

Si riprova con un errore nel campo «età»:

Image

Si ottiene la seguente risposta:

Image

Riproviamo inserendo questa volta i valori corretti:

Image

Si ottiene la seguente risposta:

Image

4.6. Conclusione

L'uso di moduli dinamici facilita la scrittura di classi del tipo ActionForm incaricate di memorizzare i valori dei moduli. È possibile semplificare ulteriormente la gestione dei moduli. Nell'applicazione strutspersonne1, abbiamo creato una classe PersonneDynaForm per verificare la validità dei valori (nome, età) del modulo. In pratica, alcune verifiche ricorrono frequentemente: campo non vuoto, campo che verifica una determinata espressione regolare, campo intero, campo data, ... Questo tipo di verifica standard può quindi essere specificato nel file di configurazione struts-config.html. Se tutte le verifiche da effettuare sono “standard”, non è più necessario scrivere una classe per il modulo. È proprio ciò che vedremo ora.