Você está na página 1de 29

Tutorial - Struts Framework

Welington B. Souza wbsouza@yahoo.com.br

Introduo
O objetivo deste tutorial dar uma viso geral sobre o funcionamento da Struts Framework. Aqui voc ir aprender o necessrio para comear a desenvolver uma aplicao web usando a Struts. Embora esta framework implemente o padro MVC, isso no quer dizer que vamos seguir a risca as explicaes de cada camada, mas sim expondo o contedo terico dependendo da necessidade do tutorial, visando a facilidade no entendimento dos conceitos medida em que eles forem necessrios. A Struts Framework um projeto open source mantido pela Apache Software Foundation. uma implementao do design pattern MVC (Model-View-Controller) para aplicaes java com internet. O objetivo do pattern MVC separar de maneira clara a camada de apresentao (View) da camada de Negcio (Model). A arquitetura MVC - Model-View-Controller (Modelo-Visualizao-Controle) um padro que separa de maneira independente o Modelo, que representa os objetos de negcio (Model) da camada de apresentao, que representa a interface com o usurio ou outro sistema (View); e o Controle de fluxo da aplicao (Controller).

Figura 1 - O Padro MVC A Struts Foi escrita por Craig McClanahan em Maio de 2000, e desde ento vem sendo melhorado pela comunidade open-source. Foi desenvolvida com o objetivo de fornecer uma framework para facilitar o desenvolvimento de aplicaes para web.

Motivos utilizar a Struts Framework


Se tornou um padro de mercado; Garantia de que algum (Apache Group) ir manter a framework (correo de bugs e novos releases); Integrao com a maioria das IDEs de mercado No reinventar a roda, focando os seus esforos em regras de negcio; Separar a camada de negcio da camada de apresentao; J incorpora diversos design patterns Criao de aplicaes padronizadas, facilitando a manuteno; Criao de Aplicaes Internacionalizadas; Possibilidade de gerar a sada de acordo com o dispositivo usado (HTML, SHTML, WML, etc); Aumentar a produtividade

