Desenvolvimento - Java

Java: Struts na prática de ponta a ponta

Boa parte do framework Struts foi desenvolvido entre maio de 2000 e junho de 2001, quando sua primeira versão foi lançada. A responsabilidade esteve com uma equipe de aproximadamente 30 desenvolvedores, sendo que Craig R. MacClanahan foi o primeiro arquiteto e desenvolvedor do framework. Após quatro anos de estrada, o Struts tornou-se padrão de mercado para aplicações web em java.

por Vicente Goetten Júnior



Boa parte do framework Struts foi desenvolvido entre maio de 2000 e junho de 2001, quando sua primeira versão foi lançada. A responsabilidade esteve com uma equipe de aproximadamente 30 desenvolvedores, sendo que Craig R. MacClanahan foi o primeiro arquiteto e desenvolvedor do framework. Após quatro anos de estrada, o Struts tornou-se padrão de mercado para aplicações web em java. Atualmente, vários frameworks são apontados como substitutos para o Struts, como o Java Server Faces, de responsabilidade do próprio Craig MacClanahan. No entanto, a procura por profissionais com conhecimento neste framework deve continuar por muitos anos.

A estrada para o sucesso das aplicações web é um caminho árduo, despendendo suor de pesquisadores e também do próprio desenvolvedor. Neste caso, como aplicação web fica subentendido de que esta não é apenas uma aplicação trivial, composta por um formulário contendo dois ou três campos que são armazenados em um banco de dados. Mas sim uma aplicação robusta que atravessa diversas camadas, utiliza diferentes tecnologias, cobertas por análise e utilização de padrões (design-patterns).

O projeto e desenvolvimento deste tipo de aplicação levam os desenvolvedores para o limite da lógica. Soluções mirabolantes são criadas para resolução de certos problemas. Algumas destas soluções funcionam, outras não. O framework Struts, criado por Craig R. McClanahan e doado para a fundação Apache (Apache Software Foundation) em 2000 é uma implementação de código aberto do Modelo 2, bastante similar ao modelo MVC (Model, View and Controller - design pattern para que as camadas de regra de negócio, visualização e controle estejam bem separadas na aplicação).

Neste contexto, ao longo desse artigo serão abordadas as tecnologias envolvidas no framework struts, já que este não é uma tecnologia específica, mas sim um conjunto de tecnologias que tornam o seu aprendizado ainda mais desafiador.

Frameworks

Um framework pode ser entendido como sendo uma aplicação reutilizável e semi-completa que pode ser especializada para produzir softwares personalizados. As aplicações construídas com o apoio de um framework são, de um modo geral, bastante semelhantes.

Os desenvolvedores que trabalham em aplicações eletrônicas convencionais estão acostumados a kits de ferramentas e a ambientes de desenvolvimento que aproveitam a igualdade entre as aplicações. Os frameworks da aplicação fornecem uma base comum reutilizável podendo servir como fundação para um produto específico.

Um framework de aplicação deve possuir as seguintes características:

  • compreender múltiplas classes ou componentes, cada qual provendo uma abstração de um conceito em particular;
  • definir como estes conceitos trabalharão juntos para resolver um determinado problema;
  • possuir componentes reutilizáveis;
  • permitir um alto nível de padronização.

Framework Jakarta Struts

O Struts é um framework para web que se tornou padrão na comunidade JEE (Java Enterprise Edition). O Struts provê uma implementação do modelo MVC-2 (ver Nota 1) para construções de aplicações web.

Nota 1. Modelo MVC-2 x Modelo MVC
O termo Modelo 2 (ou MVC-2) surgiu na especificação 0.92 da Servlet/JSP. Este modelo era especificado como uma arqutetura que utiliza servlets e as págnas JSP juntas na mesma aplicação. No modelo2, os servlets são responsáveis pelo acesso a dados e também pelo fluxo navegacional, enquanto as págnas JSP lidam com a apresentação. Este modelo permite que engenheiros Java e os desenvovedores HTML trabalhem cada um em sua parte da aplicação. Desta forma, a aparência da aplicação pode ser alterada (HTML) sem que a funcionalidade ou fluxo de navegação precise acompanhar as alterações.
O framewok Struts é baseado na arquitetura do modelo 2. Fornece um servlet controlador para lidar com o fluxo navegacional e as classes especiais para ajudar com o acesso dos dados. Uma biblioteca de tags personalizadas é enviada com o framework para tornar o Struts ainda mais fácil de usar com as páginas JSP. Pode-se observar que o Struts implementa o pattern MVC, onde as camadas de Modelo, Visualização e Controle devem ser implementadas separadamente na aplicação.

