Esse artigo faz parte da revista Java Magazine edição 19. Clique aqui para ler todos os artigos desta edição
style="MARGIN: 0cm 70.75pt 0pt 0cm; TEXT-ALIGN: left" align=left>Entre as mais importantes e úteis funcionalidades do Struts estão a coleta e a validação de dados postados via formulários HTML, além do redirecionamento do processamento (que geralmente é baseado na verificação desses dados). Neste artigo, vamos falar sobre a camada View no Struts, o "V" da arquitetura MVC, abordando taglibs, mensagens, ActionForms, DynaActionForms, internacionalização e alternativas de validação.
Componentes do View
Em aplicações Struts, a camada View pode ser composta de páginas HTML, imagens e arquivos multimídia, páginas JSP (usando ou não taglibs do Struts), ActionForms, que recebem e disponibilizam os dados de formulário para processamento, e, indiretamente, de arquivos de propriedades, onde são configurados textos a serem exibidos pela aplicação. Na camada View podem também ser usados mecanismos de templates como o Tiles, que é parte do framework, ou o Jakarta Velocity, entre outras técnicas e tecnologias. Aqui focaremos em páginas JSP e nas tecnologias oferecidas nativamente pelo Struts.
Taglibs do Struts
São fornecidas cinco bibliotecas com o Struts: HTML, com tags para criação de páginas dinâmicas e formulários; Beans para acesso a JavaBeans e suporte a internacionalização; Logic, com tags para loops e execução condicional; Tiles para a utilização do mecanismo de templates embutido; e Nested, para a manipulação de estruturas hierarquizadas de beans.Veja na Listagem 1 um exemplo de formulário utilizando algumas dessas taglibs. Observe no código a declaração das taglibs com a diretiva <%@ taglib uri="URI” prefix=”prefixo”> e a definição dos campos utilizando <html:tipo>. A Figura 1 mostra a tela resultante.
Nota: O uso de taglibs, tecnicamente, não é obrigatório nas páginas JSP de aplicações Struts, porém sua utilização facilita muito o desenvolvimento, permitindo tirar proveito dos recursos automáticos do framework, como preenchimento e validação de campos de formulário.
Prefira a JSTL
As bibliotecas de tags do Struts surgiram antes da padronização da JSTL (JSP Standard Tag Library). Várias têm praticamente as mesmas funcionalidades, e a recomendação é utilizar as tags equivalentes da JSTL no lugar das taglibs Logic e Bean do Struts. Veja na Listagem 2 um exemplo de página JSP com as tags Logic e na Listagem 3 o código equivalente usando a JSTL. A Figura 2 apresenta a tela resultante.
A JSTL foi discutida em detalhes na coluna "Pente Fino", nas Edições 7, 8 e 9. Veja também a coluna "Java Livre" nesta edição, que demonstra a uso da JSTL em uma aplicação web (mas sem uso do Struts).
Mensagens e internacionalização
Quantas vezes você precisou alterar dezenas de páginas porque uma mensagem ou um nome de botão comum foi modificado? Pois bem, com o Struts pode-se definir num único local (no arquivo ApplicationResources.properties) as mensagens de erros e os valores exibidos em botões, textos em HTML e outros componentes visuais. E não é necessária a recompilação para que as mudanças passem a valer.
O ApplicationResources.properties é usado também para internacionalização através das classes Locale e ResourceBundle (veja o quadro "i18n e Java"). Esse arquivo pode ter qualquer nome, mas a extensão .properties é obrigatória. Deve ser criada uma versão para cada idioma, além do default. Suponha que usemos o prefixo padrão "ApplicationResources", então o arquivo com as mensagens default deve chamar-se ApplicationResources.properties e conter as mensagens no idioma default do servidor. Para mensagens em outros idiomas o arquivo deve ter o nome ApplicationResources_xx.properties, onde xx é o código ISO para o idioma. Por exemplo podemos ter ApplicationResources.properties com mensagens em inglês e ApplicationResources_fr.properties com mensagens em francês. É possível também especificar o país, tratando variantes de idiomas como pt_BR para o português do Brasil.
Dessa forma, poderíamos ter um arquivo ApplicationResources.properties com o seguinte conteúdo:
pagina.titulo=Welcome to SouJava!
label.user=User
label.password=Password
E um arquivo ApplicationResources_pt_BR.properties com as mensagens correspondentes para o Brasil:
pagina.titulo= Bem-vindo ao SouJava!
label.user=Usuário
label.password=Senha
Veja dois JSPs simples demonstrando a internacionalização na Listagem 4 e um exemplo de saída na Figura 3.
ActionForms
Entre os mais importantes componentes da camada View, estão os ActionForms, que são criados estendendo-se a classe abstrata org.apache.struts.action.ActionForm. Por meio de ActionForms, que seguem o padrão JavaBeans, o Struts pode capturar os dados de um formulário HTML e passá-los para a camada de negócios. Devem ser definidos atributos e métodos get/set para cada campo do formulário a ser tratado na aplicação. Para processar um formulário de cadastro, por exemplo você criaria uma subclasse de ActionForm, digamos cadastroForm, definindo os atributos nome, endereço etc. e os métodos get/set correspondentes.
Além de receber os dados do formulário, o ActionForm é responsável pela validação, que pode ser realizada no método validate() ou usando o framework Validator (veja adiante). Os possíveis erros são retornados em um objeto ActionErrors. Não ocorrendo erros, o Struts chama o método execute() do Action[1] declarado no elemento <action-mappings> do struts-config.xml. Passa como parâmetro o ActionForm, contendo os dados validados e disponíveis para processamento.
Dica: É recomendável usar ActionForms apenas para validação e para o transporte da informação, transferindo os dados que chegam ao execute() do Action para um DTO (Data Transfer Object)[2], enviado posteriormente à camada de dados.
ActionErrors
Como vimos, o objeto ActionErrors mantém uma lista de erros detectados no método validate() do ActionForm. Se validate() retornar null ou devolver um objeto ActionErrors de tamanho zero, o Struts considera que os valores fornecidos no formulário estão validados – neste caso, o método execute() do Action é chamado.
Um objeto ActionErrors é inserido como um atributo do request após a validação, ficando acessível pela tag <html:errors> no form declarado em <action-mappings input ...>. Veja na Listagem 5 um exemplo de ActionForm com os métodos validate() e reset(). Para exibir uma mensagem de erro específica na página, passamos o nome do erro no parâmetro property de <html:errors>, que deve ser igual ao primeiro parâmetro passado para o método ActionErrors.add() no método validate(). Veja resultado de uma página com erros de validação na Figura 4.
Por exemplo, supondo que existe a entrada campoNome.faltando no ApplicationResources.properties, e o seguinte método validate() no seu ActionForm:
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors erros = new ActionErrors();
if (nome==null || nome.equals("")
erros.add("nome", new ActionError("campoNome.faltando"));
return erros;
}
Você pode usar o seguinte código no JSP, para exibir o erro ao lado do campo:
<html:form action="/cadastro">
Nome: <html:text property="nome"/><html:errors property="nome"/>
...
Voltaremos a essa técnica num exemplo posterior.
Nota: No Struts 1.1 foi introduzida ActionMessages, como superclasse de ActionErrors. As duas classes são usadas da mesma forma, mas são voltadas a mensagens de tipos diferentes. ActionMessages é recomendada para mensagens genéricas e avisos; ActionErrors deve ser reservada a erros propriamente ditos.
DynaActionForms
Sabemos que ActionForms facilitam a coleta de dados em formulários HTML, porém quando temos uma aplicação com muitos formulários, pode pesar a exigência de criar uma classe para cada um. Outro inconveniente é que inserções ou remoções de campos do formulário obrigam a alteração do ActionForm e a sua recompilação.
Buscando resolver esses problemas, foram introduzidos, na versão 1.1 do Struts, os DynaActionForms. Para usá-los, além de se definir os campos no struts-config.xml em elementos <form-bean>, devem ser declarados elementos <form-property> para cada campo. A classe básica para forms dinâmicos é org.apache.struts.action.DynaActionForm. A instanciação dos objetos dos forms é automática e o mapeamento é feito em <action attribute=”nome-do-formulario”>, dentro do elemento <action-mappings>.
Da mesma maneira que ActionForms comuns, DynaActionForms são passados como parâmetro do método ...