Licena
A Struts est disponvel sobre a licena "free-to-use-license" da Apache Software Foundation (veja http://www.apache.org/LICENSE-1.1).

Detalhes do funcionamento

Figura 2 - Fluxo de Navegao nos componentes da Struts 1. O usurio faz uma solicitao atravs de uma url no browser. Ex: http://localhost:8080/cadastro/listUsers.do. Note que no final da url tem um .do que ser usado para invocar (na verdade mapear) o servlet controller da struts. 2. Se for a primeira solicitao que o container recebeu para esta aplicao, ele ir invocar o metodo init() da ActionServlet (controller da Struts) e ir carregar as configuraes do arquivo strutsconfig.xml em estruturas de dados na memria. Vale lembrar que esta passagem s ser executada uma nica vez, pois nas solicitaes subsequentes, a servlet consulta estas estruturas na memria para decidir o fluxo a ser seguido. 3. Baseado no fluxo definido no arquivo struts-config.xml, e que neste momento j se encntra carregado em estruturas na memria, o ActionSerlet identificar qual o ActionForm (classe para a validao dos dados) ir invocar. A classe ActionForm atravs do mtodo validate ir verificar a integridade dos dados que foram recebidos na solicitao que vem do browser. 4. O controle da aplicao retomado pelo ActionServlet, que verifica o resultado da verificao do ActionForm. Se faltou alguma coisa (campo no preenchido, valor invlido, etc), o usurio recebe um formulrio html (geralmente o mesmo que fez a solicitao), informando o motivo do no atendimento da solicitao, para que o usurio possa preencher corretamente os dados para fazer uma nova solicitao. Se no faltou nenhuma informao, ou seja, todos os dados foram enviados corretamente, o controller passa para o proximo passo (Action). 5. O ActionServlet, baseado no fluxo da aplicao (estruturas j carregadas em memria) invoca uma classe Action. A classe Action passar pelo mtodo execute que ir delegar a requisio para a camada de negcio. 6. A camada de negcio ir executar algum processo (geralmente popular um bean, ou uma coleo). O resultado da execuo deste processo (objetos j populados) ser usado na camada de

apresentao para exibir os dados. 7. Quando o controle do fluxo da aplicao votar ao Action que invocou o processo da camada de negcio, ser analisado o resultado, e definido qual o mapa adotado para o fluxo da aplicao. Neste ponto, os objetos que foram populados na camada de negcio sero "atachados" como atributos na seo do usurio. 8. Baseado no mapeamento feito pelo o Action, o Controller faz um forward para o JSP para apresentar os dados. 9. Na camada de apresentao (View), os objetos que foram setados como atributos da sesso do usurio sero consultados para montar o html para o browser. 10.Chega o html da resposta requisitada pelo usurio. O Controller j vem implementado na Struts, embora, caso seja possvel estend-lo a fim de adicionar funcionalidade. O fluxo da aplicao programado em um arquivo XML atravs das aes que sero executadas. As aes so classes base implementadas pela framework seguindo o padro MVC. Assim devemos estend-las a fim de adicionar a funcionalidade desejada. A gerao da interface feita atravs de custom tags, tambm j implementadas pela Struts, evitando assim o uso de Scriptlets (cdigos java entre <%> e <%>), deixando o cdigo JSP mais limpo e fcil de manter.

Baixando e instalando a documentao


A Struts Framework pode ser baixada em http://jakarta.apache.org/struts. Neste tutorial vamos usar a verso 1.1, pois incorpora uma srie de melhorias em relao a verso anterior, e j temos uma verso estvel para produo.Aps o download, descompactar o arquivo; dentro do diretrio descompactado, possui um diretrio chamado webapps contendo as aplicaes exemplo. Se voc tiver usando o TomCat ou outro WebContainer, copie o arquivo struts-documentation.war, para o diretrio <webapps> do seu container. Neste ponto a documentao da Struts j se enconrtra instalada na sua mquina.Para acess-la v para http://localhost:8080/struts-documentation.

Projeto do Tutorial
Para entender melhor o funcionamento, vamos fazer uma aplicao prtica. Desenvolveremos um cadastro de Usurios com incluso, alterao e excluso. Portanto, um nome sugestivo para a nossa aplicao web "cadastro" Para criar uma nova aplicao com a Struts Framework, devemos seguir os seguintes passos: V para a linha de comando do seu sistema operacional; V para o diretrio onde a Struts framework foi descompactada, e entre no diretrio webapps; Faa a seguinte sequencia de comandos: mkdir cadastro cd cadastro jar -xvf ../struts-blank.war Agora temos uma aplicao web (em branco) baseada na template da Struts para comear a brincar. Mova este diretrio para o local que mais lhe convier, uma vez que os fontes da sua aplicao ficaro abaixo desta estrutura. Estrutura de diretrios da aplicao web com Struts: RootDir | +-- META-INF | Contm meta informao. Usado pelo Web Container, utilitrios, etc. | +-- WEB-INF | +-- classes | | Este diretrio contm as classes java da sua aplicao (camada de negcio). | | | +-- java | | | +-- resources

| | | +-- application.properties | Contm as mensagens (textos fixos) da aplicao, | inclusive as mensagens de erros. | Este arquivo responsvel pela internacionalizao da aplicao. +--- lib | | | +-- struts.jar | Contm as classes da Struts (Controller, Helper class, | Biblioteca de Tags, etc) | Tambm no diretrio lib contm outras bibliotecas da aplicao web. | +--*.tld | Contm os XML descriptors da biblioteca de tags da Struts. | +-- struts-config.xml | Arquivo de configurao da Struts. | Mais detalhes sobre este arquivo sero vistos adiante. | +-- web.xml Arquivo de configurao da aplicao web, relativo ao Web Container. Mais detalhes sobre este arquivo sero vistos adiante.

O arquivo web.xml
O arquivo web.xml dever ficar algo parecido com: <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <!-- Standard Action Servlet Configuration (with debugging) --> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <!-- Standard Action Servlet Mapping --> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- The Usual Welcome File List --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list>

<!-- Struts Tag Library Descriptors --> <taglib> <taglib-uri>/tags/struts-bean</taglib-uri> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-html</taglib-uri> <taglib-location>/WEB-INF/struts-html.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-logic</taglib-uri> <taglib-location>/WEB-INF/struts-logic.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-nested</taglib-uri> <taglib-location>/WEB-INF/struts-nested.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-tiles</taglib-uri> <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location> </taglib> </web-app> Temos no arquivo web.xml, trs importantes sees: A definio da Servlet que representa o Controller (ActionServlet) O URL mapping da servlet, para informar como chamar esta servlet As definies da biblioteca de tags da Struts Podemos ver pelo servlet-mapping que a nossa servlet ser invocada por http://localhost:8080/cadastro/<algumaCoisa>.do, substituindo-se <algumaCoisa> pela ao desejada.

Banco de dados
Por questes de facilidade de obteno e configurao e Usaremos o MySQL como banco de dados. O MySql pode ser baixado em http://www.mysql.com Script de criao do banco de dados: CREATE DATABASE strutsdemo; USE strutsdemo; CREATE TABLE usuario( id_usuario INTEGER NOT NULL, nome VARCHAR(50) NULL, login VARCHAR(20) NULL, senha VARCHAR(20) NULL, sexo CHAR NULL, ativo BOOL NULL, faixa_idade INTEGER, PRIMARY KEY(id_usuario) ); INSERT INTO usuario (id_usuario, nome, login, senha, sexo, ativo, faixa_idade) VALUES (1, 'Marcelo Ferreira Dantas', 'marcelo', 'marcelo', 'M', 1, 1); INSERT INTO usuario (id_usuario, nome, login, senha, sexo, ativo, faixa_idade) VALUES (2, 'Gerson Hernandes Vilela', 'gerson', 'gerson', 'M', 1, 2); INSERT INTO usuario (id_usuario, nome, login, senha, sexo, ativo, faixa_idade) VALUES (3, 'Manuela Rodrigues', 'Manuela', 'manu', 'F', 1, 2); Para acessar os dados no MySQL ser necessrio adicionar o driver JDBC no lib da nossa aplicao. O driver

pode ser baixado em http://www.mysql.com/downloads/api-jdbc-stable.html. Aps baix-lo, descompactar e copiar o arquivo mysql-connector-java-3.0.8-stable-bin.jar para diretrio lib do seu container (no tomcat "$CATALINA_HOME/common/lib" j no JBoss vai diretrio "$JBOSS_HOME/server/default/deploy").

Definindo as configuraes do Connection Pool


A maioria das aplicaes para web que usam banco de dados podem ser beneficiadas por um Connection Pool (coleo de conexes que ficam permanentemente abertas com o SGBD). Estabelecer uma conexo com o banco de dados a cada solicitao que chega no web server para consultar/manipular dados um processo muito dispendioso (conexo e verificao de permisses do usurio do banco). Uma aplicao no usa banco de dados o tempo todo, somente em algums momentos para obter os dados, depois esta conexo no mais necessria. Nesse sentido, um Connection Pool pode ajudar bastante, eliminando um overread desnecessrio de se reconectar a cada solicitao que chega, pois ele far o gerenciamento da coleo de conexes prontas para serem usadas, e "marcar" as conexes em uso. Se por acaso voc pegar uma conexo e ficar um determinado tempo sem fazer nada (timeout), o Connection Pool regata esta conexo para uso, e invalida o objeto de conexo que voc pegou anteriormente. Tamanha a importncia deste tpico, que acabou entrando na especificao JDBC (javax.sql.DataSource). Praticamente todos os Containers possuem um mecanismo que fornecem um Connection Pool. Embora o nosso projeto seja baseado no MySQL, que provavelmente muitos diro que no h necessidade de se fazer isto com o MySQL, pois o processo de conexo extremamente rpido, no podemos dizer o mesmo de outros bancos. Mesmo assim, interessante usar um Connection Pool, pois pode parecer imperceptvel para uma s solicitao chegando, mas em um ambiente de produo, com a sua aplicao sendo macivamente solicitada para manipular e consultar dados, da sim haver uma grande diferena. A Struts Framework implementa um Connection Pool usando DataSource. Na verso 1.0, a Conexo era obtida do ActionServlet. No entanto, nas nos betas e release candidate da verso 1.1 o metodo para obteno de conexes ficou deprecated, e passaram esta tarefa para o Action. Por fim no release 1.1 de produo, as classes que tratam do DataSource foram parar no arquivo struts-legacy.jar, indicando claramente a inteno de descontinuar esta funcionalidade em favor de uma soluo padro (JCA), ou seja, implementada pelo container; apesar de ainda continuar funcionando. Assim, vamos usar uma implementao fornecida pelo container. Para definir as configuraes de um DataSource no TomCat, siga os passos abaixo: Altere o arquivo server.xml adicionando o trecho abaixo: <Host name="localhost" debug="0" appBase="webapps" unpackWARs="true" autoDeploy="true"> ... <DefaultContext> <Resource name="jdbc/StrutsDemoDS" auth="Container" type="javax.sql.DataSource" scope="Shareable"/> <ResourceParams name="jdbc/StrutsDemoDS"> <parameter><name>factory</name><value>org.apache.commons.dbcp.BasicData SourceFactory</value></parameter> <parameter><name>driverClassName</name><value>com.mysql.jdbc.Driver</va lue></parameter> <parameter><name>url</name><value>jdbc:mysql://localhost/strutsdemo</va lue></parameter> <parameter><name>username</name><value>root</value></parameter> <parameter><name>password</name><value>root</value></parameter> <parameter><name>maxActive</name><value>20</value></parameter> <parameter><name>maxIdle</name><value>10</value></parameter> <parameter><name>maxWait</name><value>100</value></parameter> </ResourceParams> </DefaultContext> ... </Host> No cdigo Java, quando precisar de uma conexo de banco de dados, voc ir solicitar uma conexo ao Connection Pool, o qual ir marcar uma conexo no Pool, como sendo usada, e lhe dar algum tempo para fazer alguma coisa. To logo que voc use a conexo para consultar ou manipular dados no banco de dados, ser necessrio devolver a conexo para o pool (se no fizer isto o Connection Pool fecha a conexo para voc e a resgata para o pool). Para fazer isto, basta executar o mtodo close(), que na verdade no a fecha,

mas devolve para o Pool (dependendo da implementao do Connection Pool, poder ter variaes da maneira de devolver ao pool, algo do tipo invocar um metodo do tipo releaseConnection, do objeto Connection Pool).

Definindo a Camada de Negcio


Para listar os usurios cadastrados precisaremos definir as classes que faro parte da nossa camada de Negcio. Devemos ter duas classes. Uma classe que representa o registro do usurio "UserData" (value object) , e outra que ir gerenciar o cadastro dos usurios "AdminUsers". Segue abaixo o cdigo das duas classes: package strutsdemo.bean; public class UserData { private private private private private private private int idUsuario; String nome; String login; String senha; String sexo; boolean ativo; int faixaIdade;

public void setIdUsuario(int idUsuario) { this.idUsuario = idUsuario; } public void setLogin(String login) { this.login = login; } public void setNome(String nome) { this.nome = nome; } public void setSenha(String senha) { this.senha = senha; } public void setSexo(String sexo) { this.sexo = sexo; } public void setAtivo(boolean ativo) { this.ativo = ativo; } public void setFaixaIdade(int faixaIdade) { this.faixaIdade = faixaIdade; } public int getIdUsuario() { return idUsuario; } public String getLogin() { return login; } public String getNome() { return nome; } public String getSenha() { return senha; } public String getSexo() { return sexo; } public boolean getAtivo() { return ativo; } public String getDescricaoStatus() { return this.ativo ? "Ativo": "Inativo"; } public int getFaixaIdade() {

return faixaIdade;

} package strutsdemo.bean; import import import import import java.sql.Connection; java.sql.PreparedStatement; java.sql.ResultSet; java.sql.SQLException; java.util.LinkedList;

import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; public class AdminUsers { protected static DataSource dataSource; public AdminUsers() throws Exception { if (dataSource == null) { try { InitialContext ic = new InitialContext(); // se for tomcat dataSource = (DataSource) ic.lookup ("java:comp/env/jdbc/StrutsDemoDS"); // no JBoss faa // dataSource = (DataSource) ic.lookup ("java:jdbc/StrutsDemoDS"); } catch (NamingException ex) { System.out.println(ex.getMessage()); throw ex; }

protected Connection getConnection() throws SQLException { Connection conn = null; try { conn = dataSource.getConnection(); } catch (SQLException e) { throw e; } return conn; } protected void closeConnection( Connection conn, PreparedStatement stmt, ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException e) { } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { } } if (conn != null) { try {

conn.close(); } catch (SQLException e) { }

public LinkedList getUserList() throws SQLException { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; LinkedList users = new LinkedList(); try { conn = getConnection(); stmt = conn.prepareStatement("select * from usuario"); rs = stmt.executeQuery(); while (rs.next()) { UserData user = new UserData(); user.setIdUsuario(rs.getInt("id_usuario")); user.setNome(rs.getString("nome")); user.setLogin(rs.getString("login")); user.setSenha(rs.getString("senha")); user.setSexo(rs.getString("sexo")); user.setAtivo(rs.getBoolean("ativo")); user.setFaixaIdade(rs.getInt("faixa_idade")); users.add(user); } } catch (SQLException e) { throw e; } finally { closeConnection(conn, stmt, rs); } return users; } public void insertUser(UserData user) throws SQLException { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = getConnection(); stmt = conn.prepareStatement( "insert into usuario \n" + "(id_usuario, nome, login, senha, sexo, ativo, faixa_idade) \n" "values (?, ?, ?, ?, ?, ?, ?)"); stmt.setInt(1, user.getIdUsuario()); stmt.setString(2, user.getNome()); stmt.setString(3, user.getLogin()); stmt.setString(4, user.getSenha()); stmt.setString(5, user.getSexo()); stmt.setBoolean(6, user.getAtivo()); stmt.setInt(7, user.getFaixaIdade()); stmt.executeUpdate();

} catch (SQLException e) { throw e; } finally { if (rs != null) { rs.close(); } if (stmt != null) { stmt.close(); } }

public void updateUser(UserData user) throws SQLException { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = getConnection(); stmt = conn.prepareStatement( "update usuario set \n" + "nome = ?, login = ?, senha = ?, sexo = ?, ativo = ?, faixa_idade = ? \n" + "where id_usuario = ?"); stmt.setString(1, user.getNome()); stmt.setString(2, user.getLogin()); stmt.setString(3, user.getSenha()); stmt.setString(4, user.getSexo()); short ativo = (short) (user.getAtivo()? 1: 0); stmt.setShort(5, ativo); stmt.setInt(6, user.getFaixaIdade()); stmt.setInt(7, user.getIdUsuario()); stmt.executeUpdate(); } catch (SQLException e) { throw e; } finally { if (rs != null) { rs.close(); } if (stmt != null) { stmt.close(); } } } public void deleteUser(int idUsuario) throws SQLException { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = getConnection(); stmt = conn.prepareStatement( "delete from usuario where id_usuario = ?"); stmt.setInt(1, idUsuario); stmt.executeUpdate(); } catch (SQLException e) { throw e; } finally { if (rs != null) { rs.close(); } if (stmt != null) { stmt.close(); } } }

Definindo o Controller
O Controller responsvel por receber as requisies do browser e invocar os objetos de negcio do Model para executar algum processo retornando um resultado que servir de base para que o Controller possa direcionar para o JSP que dever gerar a interface com o usurio. O ActionServlet l as configuraes do arquivo struts-config.xml. Ao receber as solicitaes do usurio, chama o ActionBean correspondente requisio, e de acordo com o resultado do ActionBean, executa um JSP.

Para incluir, alterar ou excluir um usurio, precisamos exibir todos os usurios cadastrados para saber o que fazer. Assim, a nossa primeira implementao ser exibir os usurios j cadastrados.

Siga os procedimentos abaixo:


Criar uma package strutsdemo, e uma classe chamada ListUsersAction dentro desta package. A classe deve estender de org.apache.struts.action.Action (vamos entrar em mais detalhes sobre esta classe na seo "Definindo o Action Bean"). package strutsdemo;

import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import import import import org.apache.struts.action.Action; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionForward; org.apache.struts.action.ActionMapping;

public class ListUsersAction extends Action { /* Metdo que invoca a camada de negcios.*/ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return null; // somente para compilar, implementao futura ... }

Adicionar configurao no arquivo strutus-config.xml do Action Mapping e seus possveis forwards de sada. </struts-config> <action-mappings> <action path="/listUsers" type="strutsdemo.ListUsersAction"> <forward name="success" path="/listUsers.jsp" /> </action> </action-mappings> </struts-config> Neste caso, quando for solicitado pelo browser /listUsers.do" o Controller chamar o ListUsersAction atravs do mtodo process, e se este objeto retornar um ActionForward com o valor "sucess", O controller encaminhar a solicitao para o arquivo "/pages/listUsers.jsp". Se retornar "failure", ser encaminhado para o arquivo "/pages/error.jsp".

Definindo o Action Bean


Como foi visto anteriormente, o Controller ir invocar o Action que foi definido no struts-config.xml. H uma certa discusso sobre que parte pertence o Action e o ActionForm no padro MVC (vamos entrar em maiores detalhes mais adiante em ActionForm, por hora ainda no necessrio). Na realidade tanto o Action, quanto o ActionForm so Helper Classes. A grosso modo podemos entender como classes auxiliadores para execuo no padro MVC. Basicamente, os ActionBeans realizam as seguintes aes: Obtem os valores necessrios do ActionForm, JavaBean, request, session ou de outro local; Chama os objetos de negcio do modelo; Analisa o resultado da chamada da camada de negcio, e baseado nisso, retorna o ActionForward (indicando qual JSP ir apresentar os dados) correspondente O Cdigo da nossa Action ficar assim: package strutsdemo.action; import java.sql.SQLException; import java.util.LinkedList;

import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import import import import import import org.apache.struts.action.Action; org.apache.struts.action.ActionError; org.apache.struts.action.ActionErrors; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionForward; org.apache.struts.action.ActionMapping;

import strutsdemo.bean.AdminUsers; public class ListUsersAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { LinkedList users = null; ActionErrors errors = new ActionErrors(); try { AdminUsers adminUsers = new AdminUsers(); users = adminUsers.getUserList(); HttpSession session = request.getSession(); session.setAttribute("userListBean", users); } catch (SQLException e) { errors.add(ActionErrors.GLOBAL_ERROR, new ActionError ("error.user.list")); getServlet().log("Erro carregando a lista de usurios", e); } if (!errors.isEmpty()) { saveErrors(request, errors); return (mapping.findForward("failure")); } else { return (mapping.findForward("success")); } } }

Definindo a camada de apresentao


A Camada de apresentao representa o view (visualizao) no padro MVC. em sua grande maioria baseada em JSPs e alguns servlets envolvidos na gerao da interface com o usurio ou com outros sistemas. A Struts framework fornece suporte para construir aplicaes multi-idiomas, interao com formulrios e outras utilidades atravs de tags personalizadas (Custom Tags).

Internacionalizao
No nosso projeto (baseado no template struts-blank ), possui um arquivo de chamado application.properties no diretrio cadastro/WEB-INF/classes/java/resources. Este arquivo deve conter as chaves e os valores no formato: chave.subchave=texto que pertence ao idioma padro da aplicao. Vamos adicionar algumas chaves que sero usadas em nosso projeto. Obs: Este arquivo pode ter qualquer nome, desde que termine com .properties. No entanto existe um certo padro, geralmente chamado de ApplicationResources.properties. A nica ressalva, que se voc mudar o nome deste arquivo, tambm dever ser mudado no arquivo struts-config.xml. welcome.title=Bem Vindo ao Projeto Tutorial Struts welcome.heading=Bem vindo! welcome.message=Projeto Tutorial Struts

application.title= Struts Demo - Cadastro index.header=Bem vindo ao Demo da Strutus Framework - Cadastro users.title=Cadastro de Usurios editUser.title=Alterao de Usurio insertUser.title=Incluso de Usurio prompt.idUsuario=Cdigo prompt.nome=Nome prompt.login=Login prompt.senha=Senha prompt.confirmacaoSenha=Confirmao da Senha prompt.sexo=Sexo prompt.ativo=Ativo prompt.status=Status prompt.faixaIdade=Faixa Etria prompt.excluir=Excluir prompt.incluir=Incluir prompt.voltar=Voltar prompt.Masculino=Masculino prompt.Feminino=Feminino prompt.ate20=At 20 anos prompt.de21a30=De 21 a 30 anos prompt.de31a40=De 31 a 40 anos prompt.de41a50=De 41 a 50 anos prompt.de51a60=De 51 a 60 anos prompt.acima60=Acima de 60 anos prompt.senhaAntiga=Senha Antiga prompt.novaSenha=Nova Senha prompt.confirmacaoNovaSenha=Confirmao da Senha button.send=Enviar button.reset=Cancelar error.title=Erro Inesperado error.user.list=Erro obtendo a lista de usurios error.idUsuario.required=O identificador do usurio um campo obrigatrio error.login.required=O login do usurio um campo obrigatrio error.nome.required=O nome do usurio um campo obrigatrio error.get.user=Erro ao carregar o usurio error.senhaAntiga.required=A senha antiga um campo obrigatrio error.novaSenha.required=A nova senha um campo obrigatrio error.confirmacaoNovaSenha.required=A confirmao da nova senha um campo obrigatrio error.ConfirmacaoSenha=Erro na confirmao da nova senha error.user.notFound=Usurio no encontrado error.senhaAntiga=A senha Antiga no confere error.update.user=Erro alterando o usurio error.update.user=Erro incluindo o usurio error.delete.user=Erro excluindo o usurio error.idUsuario.duplicateKey=Este cdigo de usurio j existe Para cada idioma alternativo, devemos adicionar um novo arquivo (no mesmo diretrio do arquivo onde temos o arquivo do idioma padro) no formato "application_xx.properties", onde xx o cdigo ISO do idioma. Ex: (application_en.properties). No arquivo struts-config.xml devemos definir a localizao do arquivo com o idioma padro. Coloque neste: <message-resources parameter="resources.application"/> Obs: Na Struts 1.0 este arquivo era definido no arquivo web.xml Nos JSPs que utilizaremos a internacionalizao deveremos incluir: ... <%@ taglib uri="/tags/struts-bean" prefix="bean" %> ... Para declarar que utilizaremos a TagLibrary struts-bean com o prefixo bean e definida no arquivo /WEBINF/struts-bean.tld, configurados no arquivo web.xml. E finalmente, utilizaremos a tag (no JSP) <bean:message key="chave.subchave"/> onde a chave e a subchave correspondem ao texto que ser inserido de acordo com o idioma do usurio. Exemplo: ...

<h3><bean:message key="application.title"/></h3> ... Por default, a Struts acessa o idioma principal da aplicao. Devemos utilizar a tag <html:html locale="true"> substituindo a tag <html>, assim, deveremos substituir tambm a tag </html> por </html:html> Deste modo, ser usado preferencialmente o idioma principal que se encontra no header "Accept-Language" enviado pelo navegador. Quando o usurio fizer uma solicitao escolher um novo idioma, baseado em uma lista de idiomas suportados, informados previamente, adicionaremos o trecho abaixo: session.setAttribute(Action.LOCALE_KEY,new Java.util.Locale(country, language)); Onde country e language ser a string do pas e que ser feita a traduo. Para mais informaes a respeito do assunto, veja a documentao oficial da Sun disponvel em http://java.sun.com/j2se/1.4.2/docs/guide/intl. Por questes de organizao vamos colocar todos os nossos JSPs no diretrio cadastro/pages/ . Assim, j podemos escrever o nosso primeiro JSP para listar os usurios: <%@ taglib uri="/tags/struts-logic" prefix="logic" %> <%@ taglib uri="/tags/struts-html" prefix="html" %> <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <logic:notPresent name="userListBean" scope="session"> <logic:redirect forward="error"/> </logic:notPresent> <html:html locale="true"> <head> <title><bean:message key="users.title"/></title> </head> <body> <center> <font face="Comic Sans MS" size="3"> <blockquote> <center> <h3><font color="blue"><bean:message key="users.title"/></font></h3> <table width="80%" border="1"> <tr> <th width="10%"><bean:message key="prompt.idUsuario"/></th> <th width="50%"><bean:message key="prompt.nome"/></th> <th width="20%"><bean:message key="prompt.login"/></th> <th width="10%"><bean:message key="prompt.ativo"/></th> <th width="10%"></th> </tr> <%-- loop que percorre a Collection de usuarios --%> <logic:iterate name="userListBean" id="user" > <tr> <td align="center"> <bean:write name="user" property="idUsuario"/> </td> <td> <html:link page="/editUser.do" paramId="idUsuario" paramName="user" paramProperty="idUsuario"> <bean:write name="user" property="nome"/> </html:link> </td> <td><bean:write name="user" property="login"/></td> <td><bean:write name="user" property="descricaoStatus"/></td> <td> <html:link page="/deleteUser.do" paramId="idUsuario" paramName="user" paramProperty="idUsuario"> <bean:message key="prompt.excluir"/> </html:link> </td> </tr>

</logic:iterate> </table> <br/> <html:link page="/insertUser.do">incluir</html:link> <html:link page="/Welcome.do">Pgina Inicial</html:link> </center> </lockquote> </body> </html:html> Neste ponto, j temos uma aplicao funcionando parcialmente (listando os usurios). No entanto se clicar em algum link, ir ocorrer um erro, pois ainda no temos os ActionBeanss necessrios para invocar a camada de negcio. Neste momento para facilitar o entendimento, vamos implementar apenas os Beans necessrios para Alterar o usurio. Devemos criar um ActionBean que dever invocar a camada de negcio e popular um bean com os dados do usurio a ser alterado, e enviar para a camada de apresentao para que os dados possam ser alterados. Segue abaixo o cdigo do ActionBean. package strutsdemo.action; import java.util.Iterator; import java.util.LinkedList; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import import import import import import org.apache.struts.action.Action; org.apache.struts.action.ActionError; org.apache.struts.action.ActionErrors; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionForward; org.apache.struts.action.ActionMapping;

import strutsdemo.bean.AdminUsers; import strutsdemo.bean.UserData; public class EditUserAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ActionErrors errors = new ActionErrors(); try { HttpSession session = request.getSession(); AdminUsers adminUsers = new AdminUsers(); String idUsuario = request.getParameter("idUsuario"); session.removeAttribute("editUserBean"); LinkedList userList = (LinkedList)session.getAttribute ("userListBean"); Iterator iter = userList.iterator(); while (iter.hasNext()) { UserData user = (UserData)iter.next(); if (user.getIdUsuario() == Integer.parseInt(idUsuario)) { session.setAttribute("editUserBean", user); break; } } UserData user = (UserData)session.getAttribute("editUserBean"); if (user == null) { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.user.notFound")); } } catch (Exception e) { errors.add( ActionErrors.GLOBAL_ERROR,

new ActionError("error.get.user")); getServlet().log("Erro carregando o Usurio", e);

} } Agora devemos alterar o arquivo struts-config.xml, ou seja acrescentar um action-mapping. Para isto basta adicionar o trecho de cdigo abaixo na seo <action-mappings> <action path="/editUser" scope="session" type="strutsdemo.action.EditUserAction" unknown="false" validate="false"> <forward name="success" path="/pages/editUser.jsp" redirect="false" contextRelative="false" /> </action> Por fim vamos ver como fica o cdigo JSP para alterar o usurio(editUser.jsp). Vale lembrar que o cdigo JSP abaixo ainda no pode ser executado, pois depende de um Action que ainda no foi implementado. <%@ taglib uri="/tags/struts-logic" prefix="logic" %> <%@ taglib uri="/tags/struts-bean" prefix="bean"%> <%@ taglib uri="/tags/struts-html" prefix="html"%> <html:html locale="true"> <head> <title><bean:message key="editUser.title"/></title> </head> <body> <font face="Comic Sans MS" size="3"> <center> <h3><font color="blue"><bean:message key="editUser.title"/></font></h3> <html:form action="/saveEditUser.do" method="post" focus="login"> <html:hidden property="idUsuario" name="editUserBean"/> <table width="80%" border="0"> <tr> <td width="30%"></td> <td width="70%"> <%-- exibe os erros de validao --%> <logic:messagesPresent> <ul> <html:messages id="error"> <li><bean:write name="error"/></li> </html:messages> </ul> </logic:messagesPresent> </td> <tr> <tr> <td align="right"><bean:message key="prompt.idUsuario"/>: </td> <td align="left"><b><bean:write property="idUsuario" name="editUserBean"/></b></td> </tr> <tr> <td align="right"><bean:message

if (!errors.isEmpty()) { saveErrors(request, errors); return (mapping.findForward("failure")); } else { return (mapping.findForward("success")); }

key="prompt.login"/>: </td>

<td align="left"><html:text property="login" name="editUserBean" size="20"/></td> </tr> <tr> <td align="right"><bean:message key="prompt.nome"/></td> <td align="left"><html:text property="nome" name="editUserBean" size="60"/></td> </tr> <td align="right"><bean:message key="prompt.senhaAntiga"/>: </td> <td align="left"><html:password property="senhaAntiga" size="16" maxlength="20" redisplay="false" value="zzzzz"/></td> </tr> <tr> <td align="right"><bean:message key="prompt.novaSenha"/>: </td> <td align="left"><html:password property="novaSenha" size="16" maxlength="20" redisplay="false" value="zzzzz"/></td> </tr> <tr> <td align="right"><bean:message key="prompt.confirmacaoNovaSenha"/>: </td> <td align="left"><html:password property="confirmacaoNovaSenha" size="16" maxlength="20" redisplay="false" value="zzzzz"/></td> </tr> <tr> <td align="right"><bean:message key="prompt.faixaIdade"/>: </td> <td align="left"> <html:select property="faixaIdade" name="editUserBean"> <html:option value="1"><bean:message key="prompt.ate20"/></html:option></html:option> <html:option value="2"><bean:message key="prompt.de21a30"/></html:option></html:option> <html:option value="3"><bean:message key="prompt.de31a40"/></html:option></html:option> <html:option value="4"><bean:message key="prompt.de41a50"/></html:option></html:option> <html:option value="5"><bean:message key="prompt.de51a60"/></html:option></html:option> <html:option value="6"><bean:message key="prompt.acima60"/></html:option></html:option> </html:select> </td> </tr> <tr> <td align="right"><bean:message key="prompt.sexo"/>: </td> <td align="left"> <html:radio property="sexo" value="M" name="editUserBean"> <bean:message key="prompt.Masculino"/> </html:radio> <html:radio property="sexo" value="F" name="editUserBean"> <bean:message key="prompt.Feminino"/> </html:radio> </td> <tr>

</tr> <tr> <td align="right"><bean:message key="prompt.ativo"/>: </td> <td align="left"> <html:checkbox property="ativo" name="editUserBean" titleKey="prompt.ativo"/> </td> </tr> <tr> <td colspan="2" align="center"> <html:submit><bean:message key="button.send"/></html:submit> <html:reset><bean:message key="button.reset"/></html:reset> </td> </tr> </table> </html:form> <br/> <html:link page="/listUsers.do">voltar</html:link> </center> </font> </body> </html:html>

Forms
Uma das tarefas mais trabalhosas no desenvolvimento de uma aplicao a interao com formulrios, para se alterar e obter nova informao. As validaes, o tratamento de erros, a apresentao, e o mesmo a entrada de dados do form pelo usurio e mensagens de erros, so contempladas pela Struts, o que torna a vida um pouco mais fcil. Todo trabalho de validao e gerao de mensagens de erros sero implementados nos ActionForm e todo o trabalho de gerao de interface no JSP. Basicamente o ActionForm ser um espelho dos inputs que vem do html do browser, ou seja, dever conter todos os campos (variaveis privadas com os devidos metodos gets e sets), coincidindo com o nome dos inputs do formulrio html. Toda validao de dados pela Struts passa por um FormBean. O FormBean a primeira classe (quando definida no action-mapping) a ser chamada atravs do mtodo validate (Detalhes na Figura 2). No entanto, nem toda solicitao que vem da web necessita de validao de dados. Assim s ser necessrio usar um FormBean quando necessitarmos de validao dos dados. No nosso caso, quando precisarmos salvar os dados que foram alterados pelo usurio. No entanto, antes de devemos fazer uma validao para que no v besteira para o banco de dados. Um ActionForm possui dois mtodos importantes. So eles reset e validate. Veja abaixo a implementao do nosso ActionForm que faz as validaes mnimas necessrias. package strutsdemo.form; import javax.servlet.http.HttpServletRequest; import import import import org.apache.struts.action.ActionError; org.apache.struts.action.ActionErrors; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionMapping;

public class SaveEditUserForm extends ActionForm { private private private private private private private private private String String String String String String String String String idUsuario; login; nome; ativo; faixaIdade; sexo; senhaAntiga; novaSenha; confirmacaoNovaSenha;

public void reset(ActionMapping mapping, HttpServletRequest request) { idUsuario = "-1"; login = ""; nome = ""; ativo = "false"; faixaIdade = "1"; sexo = "M"; senhaAntiga = ""; novaSenha = ""; confirmacaoNovaSenha = ""; } public ActionErrors validate( ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if ((idUsuario == null) || (idUsuario.length() < 1)) { errors.add("idUsuario", new ActionError ("error.idUsuario.required")); } if ((login == null) || (login.length() < 1)) { errors.add("login", new ActionError("error.login.required")); } if ((nome == null) || (nome.length() < 1)) { errors.add("nome", new ActionError("error.nome.required")); } if ((novaSenha == null) || (novaSenha.length() < 1)) { errors.add("nome", new ActionError("error.novaSenha.required")); } if ((confirmacaoNovaSenha == null) || (confirmacaoNovaSenha.length() < 1)) { errors.add("confirmacaoNovaSenha", new ActionError ("error.confirmacaoNovaSenha.required")); } if ((senhaAntiga == null) || (senhaAntiga.length() < 1)) { errors.add("senhaAntiga", new ActionError ("error.senhaAntiga.required")); } if (errors.isEmpty()) { if (!novaSenha.equals(confirmacaoNovaSenha)) { errors.add("senhaAntiga", new ActionError ("error.ConfirmacaoSenha")); } } return errors; } public String getNovaSenha() { return novaSenha; } public void setNovaSenha(String novaSenha) { this.novaSenha = novaSenha; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getAtivo() { return ativo; } public void setAtivo(String ativo) { this.ativo = ativo; } public String getLogin() { return login;

} Quando terminar a execuo do mtodo validate, se ocorrer algum erro, ser adicionado em um Collection de erros. Se este collection tiver algum erro, o FormBean devolve para o jsp que entrou com os dados, com os campos devidamente preenchidos, e com as mensagens dos erros ocorridos. Caso contrrio, ou seja, se no ocorrer nenhum erro, ento o fluxo segue para um ActionBean para invocar a camada de negcio para gravar estes dados no banco de dados. Logo, precisamos criar este bean. Segue abaixo o cdigo do nosso ActionBean. package strutsdemo.action; import java.sql.SQLException; import import import import import import import import import import import javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; javax.servlet.http.HttpSession; javax.sql.DataSource; org.apache.commons.beanutils.BeanUtils; org.apache.struts.action.Action; org.apache.struts.action.ActionError; org.apache.struts.action.ActionErrors; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionForward; org.apache.struts.action.ActionMapping;

} public void setLogin(String login) { this.login = login; } public String getSenhaAntiga() { return senhaAntiga; } public void setSenhaAntiga(String senhaAntiga) { this.senhaAntiga = senhaAntiga; } public String getSexo() { return sexo; } public void setSexo(String sexo) { this.sexo = sexo; } public String getConfirmacaoNovaSenha() { return confirmacaoNovaSenha; } public void setConfirmacaoNovaSenha(String confirmacaoNovaSenha) { this.confirmacaoNovaSenha = confirmacaoNovaSenha; } public String getFaixaIdade() { return faixaIdade; } public void setFaixaIdade(String faixaIdade) { this.faixaIdade = faixaIdade; } public String getIdUsuario() { return idUsuario; } public void setIdUsuario(String idUsuario) { this.idUsuario = idUsuario; }

import strutsdemo.bean.AdminUsers; import strutsdemo.bean.UserData; import strutsdemo.form.SaveEditUserForm; public class SaveEditUserAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request,

HttpServletResponse response) throws Exception { ActionErrors errors = new ActionErrors(); try { HttpSession session = request.getSession(); SaveEditUserForm editUserForm = (SaveEditUserForm)form; UserData user = (UserData)session.getAttribute("editUserBean"); if (!editUserForm.getSenhaAntiga().equals("zzzzz")) { if (!user.getSenha().equals(editUserForm.getSenhaAntiga())) { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.senhaAntiga")); } else { user.setSenha(editUserForm.getNovaSenha()); } } if (errors.isEmpty()) { BeanUtils.copyProperties(user, editUserForm); DataSource dataSource = getDataSource(request); AdminUsers adminUsers = new AdminUsers(); adminUsers.updateUser(user); } } catch (SQLException e) { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.update.user")); getServlet().log("Erro alterando o Usurio", e); } if (!errors.isEmpty()) { saveErrors(request, errors); return (mapping.findForward("failure")); } else { return (mapping.findForward("success")); }

} Agora, que fizemos o FormBean e o ActionBean, devemos fazer o action-mapping associando estes beans. Segue abaixo as alteraes necessrias no struts-config.xml. <form-beans> <form-bean dynamic="false" name="saveEditUserForm" type="strutsdemo.form.SaveEditUserForm"> </form-beans> ... <action-mappings> ... <action attribute="saveEditUserForm" input="/pages/editUser.jsp" name="saveEditUserForm" path="/saveEditUser" scope="session" type="strutsdemo.action.SaveEditUserAction" unknown="false" validate="true"> <forward name="success" path="/pages/listUsers.jsp" redirect="false" contextRelative="false" /> </action>

... </action-mappings> Obs: At a verso 1.0 da Struts, a nica maneira de validar os dados era herdando do ActionForm, e colocando as regras de validao no mtodo validate. No entanto com a Struts 1.1 possvel fazer a validao atravs de um Form Dinmico, mais adiante veremos como definir um Form dinmico. Outra novidade na Struts 1.1 o suporte para validao do lado client atravs de uma biblioteca de javascript definidos no arquivo validator.xml. Assim, podemos evitar o overread gerado pelas solicitaes desnecessrias no servidor, pois quando a solicitao chega ao web server, estaremos tratando com os dados previamente tratados pelo javascript do lado client. S pra constar como lembrete para os novatos em internet. Pode parecer tentador, mas nunca deixe de validar os dados no lado servidor se tiver tudo tratado no lado client, pois o usurio pode desabilitar o javascript do browser e causar erros imprevisveis na sua aplicao. Concluso: Use javascript para validar se puder, e sempre use validao do lado servidor.

Validando dados via javascript


Para fazer a validao com a struts no client via javascript devemos acrescentar os criterios no arquivo no arquivo validation.xml. Adicionar o trecho de cdigo abaixo na seo <formset>. <formset> <form name="saveEditUserForm"> <field property="idUsuario" depends="required"> <arg0 key="prompt.idUsuario"/> </field> <field property="login" depends="required"> <arg0 key="prompt.login"/> </field> <field property="nome" depends="required"> <arg0 key="prompt.nome"/> </field> <field property="novaSenha" depends="required,mask"> <arg0 key="prompt.novaSenha"/> <var> <var-name>mask</var-name> <var-value>^[0-9a-zA-Z]*$</var-value> </var> </field> <field property="senhaAntiga" depends="required,mask"> <arg0 key="prompt.senhaAntiga"/> <var> <var-name>mask</var-name> <var-value>^[0-9a-zA-Z]*$</var-value> </var> </field> <field property="confirmacaoNovaSenha" depends="required,mask"> <arg0 key="prompt.confirmacaoNovaSenha"/> <var> <var-name>mask</var-name> <var-value>^[0-9a-zA-Z]*$</var-value> </var> </field> </form> </formset> Tambm precisaremos "traduzir" algumas mensagens que j vieram no arquivo application.properties da template struts-blank.war, pois sero usados no javascript. # Mensagens de erro padro para as validaes errors.required={0} um campo obrigatrio. errors.minlength={0} No pode ser menor que {1} caracteres. errors.maxlength={0} No pode ser maior que {2} caracteres. errors.invalid={0} est invlido. errors.byte={0} deve ser um byte. errors.short={0} deve ser um inteiro curto. errors.integer={0} deve ser um inteiro. errors.long={0} deve ser um inteiro longo. errors.float={0} deve ser um ponto flutuante de preciso simples. errors.double={0} deve ser um ponto flutuante de preciso dupla.

errors.date={0} no uma data. errors.range={0} no est na faixa entre {1} e {2}. errors.creditcard={0} no um nmero de carto de crdito vlido. errors.email={0} no um e-mail vlido. Neste ponto temos a aplicao Listando e alterando o cadastro de usurios. No entanto, precisamos ainda fazer a Incluso e a Excluso de Usurios. Ento vamos l ...

Forms Dinmicos
Uma das grandes melhorias do Struts 1.1 em relao 1.0 (pode haver controvrsias, mas ...) foi a introduo dos DynamicForms. Assim voc no mais "obrigado" a criar um Form para validar as entradas de cada formulrio HTML. O Dynamic Form configurado apenas no struts-config.xml e a Struts j tem uma classe "prontinha para fazer as validaes para voc. Veja o trecho abaixo do codigo para um Form Dinmico: <form-bean dynamic="true" name="saveInsertUserForm" type="org.apache.struts.validator.DynaValidatorForm"> <form-property name="idUsuario" type="java.lang.String" /> <form-property name="login" type="java.lang.String" /> <form-property name="nome" type="java.lang.String" /> <form-property name="faixaIdade" type="java.lang.String" /> <form-property name="sexo" type="java.lang.String" /> <form-property name="ativo" type="java.lang.String" /> <form-property name="senha" type="java.lang.String" /> <form-property name="confirmacaoSenha" type="java.lang.String" /> </form-bean>

Terminando o projeto
Neste ponto o nosso projeto est praticamente finalizado. A partir de agora vamos repetir alguns passos que j foram feitos antes. ou seja, se voc chegou at aqui, s falta um pouco de pratica para voc se tornar um expert nesta framework. Segue abaixo os codigos que ainda faltam: cadastro/pages/Welcome.jsp <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@ taglib uri="/tags/struts-html" prefix="html" %> <%@ taglib uri="/tags/struts-logic" prefix="logic" %> <html:html locale="true"> <head> <title><bean:message key="welcome.title"/></title> <html:base/> </head> <body bgcolor="white"> <font face="Comic Sans MS" size="3"> <center> <h1><font color="blue"><bean:message key="welcome.title"/></font></h1> <logic:notPresent name="org.apache.struts.action.MESSAGE" scope="application"> <font color="red"> ERROR: Application resources not loaded -- check servlet container logs for error messages. </font> </logic:notPresent> <h3><bean:message key="welcome.heading"/></h3> <p><bean:message key="welcome.message"/></p> <html:link page="/listUsers.do">Cadastro de Usurios</html:link> </center> <p><font color="darkblue"> Autor: <html:link href="mailto:wbsouza@yahoo.com.br">Welington B.Souza</html:link> <br>01/07/2003 </font></p> </p> </font>

</body> </html:html> cadastro/pages/error.jsp <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@ taglib uri="/tags/struts-html" prefix="html" %> <%@ taglib uri="/tags/struts-logic" prefix="logic" %> <html:html locale="true"> <head> <title><bean:message key="error.title"/></title> <html:base/> </head> <body bgcolor="white"> <font face="Comic Sans MS" size="3"> <center> <blockquote> <h1><font color=red><bean:message key="error.title"/></font></h1> <logic:messagesPresent> <ul> <html:messages id="error"> <li><bean:write name="error"/></li> </html:messages> </ul> </logic:messagesPresent> </blockquote> <br/> <html:link page="/Welcome.do">Pgina Inicial</html:link> </center> </body> </html:html> package strutsdemo.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import import import import org.apache.struts.action.Action; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionForward; org.apache.struts.action.ActionMapping;

import strutsdemo.bean.UserData; public class InsertUserAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { HttpSession session = request.getSession(); UserData user = new UserData(); session.setAttribute("insertUserBean", user); return (mapping.findForward("success")); }

cadastro/pages/insertUser.jsp <%@ taglib uri="/tags/struts-logic" prefix="logic" %> <%@ taglib uri="/tags/struts-bean" prefix="bean"%> <%@ taglib uri="/tags/struts-html" prefix="html"%> <html:html locale="true"> <head> <title><bean:message key="insertUser.title"/></title> </head> <body> <font face="Comic Sans MS" size="3">

<center> <h3><font color="blue"><bean:message key="insertUser.title"/></font></h3> <html:form action="/saveInsertUser.do" method="post" onsubmit="return validateSaveInsertUserForm(this);" focus="idUsuario"> <table width="80%" border="0"> <tr> <td width="30%"></td> <td width="70%"> <%-- exibe os erros de validao --%> <logic:messagesPresent> <ul> <html:messages id="error"> <li><bean:write name="error"/></li> </html:messages> </ul> </logic:messagesPresent> </td> <tr> <tr> <td align="right"><bean:message key="prompt.idUsuario" name="insertUserBean"/>: </td> <logic:equal name="insertUserBean" property="idUsuario" value="0"> <td align="left"><html:text property="idUsuario" size="5" value=""/></td> </logic:equal> <logic:notEqual name="insertUserBean" property="idUsuario" value="0"> <td align="left"><html:text property="idUsuario" size="5" name="insertUserBean"/></td> </logic:notEqual> </tr> <tr> <td align="right"><bean:message key="prompt.login"/>: </td> <td align="left"><html:text property="login" size="20" name="insertUserBean"/></td> </tr> <tr> <td align="right"><bean:message key="prompt.nome"/></td> <td align="left"><html:text property="nome" size="60" name="insertUserBean"/></td> </tr> <tr> <td align="right"><bean:message key="prompt.senha"/>: </td> <td align="left"> <html:password property="senha" size="16" maxlength="20" redisplay="false"/> </td> </tr> <tr> <td align="right"><bean:message key="prompt.confirmacaoSenha"/>: </td> <td align="left"> <html:password property="confirmacaoSenha" size="16" maxlength="20" redisplay="false"/> </td> </tr> <tr> <td align="right"><bean:message key="prompt.faixaIdade"/>: </td> <td align="left"> <html:select property="faixaIdade" name="insertUserBean"> <html:option value="1"><bean:message

key="prompt.ate20"/></html:option></html:option> <html:option value="2"><bean:message key="prompt.de21a30"/></html:option></html:option> <html:option value="3"><bean:message key="prompt.de31a40"/></html:option></html:option> <html:option value="4"><bean:message key="prompt.de41a50"/></html:option></html:option> <html:option value="5"><bean:message key="prompt.de51a60"/></html:option></html:option> <html:option value="6"><bean:message key="prompt.acima60"/></html:option></html:option> </html:select> </td> </tr> <tr> <td align="right"><bean:message key="prompt.sexo"/>: </td> <td align="left"> <html:radio property="sexo" value="M" name="insertUserBean"> <bean:message key="prompt.Masculino"/> </html:radio> <html:radio property="sexo" value="F" name="insertUserBean"> <bean:message key="prompt.Feminino"/> </html:radio> </td> </tr> <tr> <td align="right"><bean:message key="prompt.ativo"/>: </td> <td align="left"> <html:checkbox property="ativo" titleKey="prompt.ativo" name="insertUserBean" /> </td> </tr> <tr> <td colspan="2" align="center"> <html:submit><bean:message key="button.send"/></html:submit> <html:reset><bean:message key="button.reset"/></html:reset> </td> </tr> </table> </html:form> <br/> <html:link page="/listUsers.do">voltar</html:link> </center> </font> </body> <html:javascript formName="saveInsertUserForm"/> </html:html> package strutsdemo.action; import java.sql.SQLException; import java.util.LinkedList; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import import import import import import org.apache.struts.action.Action; org.apache.struts.action.ActionError; org.apache.struts.action.ActionErrors; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionForward; org.apache.struts.action.ActionMapping;

import org.apache.struts.validator.DynaValidatorForm; import strutsdemo.bean.AdminUsers; import strutsdemo.bean.UserData; public class SaveInsertUserAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { DynaValidatorForm dynaForm = (DynaValidatorForm) form; ActionErrors errors = new ActionErrors(); String senha1 = (String)dynaForm.get("senha"); String senha2 = (String)dynaForm.get("confirmacaoSenha"); // como utilizamos um DynamicForm, precisamos terminar a validao aqui. if (senha1.equals(senha2)) { try { HttpSession session = request.getSession(); // popula o bean do usuario com os dados que vieram do Form UserData user = (UserData) session.getAttribute ("insertUserBean"); user.setIdUsuario(Integer.parseInt((String)dynaForm.get ("idUsuario"))); user.setLogin((String)dynaForm.get("login")); user.setNome((String)dynaForm.get("nome")); user.setFaixaIdade(Integer.parseInt((String)dynaForm.get ("faixaIdade"))); user.setSexo((String)dynaForm.get("sexo")); user.setNome((String)dynaForm.get("nome")); user.setSenha(senha1); boolean ativo = ((String)dynaForm.get("ativo")).equals("on"); user.setAtivo(ativo); AdminUsers adminUsers = new AdminUsers(); adminUsers.insertUser(user); LinkedList userList = (LinkedList) session.getAttribute ("userListBean"); userList.add(user); session.removeAttribute("insertUserBean"); } catch (SQLException e) { if (e.getErrorCode() == 1062) { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.idUsuario.duplicateKey")); } else { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.insert.user")); } } } else { errors.add( ActionErrors.GLOBAL_ERROR, new ActionError("error.ConfirmacaoSenha")); }

if (!errors.isEmpty()) {

} else { return (mapping.findForward("success")); }

saveErrors(request, errors); return (mapping.findForward("error"));

package strutsdemo.action; import java.util.Iterator; import java.util.LinkedList; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import import import import import import org.apache.struts.action.Action; org.apache.struts.action.ActionError; org.apache.struts.action.ActionErrors; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionForward; org.apache.struts.action.ActionMapping;

import strutsdemo.bean.AdminUsers; import strutsdemo.bean.UserData; public class DeleteUserAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { HttpSession session = request.getSession(); String idUsuario = request.getParameter("idUsuario"); ActionErrors errors = new ActionErrors(); try { LinkedList userList = (LinkedList)session.getAttribute ("userListBean"); Iterator iter = userList.iterator(); while (iter.hasNext()) { UserData user = (UserData)iter.next(); if (user.getIdUsuario() == Integer.parseInt(idUsuario)) { AdminUsers adminUsers = new AdminUsers(); adminUsers.deleteUser(Integer.parseInt(idUsuario)); userList.remove(user); break; } } } catch (Exception e) { errors.add(ActionErrors.GLOBAL_ERROR, new ActionError ("error.delete.user")); getServlet().log("Erro carregando a lista de usurios", e); } if (!errors.isEmpty()) { saveErrors(request, errors); return (mapping.findForward("failure")); } else { return (mapping.findForward("success")); }

Outras fontes de pesquisa


Struttin' With Struts - Lessons Stepping through Jakarta Struts About Struts i18n with Struts Introduction to Jakarta Struts Framework Learn Struts' Form-Related Tags TheServerSide.com J2EE Community Project Refinery, Inc Create Better Web Apps with Struts Struts Tutorial Overview

Ferramentas para a Struts


Atualmente existem diversas ferramentas para configurao da Struts de forma visual com diversas opes entre produtos pagos e open source (EasyStruts, Struts Console). No entanto, recomendvel familiarizar-se primeiro com a configurao manual antes de utilizar estas ferramentas, pois caso ocorra algum problema imprevisto, possa ser corrigido manualmente. Voc pode encontrar mais detalhes em buscas no SourceForge.net, tem um monte de coisas legais l.

Integrao com outras bibliotecas


Assim como existe a Struts, existem tambm outras bibliotecas para algumas funcionalidades especficas (custom tags, templates, etc). Assim possvel fazer uma srie de combinaes no sentido de conseguir o efeito desejado na sua aplicao web. Veja algumas bibliotecas que podem ser integradas Struts. Struts-Layout Struts Menu Velocity JavaServer Faces Novamente faa buscas no site SourceForge.net Boa sorte nos seus projetos com a Struts Framework ! Clique aqui e baixe os fontes deste tutorial.

Você também pode gostar