Mas qual a finalidade do Struts? Da mesma forma que a construção de uma casa, ponte e prédio necessitam de uma base mantenedora, os desenvolvedores utilizam o Struts para suportar cada camada de uma aplicação. O nome Struts deve-se ao papel por ele desempenhado nas aplicações web, o de fornecer toda a estrutura inicial. O Struts implementa o controlador da aplicação (a letra C da sigla MVC-2), sendo este controlador o responsável por toda a logística e também pela integração das camadas de visualização e regra de negócio do sistema.

Struts de ponta a ponta

Para facilitar o entendimento do Struts, observe na Figura 1 o fluxo normal de uma aplicação utilizando o Struts, e também quais tecnologias estão envolvidas em cada uma das etapas.

As etapas estão descritas a seguir, de acordo com a numeração indicada na Figura 1:

1. Cada solicitação HTTP tem que ser respondida neste mesmo protocolo. Desta forma, inicia-se uma aplicação que utiliza o Struts. Esta solicitação normalmente é definida como requisicao.do, que é um nome lógico para a requisição do usuário.

2. A solicitação requisicao.do é mapeada no arquivo struts-config.xml. Neste arquivo estão todas as definições do controlador do framework. O arquivo é então lido por um ActionServlet (que fará efetivamente o papel do controlador da aplicação) na inicialização da aplicação criando então um banco de objetos com o arquivo de configuração. No arquivo de configuração são definidos os Actions (requisições dos usuários) para cada solicitação.

3. O ActionServlet (que faz o papel do controlador da aplicação), define o Action correspondente para a solicitação. Um Action pode validar a entrada de dados e acessar a camada de negócios para recuperar as informações nos bancos de dados e outros serviços de dados.

4. A requisição HTTP pode ser feita também através de um formulário HTML. Em vez de fazer com que cada Action retire os valores do campo da solicitação, o ActionServlet coloca a entrada em um JavaBean. Estes JavaBeans são definidos como FormBeans no Struts e estendem a classe org.apache.struts.action.ActionForm (os Actions e FormBeans serão abordados com maiores detalhes no decorrer do artigo).

5. O Action pode acessar o FormBean, efetuar qualquer operação e armazenar o resultado em um ResultBean.

6. O Action interage com a camada de negócio onde uma base de dados poderá ser atualizada.

Em geral, o Struts não apresenta a resposta em si, mas envia a solicitação para outro recurso, como uma página JSP. O Struts fornece a classe ActionForward que pode ser usada para armazenar o caminho para uma página sob um nome lógico. Desta forma, o endereço ficará oculto para o usuário. Este visualizará apenas o nome definido para o caminho (por exemplo, resposta.do). Este recurso evita que o usuário possa estar visualizando uma versão desatualizada da aplicação, já que as requisições serão feitas apenas para nomes lógicos.

Ao completar a lógica de negócio, o Action selecionará e retornará um ActionForward para o servlet. Então, o servlet usará o caminho armazenado no objeto ActionForward para chamar a página e completar a resposta.

Estes detalhes logísticos da aplicação são definidos no objeto ActionMapping. Cada ActionMapping está relacionado a um caminho específico. Quando este caminho for selecionado, como requisicao.do, o servlet irá recuperar o objeto ActionMapping. O mapeamento informará ao servlet quais Actions, ActionForms e ActionForwards usar. Ambiente de desenvolvimento

Para desenvolver uma aplicação que utilize o framework Struts,são necessários que sejam instalados e configurados os seguintes pacotes:

  • JSE – Java Standard Edition (kit de desenvolvimento Java);
  • Servlet Container, como o TOMCAT;
  • Apache Ant (opcional – ferramenta de build);
  • Framework Struts.

Todas as ferramentas que compõem este ambiente de desenvolvimento podem ser obtidas gratuitamente. A partir deste ponto, o leitor deverá estar com o kit de desenvolvimento Java, Apache ANT e também com o Tomcat devidamente instalados e configurados, já que a instalação e configuração destes pacotes não serão abordadas neste artigo.

Para desenvolvimento da aplicação de exemplo deste artigo foram utilizadas as seguintes versões:

Obtendo e instalando o Struts

O Struts é mantido pelo Apache Software Foundation e possui a licença Apache, sendo esta OpenSource. A licença Apache possibilita que o framework seja distribuído juntamente com a aplicação sem que seja necessário efetuar qualquer pagamento à fundação.

O Struts pode ser obtido no site oficial do projeto, http://struts.apache.org. Os arquivos binários são distribuídos em diversos formatos na página de download http://struts.apache.org/acquiring.html. Nesta página, selecione a versão 1.2.7, e o formato que desejar, como jakarta-struts-1.2.7.tar.gz.

