Skip to content

4. Utilização de formulários dinâmicos

4.1. Declaração do formulário dinâmico

Vimos que o Struts utiliza objetos ActionForm para armazenar os valores dos formulários HTML processados pelos diferentes servlets da aplicação. Para cada formulário da nossa aplicação, temos de criar uma classe derivada de ActionForm. Isto pode tornar-se rapidamente bastante trabalhoso, uma vez que, para cada campo xx, temos de escrever dois métodos: setXx e getXx. O Struts oferece-nos a possibilidade de utilizar formulários

  • cuja estrutura é declarada no ficheiro struts-config.xml, na secção <form-beans>
  • e que são criados dinamicamente pelo ambiente Struts de acordo com a estrutura declarada

Assim, a classe utilizada para armazenar os valores «nome» e «idade» da aplicação strutspersonne poderia ser definida da seguinte forma:

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

Para cada campo do formulário, define-se uma baliza <form-property> com dois atributos:

  • name: o nome do campo
  • type: o seu tipo Java

Como os valores de um formulário enviados por um cliente web são cadeias de caracteres, os tipos mais utilizados são java.lang.String para campos com um único valor e java.lang.String[] para campos com vários valores (caixas de seleção com o mesmo nome, listas de seleção múltipla, etc.). Tanto a classe DynactionForm como a classe ActionForm têm um método validate que não faz nada. Para que verifique a validade dos parâmetros do formulário, é necessário derivá-la e escrever o método validate por conta própria. A declaração do formulário será, portanto, a seguinte:

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

A classe istia.st.struts.personne.PersonneDynaForm terá de ser criada por nós.

4.2. Criação da classe DynaActionForm associada ao formulário dinâmico

Acima, associamos a classe istia.st.struts.personne.PersonneDynaForm ao formulário (nome, idade). Vamos agora escrever esta classe:

package istia.st.struts.personne;

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

public class PersonneDynaForm extends DynaActionForm {
   // validação
  public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
    // gestão de erros
    ActionErrors erreurs = new ActionErrors();
     // o nome não pode estar vazio
    String nom = (String)this.get("nom");
    if (nom == null || nom.trim().equals("")) {
      erreurs.add("nomvide", new ActionError("personne.formulaire.nom.vide"));
    }
     // a idade não pode estar em branco
    String age = (String)this.get("age");
    if (age == null || age.trim().equals("")) {
      erreurs.add("agevide", new ActionError("personne.formulaire.age.vide"));
    }
    else {
      // a idade deve ser um número inteiro positivo
      if (!age.matches("^\\s*\\d+\\s*$")) {
        erreurs.add("ageincorrect", new ActionError("personne.formulaire.age.incorrect", age));
        // apresenta-se a lista de erros
      }
    } //if
     // retorna-se a lista de erros
    return erreurs;
  }
}//classe

Os pontos a ter em conta são os seguintes:

  • a classe deriva de DynaActionForm
  • o método validate da classe DynaActionForm foi reescrito. Quando executado pelo controlador Struts, o objeto PersonneDynaForm foi criado. Este contém um dicionário cujas chaves são os campos do formulário «nome» e «idade» e cujos valores são os valores desses campos. Para aceder a um campo nos métodos de DynaActionForm, utiliza-se o método Object get(String nomDuChamp). Se se pretender atribuir um valor a um campo, pode-se utilizar o método void set(String nomDuChamp, Object valor). Consulte a definição da classe DynaActionForm para obter uma definição completa.
  • Depois de recuperados os valores dos campos «nome» e «idade» do formulário, o método «validate» não difere daquele que tinha sido escrito quando o formulário estava associado a um objeto ActionForm.

4.3. A nova classe FormulaireAction

O ficheiro de configuração define a seguinte ação /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>

Esta definição é idêntica à da aplicação strutspersonne. A ação /main é executada por um objeto do tipo FormulaireAction. Este objeto recebia os valores do formulário frmPersonne num objeto do tipo FormulaireBean. Agora, recebe-os num objeto do tipo PersonneDynaForm. Por isso, é necessário reescrever a 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 {

     // temos um formulário válido; caso contrário, não teríamos chegado até aqui
    PersonneDynaForm formulaire=(PersonneDynaForm)form;
    request.setAttribute("nom",formulaire.get("nom"));
    request.setAttribute("age",formulaire.get("age"));
    return mapping.findForward("reponse");
  }//executar
}

Os pontos a ter em conta são os seguintes:

  • temos de importar a classe PersonneDynaForm, que contém os dados do formulário, para ter acesso à sua definição
  • o método `execute` recupera o valor dos parâmetros do formulário através do método `[DynaActionForm].get`.

No que diz respeito à classe FormulaireAction da aplicação strutspersonne, apenas a forma de aceder aos valores do formulário mudou.

4.4. Implantação e teste da aplicação strutspersonne1

4.4.1. Criação do contexto

Chamámos a esta nova aplicação «strutspersonne1». Criamos uma nova definição no ficheiro <tomcat>\conf\serveur.xml do Tomcat 4.x:

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

Feito isto, é necessário reiniciar o Tomcat. É possível verificar a validade do contexto acedendo ao URL:

http://localhost:8080/strutspersonne1/

Image

4.4.2. As vistas

Vamos copiar a pasta «vues» da aplicação «strutspersonne» para a pasta da aplicação «strutspersonne1». Com efeito, as vistas não sofreram alterações.

Image

4.4.3. Compilação das classes

Temos duas classes para criar: PersonneDynaForm e FormulaireAction, sendo que a última utiliza a primeira. Podemos criá-las e compilá-las utilizando um projeto do JBuilder:

Image

4.4.4. A pasta WEB-INF

Vamos copiar a pasta WEB-INF da aplicação strutspersonne para a pasta da aplicação strutspersonne1. Alguns ficheiros são alterados:

Image

O ficheiro de configuração struts-config.xml passa a ter o seguinte conteúdo:

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

Este ficheiro é idêntico ao da aplicação strutspersonne, com exceção da definição dinâmica do formulário (parte emoldurada).

Na pasta WEB-INF/classes, colocar-se-ão as classes compiladas pelo JBuilder:

Image

Na pasta WEB-INF\classes\ressources, deve-se colocar o ficheiro de mensagens. Este não sofreu alterações.

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

Estamos prontos para os testes. Seguem-se algumas capturas de ecrã que o leitor é convidado a reproduzir.

Pede-se o URLhttp://localhost:8080/strutspersonne1/formulaire.do:

Image

Utiliza-se o botão [Envoyer] sem preencher os campos:

Image

Repetimos o processo com um erro no campo «age»:

Image

Obtém-se a seguinte resposta:

Image

Vamos tentar novamente, desta vez introduzindo valores corretos:

Image

Obtém-se a seguinte resposta:

Image

4.6. Conclusão

A utilização de formulários dinâmicos facilita a criação de classes do tipo ActionForm, encarregadas de armazenar os valores dos formulários. É possível ir um pouco mais longe na simplificação da gestão dos formulários. Na aplicação strutspersonne1, criámos uma classe PersonneDynaForm para verificar a validade dos valores (nome, idade) do formulário. Na prática, algumas verificações repetem-se frequentemente: campo não vazio, campo que verifica uma determinada expressão regular, campo inteiro, campo de data, ... Este tipo de verificação padrão pode, então, ser definido no ficheiro de configuração struts-config.html. Se todas as verificações a realizar forem «padrão», então já não é necessário criar nenhuma classe para o formulário. É isso que vamos ver agora.