Skip to content

4. Uso 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 diversos servlets da aplicação. Para cada formulário de nossa aplicação, precisamos criar uma classe derivada de ActionForm. Isso pode se tornar rapidamente bastante trabalhoso, já que, para cada campo xx, precisamos escrever dois métodos: setXx e getXx. O Struts nos oferece a possibilidade de utilizar formulários

  • cuja estrutura é declarada no arquivo struts-config.xml, na seçã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 tag <form-property> com dois atributos:

  • name: o nome do campo
  • type: seu tipo em 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 valor único e java.lang.String[] para campos com valores múltiplos (caixas de seleção com o mesmo nome, listas de seleção múltipla, etc.). Tanto a classe DynactionForm quanto a classe ActionForm possuem um método validate que não faz nada. Para que ela 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 deverá 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). Agora, vamos criar essa 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 vazia
    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));
        // retornamos a lista de erros
      }
    } //if
     // retorna-se a lista de erros
    return erreurs;
  }
}//classe

Os pontos a serem observados 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. Ele 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 acessar um campo nos métodos de DynaActionForm, utiliza-se o método Object get(String nomDuChamp). Se for necessário 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 descrição completa.
  • Depois de recuperados os valores dos campos nome e idade do formulário, o método validate não difere daquele que havia sido escrito quando o formulário estava associado a um objeto ActionForm.

4.3. A nova classe FormulaireAction

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

Essa definição é a mesma da aplicação strutspersonne. A ação /main é executada por um objeto do tipo FormulaireAction. Esse objeto recebia os valores do formulário frmPersonne em um objeto do tipo FormulaireBean. Agora, ele os recebe em um objeto do tipo PersonneDynaForm. Portanto, é 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 serem observados são os seguintes:

  • precisamos 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 com o método `[DynaActionForm].get`.

Em relação à classe FormulaireAction do aplicativo strutspersonne, apenas a forma de acessar os valores do formulário mudou.

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

4.4.1. Criação do contexto

Chamamos essa nova aplicação de strutspersonne1. Criamos uma nova definição no arquivo <tomcat>\conf\serveur.xml do Tomcat 4.x:

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

Feito isso, é preciso reiniciar o Tomcat. É possível verificar a validade do contexto acessando o URL:

http://localhost:8080/strutspersonne1/

Image

4.4.2. As visualizações

Copiaremos a pasta “vues” do aplicativo strutspersonne para a pasta do aplicativo strutspersonne1. Na verdade, as visualizações não sofreram alterações.

Image

4.4.3. Compilação das classes

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

Image

4.4.4. A pasta WEB-INF

Copiaremos a pasta WEB-INF do aplicativo strutspersonne para a pasta do aplicativo strutspersonne1. Alguns arquivos serão alterados:

Image

O arquivo 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 arquivo é 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, serão colocadas as classes compiladas pelo JBuilder:

Image

Na pasta WEB-INF\classes\ressources, deve-se colocar o arquivo de mensagens. Ele 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. Abaixo, apresentamos algumas capturas de tela que o leitor é convidado a reproduzir.

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

Image

Utilize o botão [Envoyer] sem preencher os campos:

Image

Tentamos novamente, mas ocorre um erro no campo “idade”:

Image

Recebemos a seguinte resposta:

Image

Tentamos novamente, desta vez inserindo valores corretos:

Image

Obtém-se a seguinte resposta:

Image

4.6. Conclusão

O uso de formulários dinâmicos facilita a criação de classes do tipo ActionForm, responsáveis por armazenar os valores dos formulários. É possível simplificar ainda mais o gerenciamento dos formulários. Na aplicação strutspersonne1, criamos uma classe PersonneDynaForm para verificar a validade dos valores (nome, idade) do formulário. Na prática, algumas verificações se repetem com frequência: campo não vazio, campo que verifica uma determinada expressão regular, campo inteiro, campo de data, etc. Esse tipo de verificação padrão pode, então, ser definido no arquivo de configuração struts-config.html. Se todas as verificações a serem feitas forem “padrão”, não será mais necessário criar uma classe para o formulário. É isso que veremos agora.