O processo de instalação e configuração do Struts é bastante simples: basta descompactá-lo em um diretório qualquer, como /usr/local/jakarta-struts-1.2.7 (caso esteja utilizando o linux) ou c:\apache\jakartastruts- 1.2.7 (caso esteja utilizando o Windows).

Após descompactar o Struts, será necessário adicionar o arquivo $STRUTS_HOME/lib/struts.jar no CLASSPATH, onde $STRUTS_HOME é o diretório principal onde o Struts foi descompactado. Veja o comando abaixo para editar o classpath:

  • Se estiver utilizando o Linux, abra uma sessão no console (shell) e digite o comando:
    CLASSPATH=/usr/local/strtus.1.2.7/lib/struts.jar:$CLASSPATH
    export CLASSPATH.
    

  • Se estiver utilizando o Windows, abra uma sessão do prompt de ms-dos, e digite o comando:
    set CLASSPATH=c:\struts1.2.7\struts.jar;%CLASSPATH%.
    

    Testando a instalação do Struts

    O Struts fornece uma aplicação semi-pronta que pode ser evoluída (exatamente o que faremos na aplicação de exemplo). Esta aplicação também pode ser utilizada para testar a instalação do Struts. Para isto, o arquivo $STRUTS_HOME/webapps/struts-blank.war deve ser copiado para o diretório webapps do Tomcat, $TOMCAT_HOME/webapps (observe que $STRUTS_HOME e $TOMCAT_HOME equivalem ao diretório de instalação do Struts e Tomcat, respectivamente).

    Após reiniciar o Tomcat, a aplicação Blank, do Struts, pode ser acessada pelo endereço http://localhost:8080/struts-blank (observe que 8080 é a porta padrão do Tomcat. Altere conforme a configuração do seu contêiner). O resultado deve ser semelhante ao da Figura 2.

    Para iniciar o desenvolvimento da aplicação de exemplo deste artigo, altere o nome do diretório strutsblank para cadastro, copie o diretório $TOMCAT_HOME/webapps/cadastro para o seu diretório de desenvolvimento (por exemplo, c:\devel no windows ou /home/user/devel no linux).

    Struts: entendendo e aplicando os conceitos

    A partir deste ponto, estaremos desenvolvendo uma aplicação bastante simples, mas que utilizará praticamente todos os componentes do Struts. O desenvolvimento será a partir da aplicação semi-pronta do struts – struts-blank (que já deve estar copiada para o seu diretório de desenvolvimento com o nome de cadastro).

    A aplicação consiste em um formulário onde o usuário deverá informar e-mail e senha. Serão feitas algumas validações, como verificar se todos os campos estão preenchidos, se o campo e-mail segue o formato nome@host.com, e se o campo senha possui pelo menos 8 caracteres.

    A aplicação, que iremos desenvolver, deve ter a estrutura de diretórios apresentada na Figura 3..

    As páginas JSPs serão salvas abaixo do diretório pages. Este é o único diretório que o usuário poderá acessar pelo navegador. Veja abaixo a funcionalidade dos demais diretórios que serão utilizados pela aplicação:

    • WEB-INF/results: páginas JSPs contendo o resultado de uma operação realizada pelo usuário. Estas páginas poderão ser chamadas somente pelo Struts. O usuário da aplicação não conseguirá acessá-las diretamente;
    • WEB-INF/src: abaixo deste diretório serão mantidos os arquivos .java da aplicação (abaixo do subdiretório goetten);
    • WEB-INF/lib: bibliotecas utilizadas pela aplicação;
    • WEB-INF/classes: arquivos .class referentes às classes Java compiladas da aplicação;
    • Os demais diretórios não serão utilizados pela nossa aplicação, no entanto fazem parte da estrutura padrão de uma aplicação utilizando o Struts.
    As requisições .do: conhecendo o arquivo web.xml

    No Struts, todas as requisições dos usuários recebem um nome lógico (conforme já vimos, este nome lógico vai evitar que o usuário visualize uma versão desatualizada de algum componente da aplicação). A este nome lógico é acrescentada a extensão .do. No entanto, esta extensão é dinâmica, o desenvolvedor pode definir qual extensão utilizar em sua aplicação. O padrão do Struts é utilizar o .do. Na Listagem 1, a extensão para as requisições do servlet é definida, e definimos também o servlet que deverá ser invocado para estas solicitações.

    Listagem 1. Configuração do contêiner jakarta tomcat
    Fonte: cadastro/WEB-INF/web.xml.
    
    1. <?xml version="1.0" encoding="ISO-8859-1"?>
    2. <!DOCTYPE web-app
    3. PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
    4. "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
    5.
    6. <web-app>
    7. <display-name>Cadastro – WebMobile Magazine</display-name>
    8.
    9. <!-- Standard Action Servlet Configuration (with debugging) -->
    10. <servlet>
    11. <servlet-name>action</servlet-name>
    12. <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    13. <init-param>
    14. <param-name>config</param-name>
    15. <param-value>/WEB-INF/struts-config.xml</param-value>
    16. </init-param>
    17. <init-param>
    18. <param-name>debug</param-name>
    19. <param-value>2</param-value>
    20. </init-param>
    21. <init-param>
    22. <param-name>detail</param-name>
    23. <param-value>2</param-value>
    24. </init-param>
    25. <load-on-startup>2</load-on-startup>
    26. </servlet>
    27.
    28. <!-- Standard Action Servlet Mapping -->
    29. <servlet-mapping>
    30. <servlet-name>action</servlet-name>
    31. <url-pattern>*.do</url-pattern>
    32. </servlet-mapping>
    33.
    34. <!-- The Usual Welcome File List -->
    35. <welcome-file-list>
    36. <welcome-file>index.jsp</welcome-file>
    37. </welcome-file-list>
    38.
    39. <!-- Struts Tag Library Descriptors -->
    40. <taglib>
    41. <taglib-uri>/tags/struts-bean</taglib-uri>
    42. <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
    43. </taglib>
    44.
    45. <taglib>
    46. <taglib-uri>/tags/struts-html</taglib-uri>
    47. <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
    48. </taglib>
    49.
    50. <taglib>
    51. <taglib-uri>/tags/struts-logic</taglib-uri>
    52. <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
    53. </taglib>
    54.
    55. <taglib>
    56. <taglib-uri>/tags/struts-nested</taglib-uri>
    57. <taglib-location>/WEB-INF/struts-nested.tld</taglib-location>
    58. </taglib>
    59.
    60. <taglib>
    61. <taglib-uri>/tags/struts-tiles</taglib-uri>
    62. <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location>
    63. </taglib>
    64.
    65. </web-app>
    

    Na linha 7, estamos definindo a descrição da aplicação: <display-name>Cadastro – WebMobile Magazine</display-name>. Entre as linhas 9 e 26 definimos o servlet padrão e o arquivo de configuração para este servlet. A definição da extensão .do fica entre as linhas 28 e 32. Observe que neste trecho mencionamos o servlet a ser mapeado (no caso o action) e definimos a sua extensão, entre as tags <urlpattern> </url-pattern>. Entre as linhas 34 e 37 definimos os arquivos indexadores da aplicação, e nas demais linhas são definidas as taglibs que serão utilizadas. Estas taglibs permitem que o desenvolvedor da camada de visualização, o web designer, se preocupe principalmente com o layout da aplicação, utilizando tags HTML combinadas com tags especiais das taglibs configuradas. Observe que todas as taglibs definidas são fornecidas pelo Struts, não havendo necessidade de alterá-las para utilização.

    Configurando a aplicação

    Com Struts, o processo de funcionamento normal de uma aplicação é: um formulário submete os dados para um endereço (URL), como requisicao.do. Este endereço (requisicao.do) é mapeado no arquivo de configuração do Struts, o struts-config.xml, para um objeto Action. Este objeto executa um método para tratar a requisição.

    Um dos argumentos do Action é um formBean, que é automaticamente criado e populado com os dados submetidos do formulário. O objeto Action invoca a lógica de negócio e lógica de acesso a dados, posiciona os resultados em um bean, sendo que este bean pode ter o seu escopo definido como sendo específico da requisição, sessão ou até mesmo da aplicação. O Action utiliza então o mapping.findForward para retornar uma condição, que é também mapeada pelo struts-config.xml, podendo direcionar o resultado para uma página JSP.

    Na primeira etapa da aplicação, iremos definir os detalhes de configuração da aplicação. Observe a Listagem 2 referente ao arquivo de configuração do Struts.

    Listagem 2. Configuração da aplicação 
    Fonte: cadastro/WEB-INF/struts-config.xml.
    
    1. <?xml version="1.0" encoding="ISO-8859-1" ?>
    2. <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
    "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
    3. <form-beans>
    4. <form-bean name="userFormBean" type="goetten.UserFormBean"/>
    5. </form-beans>
    6. <global-forwards>
    7. <!-- Default forward to "Welcome" action -->
    8. <!-- Demonstrates using index.jsp to forward -->
    9. <forward
    name="welcome"
    path="/Welcome.do"/>
    10. </global-forwards>
    11. <action-mappings>
    <!-- Default "Welcome" action -->
    <!-- Forwards to Welcome.jsp -->
    12. <action
    13. path="/Welcome"
    14. forward="/pages/register.jsp"/>
    15. <action
    16. path="/actions/register"
    17. type="goetten.RegisterAction"
    18. name="userFormBean"
    scope="request"
    input="/pages/action/register.jsp">
    20. <forward name="success"
    path="/WEB-INF/results/result.jsp"/>
    21. <forward name="bad-address"
    path="/WEB-INF/results/bad-address.jsp"/>
    22. <forward name="bad-password"
    path="/WEB-INF/results/bad-password.jsp"/>
    23. </action>
    24. </action-mappings>
    25. </struts-config>
    

    A primeira parte a ser analisada neste arquivo fica entre as linhas 15 e 23, que é onde estamos definindo os Actions que serão mapeados pela aplicação e os seus possíveis resultados (forwards). Observe as linhas 15 e 16 (<action path="/actions/register"), a propriedade define o nome lógico para o Action, neste caso /actions/register.do. Observe que a extensão .do não foi definida, pois já definimos esta extensão como padrão no arquivo web.xml.

    Na linha 17 (type=goetten.RegisterAction) estamos definindo qual será a classe Java responsável por fazer o tratamento da requisição. Já nas linhas 18 e 19 estamos definindo o Bean utilizado na requisição (userFormBean), este é apenas um nome lógico para o Bean. Na linha 4 definimos o nome lógico e a classe Java referente ao Bean. Entre as linhas 20 e 22, definimos todos os possíveis retornos para a requisição. O parâmetro name define um nome lógico para o resultado e o parâmetro path pode conter uma página JSP ou ainda outro Action.

    FormBeans

    Um FormBean nada mais é do que um JavaBean. Os JavaBeans são classes Java que seguem um conjunto de padrões de construção que facilitam a sua utilização em ferramentas de desenvolvimento (ou frameworks) e aplicação.

    Um JavaBean pode ser ainda definido como um componente de software reutilizável escrito em Java. Para ser qualificado como JavaBean, a classe tem que ser concreta e pública e ter um construtor sem argumentos. Os JavaBeans expõem os campos internos como propriedades fornecendo métodos públicos que seguem um padrão de projeto consistente. Sabendo que os nomes patenteados seguem esse padrão, as outras classes Java são capazes de usar a introspecção, onde a classe é capaz de analisar a sua estrutura em tempo de execução, para descobrir e manipular as propriedades do JavaBean.

    Cada campo do formulário para ser mapeado no Action deverá ter o seu devido atributo na classe, juntamente com os métodos para definição e recuperação dos valores (set e get). Quando um formulário HTML é enviado, as duplas nome-valor são obtidas pelo controlador Struts e aplicadas em um ActionForm (org.apache.struts.action.ActionForm). O Struts compara então os nomes das propriedades deste Bean com os nomes das duplas de entrada. Quando coincidem, o controlador define a propriedade para o valor da dupla correspondente. As propriedades extras são ignoradas. As propriedades ausentes mantêm o seu valor padrão. Estes pares de entrada são compostos pelos campos do formulário HTML. Um formulário contendo os campos e-mail e password conteria os seguintes pares, por exemplo:

  • email=goetten@gmail.com
  • password = 12345678

    A Listagem 3 apresenta o Bean utilizado pela aplicação cadastro, o UserFormBean.java.

    Listagem 3. FormBean da aplicação de cadastro 
    Fonte: cadastro/src/goetten/UserFormBean.java.
    
    Package goetten;
    import org.apache.struts.action.*;
    public class UserFormBean extends ActionForm {
       private String email = "Informe o email";
       private String password = "";
       public String getEmail() {
       return(email);
       }
       public void setEmail(String email) {
       this.email = email;
       }
       public String getPassword() {
       return(password);
       }
       public void setPassword(String password) {
       this.password = password;
       }
    }
    

    ResultBeans

    O FormBean representa os dados de entrada, ou seja, os dados submetidos de um formulário HTML. Na maioria das aplicações, o mais importante são os dados referentes ao resultado de uma requisição, o dado criado pela lógica de negócio, podendo ser resultado de uma computação qualquer como um cálculo, ou ainda operações realizadas no banco de dados. No modelo MVC, o ResultBean representa a letra M - o Modelo.

    Assim como os FormBeans, os ResultBeans também devem possuir métodos para definição e recuperação de atributos. No entanto, não é necessário defini-los no arquivo de configuração do Struts (struts-config.xml) e também não há necessidade de estender qualquer classe do Struts.

    Nossa aplicação de cadastro utilizará o ResultBean SuggestionBean.java que armazenará sugestões de email e senha para o usuário. Quando o usuário submeter um e-mail inválido, ou uma quantidade de caracteres inferior à mínima necessária para a sua senha, o SuggestionBean será populado pela classe SuggestionUtils com valores sugestivos de e-mail e senha, sendo exibido na página de erro que reportará o email ou senha ilegal.

    A classe ResultBean SuggestionBean e a classe para populá-lo são apresentadas nas Listagens 4 e 5 respectivamente.

    Listagem 4. Classe ResultBean para a aplicação de cadastro 
    Fonte: cadastro/src/goetten/SuggestionBean.java.
    
    package goetten;
    public class SuggestionBean {
       private String email;
       private String password;
       public SuggestionBean(String email, String password) {
       this.email = email;
       this.password = password;
       }
       public String getEmail() {
       return(email);
       }
       public String getPassword() {
       return(password);
       }
       public void setEmail (String email){
       this.email = email;
       }
       public void setPassword (String password){
       this.password = password;
       }
    }
    

    Listagem 5. Classe para popular o ResultBean 
    Fonte: cadastro/src/goetten/SuggestionUtils.java.
    
    package goetten;
    public class SuggestionUtils {
       private static String[] suggestedAddresses =
          /* sugestões de emails para o usuário */
         { "nome.sobrenome@datasul.com.br",
         "nome@gmail.com",
         "nome@ibm.com",
         "nome@oracle.com" };
       /* String com os possíveis caracteres para a senha do usuário */
       private static String chars = "abcdefghijklmnopqrstuvwxyz0123456789";
       public static SuggestionBean getSuggestionBean() {
          /* Recuperando uma sugestão randômica para o campo de email */
          String address = randomString(suggestedAddresses);
          /* Montando exemplo de senha com 8 caracteres randômicos */
          String password = randomString(chars, 8);
          return(new SuggestionBean(address, password));
       }
    
       public static int randomInt(int range) {
          return((int)(Math.random() * range));
       }
    
       public static String randomString(String[] strings) {
          return(strings[randomInt(strings.length)]);
       }
    
       public static char randomChar(String string) {
          return(string.charAt(randomInt(string.length())));
       }
       
    	public static String randomString(String string, int length) {
           StringBuffer result = new StringBuffer();
           for(int i=0; i<length; i++) {
              result.append(randomChar(string));
           }
           return(result.toString());
       }
    }
    
    Action

    Um Action é uma classe Java que estende o org.apache.struts.Action. O ActionServlet, que faz o papel de controlador da aplicação, preenche o ActionForm (JavaBean) e então transmite-o para o Action. Um Action é geralmente responsável por validar a entrada, acessar as informações comerciais e determinar qual ActionForward retornar para o controlador.

    No arquivo de configuração da aplicação, definimos o nome lógico register para o action, apontando para a classe RegisterAction.java. A Listagem 6 detalha o Action da aplicação.

    Listagem 6. Action da Aplicação 
    Fonte: cadastro/src/goetten/RegisterAction.java.
    
    1. package goetten;
    2. import javax.servlet.http.*;
    3. import org.apache.struts.action.*;
    4. public class RegisterAction extends Action {
    5. public ActionForward execute(ActionMapping mapping,
    6. ActionForm form,
    7. HttpServletRequest request,
    8. HttpServletResponse response)
    9. throws Exception {
    10. UserFormBean userBean = (UserFormBean)form;
    11. String email = userBean.getEmail();
    12. String password = userBean.getPassword();
    13. SuggestionBean suggestionBean = SuggestionUtils.getSuggestionBean();
    14. request.setAttribute("suggestionBean", suggestionBean);
    15. if ((email == null) || (email.trim().length() 
    

    Embora bastante simples, a classe RegisterAction efetua todas as ações que normalmente os Actions fazem.

    A classe RegisterAction estende a classe Action fornecida pelo Struts (linha 4). Entre as linhas 5 e 8 declaramos algumas classes que serão utilizadas pela aplicação. Em seguida (linha 10), há uma coerção aplicada para UserFormBean para que possa ser possível extrair os atributos e-mail (linha 11) e password (linha 12). Nas linhas 13 e 14 instanciamos o resultBean e chamamos os métodos para definir valores aos atributos.

    O Action pode retornar ainda três tipos diferentes de ActionForward:

    • bad-address: o e-mail informado pelo usuário é invalido (linha 16);
    • bad-password: a senha informada não contém no mínimo oito caracteres (linha 18);
    • success: todos os parâmetros informados atendem a regra da aplicação (linha 20).

    Estes ActionForwards foram definidos no arquivo de configuração, conforme a Listagem 7.

    Listagem 7. Trecho do struts-config.xml que define os Forwards da aplicação 
    Fonte: cadastro/WEB-INF/strutsconfig.
    xml.
    
    ...
       <forward name="success"
          path="/WEB-INF/results/result.jsp"/>
       <forward name="bad-address"
          path="/WEB-INF/results/bad-address.jsp"/>
       <forward name="bad-password"
          path="/WEB-INF/results/bad-password.jsp"/>
    ...
    

    Camada de visualização

    Para finalizar a aplicação, é necessário que sejam criados o formulário para que o usuário informe e-mail e senha, e os arquivos de resultado (para bad-address, bad-password e sucess). As Listagens 8, 9 e 10 apresentam os códigos destas páginas, respectivamente. Você pode observar que são páginas JSP simples e fáceis de serem entendidas.

    Listagem 8. Página para ser exibida caso seja informado um e-mail inválido 
    Fonte: cadastro/WEB-INF/results/badaddress.jsp.
    
    <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
    
    <%@page contentType="text/html" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <HTML>
    <HEAD>
       <TITLE>ERRO: Endereço de Email inválido</TITLE>
    </HEAD>
    <BODY BGCOLOR="#FDF5E6">
    <CENTER>
       <H1>Endereço de E-mail inválido</H1>
       O Email
       "<bean:write name="userFormBean" property="email"/>"
       Não segue o padrão nome@servidor.com.br (como.,
       <bean:write name="suggestionBean" property="email"/>).
       <P>
       <A HREF="../pages/register.jsp">Voltar</A>.
    </CENTER>
    </BODY>
    </HTML>
    

    Listagem 9. Página para ser exibida caso seja informado uma senha inválida 
    Fonte: cadastro/WEB-INF/results/badpassword.jsp.
    
    <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
    
    <%@page contentType="text/html" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <HTML>
    <HEAD>
       <TITLE>Senha Inválida</TITLE>
    </HEAD>
    <BODY BGCOLOR="#FDF5E6">
    <CENTER>
       <H1>Senha Inválida</H1>
       A senha digitada
       "<bean:write name="userFormBean" property="password"/>"
       não contém a quantidade mínima de caracteres necessários.
       Exemplo de senha:
       <bean:write name="suggestionBean" property="password"/>.
       <P>
       <A HREF="../pages/register.jsp">Voltar</A>.
    </CENTER>
    </BODY>
    </HTML>
    

    Listagem 10. Página de sucesso, caso todos os campos tenham sido preenchidos corretamente 
    Fonte: cadastro/WEB-INF/results/result.jsp.
    
    <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
    
    <%@page contentType="text/html" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <HTML>
    <HEAD>
       <TITLE>Sucesso</TITLE>
    </HEAD>
    <BODY BGCOLOR="#FDF5E6">
    <CENTER>
       <H1>O Registro foi efetuado com sucesso.</H1>
       <UL>
       <LI>Email:
       <bean:write name="userFormBean" property="email"/>
       <LI>Senha:
       <bean:write name="userFormBean" property="password"/>
       </UL>
    </CENTER>
    </BODY>
    </HTML>
    

    Falta agora apenas o formulário para que o usuário possa informar e-mail e senha. A página JSP para este formulário é apresentada na Listagem 11.

    Listagem 11. Formulário para que o usuário informe e-mail e senha 
    Fonte: cadastro/pages/actions/register.jsp.
    
    <%@page contentType="text/html" %>
    
    <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <HTML>
    <HEAD><TITLE>Registro de Nova Conta</TITLE></HEAD>
    <BODY BGCOLOR="#FDF5E6">
    <CENTER>
       <H1>Registro de Nova Conta</H1>
       <html:form action="/actions/register">
       Email: <html:text property="email"/><BR>
       Senha: <html:password property="password"/><BR>
       <html:submit value="Efetuar Registro"/>
      </html:form>
    </CENTER>
    </BODY>
    </HTML>
    

    A taglibs html do Struts faz o mapeamento automático dos campos do formulário com os atributos do bean associado no Action, através da tag . Os atributos não encontrados no Bean são desconsiderados.

    Para poder executar a aplicação, precisamos agora compilar as classes Java, e copiar a pasta para o diretório webapps do Tomcat. Para compilar as classes, siga os seguintes passos:

    1. Abra uma sessão do console (prompt do dos ou shell do linux) e vá até o diretório cadastro/WEBINF/ src. Observe que neste diretório encontra-se o arquivo build.xml, que é o configurador para fazermos o build automático com o Ant.

    2. Execute o comando ant. Neste momento, o Ant fará a compilação dos arquivos .java e posicionará os arquivos .class (.java compilados), na pasta cadastro/WEB-INF/classes/goetten.

    3. Se estiver utilizando uma IDE, como o eclipse (www.eclipse.org), o build pode ser feito pela própria IDE, conforme demonstrado na Figura 4.

    4. A pasta cadastro precisar ser copiada para o diretório webapps do Tomcat. Após isto, é aconselhável reiniciar o Conteiner.
    Para visualizar o resultado, precisamos acessar o endereço http://localhost:8080/pages/register.jsp. O resultado pode ser observado na Figura 5.

    Se tentarmos submeter o formulário com os dados desta forma, veremos uma tela similar à apresentada na Figura 6.

    Se o campo de e-mail for preenchido corretamente com o e-mail vicente.junior@datasul.com.br, por exemplo, mas no campo senha for informado apenas três dígitos, veremos uma nova mensagem de erro, conforme a Figura 7.

    Se o campo e-mail for preenchido corretamente e o campo senha possuir no mínimo oito caracteres, é exibida então uma mensagem de sucesso, informando que o registro do usuário foi efetuado com sucesso, conforme a Figura 8.

    Conclusão

    Aplicações web normalmente são componentes críticos do dia a dia de uma empresa. Como sempre, as equipes de desenvolvimento precisam construir aplicações em tempo recorde, mas têm que construí-las corretamente, de forma a não dificultar a sua manutenção e fazer com que a performance não seja comprometida.

    O framework Struts não é uma tecnologia em específico, mas sim um conjunto destas que possibilita o desenvolvimento de aplicações web utilizando-se do modelo MVC-2. Este modelo é implementado no Struts através de um servlet que controla a aplicação, o ActionServlet, sendo este o responsável pelo controle do fluxo entre as páginas JSP e as diversas camadas da aplicação. O Struts implementa ainda o padrão MVC/Layers usando ActionForwards e ActionMappings para manter as decisões do fluxo do controle fora da camada de apresentação.

    Esta definição bem clara das camadas em uma aplicação permite a distribuição do trabalho, de forma que o designer pode desenvolver as páginas JSP"s sem se preocupar com o restante da aplicação, e a sua integração será bastante simples através da utilização das taglibs do próprio Struts.

    Por se tratar de um conjunto de tecnologias, o aprendizado do Struts pode tornar-se bastante dispendioso. Outro ponto que pode dificultar o aprendizado deste framework é a nomenclatura não muito clara dos componentes do Struts.

    Apesar destas dificuldades, os pontos positivos e a utilização no mercado do Struts são fatores motivantes para seu aprendizado e utilização. Além destes, podemos destacar também:

    • O Struts melhora, em geral, o desempenho das aplicações Web;
    • Os componentes ActionForm minimizam o código de subclasse e encurtam as hierarquias de subclasses;
    • As bibliotecas de tags Struts fornecem funcionalidades que agilizam o desenvolvimento da aplicação;
    • Os componentes do Struts são reutilizáveis pela aplicação;
    • As estratégias de localização do Struts reduzem a necessidade de JSPs redundantes, já que não há necessidade de desenvolver versões diferentes da página JSP para cada idioma da aplicação;
    • O Struts é designado como uma arquitetura aberta;
    • O Struts é leve. Todo o framework é composto apenas por cinco bibliotecas de tags e cinco pacotes básicos;
    • O Struts é compatível com os padrões (design patterns);
    • O Struts possui código fonte aberto e uma ótima documentação disponível que auxilia bastante àqueles que estão iniciando a utilização desta tecnologia.

    Referências

    • Struts – site oficial: http://struts.apache.org/.
    • CAVANESS, Chuck. Programming Jakarta Struts. O"REILLY, 2002. ISBN: 0-596- 00328 – 5
    • DUDNEY, Bill. Jakarta Pitfals. Willey Publishing, 2003 ISBN: 0- 471- 44915-6
    • HUSTED, Ted. Struts in Action. Manning Books, 2004. ISBN: 85- 7393-299- 6
    • SPIELMAN, Sue. The Struts Framework - Pratical Guid for Java Programmers. Morgan Kaufmann Publishers, 2003. ISBN: 1- 55860- 862- 1
  • Vicente Goetten Júnior

    Vicente Goetten Júnior - Visite o site do autor: www.goetten.org.
    Atua como Analista de Sistemas da Datasul Tecnologia (www.datasul.com.br), em Joinville – SC. É formado em Tecnologia da Informação pela UTESC (www.utesc.br) e possui MBA em Gestão empresarial pela Fundação Getúlio Vargas.