Download "Aprenda a usar um framework MVC desenvolvendo o login de um sistema com o Webwork utilizando seus principais recursos."
1 Introdução ao Webwork Samuel Mota Aprenda a usar um framework MVC desenvolvendo o login de um sistema com o Webwork utilizando seus principais recursos. Introdução Objetivo O objetivo deste tutorial é apresentar o maior número de recursos existentes no Webwork de forma fácil ao implementar um login que valide o usuário e dê a ele acesso aos recursos do sistema. Para manter a simplicidade do tutorial não faremos a conexão com o banco de dados, apesar de ser uma tarefa básica e essencial para este sistema. É importante que à medida que for lendo o tutorial o leitor se atente aos termos utilizados e procure se aprofundar, principalmente nos patterns, pois saber o que está por trás do framework muitas vezes o ajudará a entender o porquê de muitas características. Banco de Dados Existem muitas abordagens possíveis para permitir o gerenciamento e uso de conexões, as mais documentadas utilizam o Hibernate ( como framework de mapeamento Objeto/Relacional. Uma abordagem muito interessante que utiliza interceptors (IoC) para esse gerenciamento está documentada no Wiki: Opensymphony O framework foi desenvolvido e é mantido com o apoio de diversas empresas que diretamente contribuem ao grupo denominado Opensymphony ( e que abriga diversos projetos open-source. Muitos desses projetos tem alguma relação com o Webwork, na maioria das vezes complementando suas funcionalidades para criar uma plataforma extremamente ágil de desenvolvimento de projetos. O webwork está intimamente ligado ao Xwork que é a base de suas funcionalidades, o Xwork é quem controla a execução em si de todas as ações do sistema por isso será muito citado no tutorial. Outro projeto que pode ser utilizado em conjunto e irá aumentar sua produtividade é o SiteMesh, não se esqueça ;-). Documentação O Webwork não tem uma documentação oficial bem estruturada. Sua principal fonte de consulta será o Wiki disponível em A melhor fonte de suporte ao Webwork é a lista oficial do desenvolvimento disponível no portal Java.net: Grupo de Usuários Java Página 1
2 Conceitos e Recursos Esta seção é para aqueles que queiram entender as opções que existem para utilizar diversos recursos do framework, se você quiser pode ir direto à seção Aplicação e voltar para ler esta seção depois. Xwork É uma implementação genérica do Command Pattern e é totalmente desacoplado do ambiente Web o que facilita o testes de suas ações. Ele provê ao processamento das ações uma poderosa linguagem de expressões conhecida como OGNL, um container de IoC, interceptadores, conversão de tipos e um framework de validação. Webwork É o framework MVC propriamente dito. É construído totalmente baseado no Xwork com um conjunto de interceptors, results e dispatchers e provê suporte a camada de visualização (View) possibilitando o uso de praticamente qualquer framework como JSP, Velocity, FreeMarker, etc. ActionSupport Na distribuição do framework existe a classe com.opensymphony.xwork.actionsupport que implementa diversas interfaces que são usadas pelo framework para prover a maioria dos serviços que desejamos como internacionalização, tratamento e validação de entrada e o comportamento padrão de uma action. Todas as nossas actions herdarão estes recursos dessa classe, é possível alterar o comportamento do framework e suas características não utilizando esta classe como superclasse, mas este não é nosso objetivo e muito provavelmente você também não precisará. Interceptors A maioria dos recursos existentes no Webwork foram codificados como Interceptors que gerenciam o processamento passo a passo da requisição e resposta. Depois de registrados os interceptors podem ser aplicados a ação conforme a necessidade de utilização de cada um. O framework têm a facilidade de configurarmos pilhas de interceptor e provê inclusive duas pilhas padrão com os serviços básicos que precisaremos. Validação O suporte a validação de entradas no Webwork pode ser feito através da implementação de validadores gerenciados pelo Xwork ou da implementação do método validate() na action. Pode-se utilizar os dois meios em conjunto criando um suporte de validação extremamente eficiente. Workflow Interceptor O método validate() não tem retorno nenhum (é void) e, assim como os validadores, não irá impedir a execução da action. Na validationworkflowstack existe um interceptor chamado workflow que é responsável por verificar se existe algum erro nos mapas de erro e se existir interrompe a execução da action retornando diretamente INPUT. Lembre-se disso quando não for utilizar a validationworkflowstack e quiser fazer validações. Existem diversos validadores implementados na distribuição e para desenvolver um que ainda não existe basta registra-lo no arquivo validators.xml e implementa-lo seguindo as instruções em O arquivo validators.xml deve ser encontrado na raiz do classpath (WEB-INF\classes). Grupo de Usuários Java Página 2
3 Para configurar a validação criamos arquivos xml com o conteúdo conforme explicado em Esses arquivos são processados seguindo a seguinte seqüência: Busca o arquivo com o NomeDaClasseDaAction-validation.xml e caso não encontre faz a mesma composição com o nome das super classes da action até que encontre java.lang.object; Busca o arquivo com o NomeDaClasseDaAction-NomeDaAction-validation.xml onde NomeDaAction é o alias da action e irá também fazer a mesma composição com as super classes. Internacionalização O webwork oferece ótimo suporte à internacionalização do sistema, isso permite que você crie arquivos, um para cada idioma que desejar suportar, contendo todas as mensagens que utilizará no sistema. Desde as mensagens de erro na validação, até os textos de conteúdo do seu sistema podem ser automaticamente localizados baseado no idioma do usuário. O webwork se baseia no Locale informado na requisição http, isso normalmente significa que o locale é o do sistema operacional, embora possa ser configurado pelo usuário. Os arquivos de localização utilizados pelo framework a cada processamento seguem o seguinte padrão: Busca a chave em um arquivo.properties com o nome da classe da action (ActionClass.properties) no mesmo endereço da classe (mesma package), se não encontra-la procura o mesmo padrão para as super classes da action até que encontre java.lang.object; Caso não tenha sucesso faz o mesmo processo anterior concatenando ao nome da classe o locale com um underscore. (ex: para usuário com locale pt_br procurará ActionClass_pt_BR.properties); Se ainda assim não encontrar buscará nos arquivos de recursos registrados como padrão. Ao iniciar o webwork registra os seguintes arquivos de recursos para recuperar as mensagens: com/opensymphony/webwork/webwork-messages e com/opensymphony/xwork/xwork-messages. Componentes O Xwork implementa IoC (Inversion Of Control) através da Injeção de Interface (Tipo 1), ou seja, para dizer que determinada action irá utilizar um componente basta que esta action implemente uma interface específica. Introdução ao IoC Leia o artigo no portal Java.net: A configuração dos componentes é feita no arquivo components.xml que deve estar na raiz do classpath (WEB-INF\classes). O tempo de vida dos componentes é definido pelo escopo que pode ser por requisição (request), sessão (session) ou aplicação (application), a definição desses escopos é análoga ao ciclo dentro da aplicação em um Webserver. IoC Interceptor O uso de componentes só é possível se o interceptor chamado component estiver aplicado à action, este interceptor não está em nenhuma pilha padrão de interceptors do framework. View O Webwork tem uma vasta biblioteca de tags que podemos utilizar em nossa camada de visualização. Grupo de Usuários Java Página 3
4 Basicamente essas tags trabalham utilizando todos os recursos do framework como internacionalização, tratamento de erros e entradas. Os templates das tags podem ser alterados ou sobrescritos, os que são utilizados por padrão estão no arquivo JAR do Webwork na package template. Parâmetros Lembre-se sempre que todos os parâmetros das tags são parseados pelo OGNL que busca executa as expressões, para não executa-las e ter o retorno exatamente com o conteúdo que escrever você dever colocar o texto entre '. Ex: 'textonãoprocessado' Aplicação Agora que conhecemos os principais conceitos relacionados ao framework vamos desenvolver nossa aplicação, passo a passo. Você também pode baixar o projeto (Eclipse) no link de recursos na página do tutorial. Instalação e Ambiente No mínimo você precisará de um servlet container, para este artigo estamos utilizando o Jakarta Tomcat (na verdade a versão não fará grande diferença), faça o download no site oficial e instale seguindo as instruções em Tomcat e Servlets Veja o tutorial de introdução ao Tomcat e Servlets no GUJ: /user.article.get.chain?page=1&article.id=9 Agora precisamos pegar o framework, faça o download do arquivo webwork-2.0.zip em e descompacte-o onde preferir. Crie um projeto em sua IDE preferida que seja uma aplicação no Tomcat, copie todos os arquivos com extensão jar que estão no subdiretório lib/core no diretório onde você descompactou o Webwork e também o arquivo webwork-2.0.jar e coloque-os no diretório WEB-INF\lib de sua aplicação. web.xml Para utilizarmos o framework precisamos configurar nossa aplicação no Tomcat para utiliza-lo. O código abaixo é o conteúdo total deste arquivo que deve estar no diretório WEB-INF da aplicação. <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" " <web-app> <display -name>webwork Application</display-name> <filter> <filter-name>container</filter-name> <filterclass>com.opensymphony.webwork.lifecycle.requestlifecyclefilter</filter-class> </filter> <filter-mapping> <filter-name>container</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> Grupo de Usuários Java Página 4
9 É importante notar que o objeto usersession será sempre setado com a chamada do método setusersession(usersession usr) que é feita pelo container IoC do framework e na sua configuração definimos que esse objeto tem o escopo da sessão do usuário, por isso nós o utilizaremos como nosso objeto que identifica o usuário e todas as suas propriedades. Login A classe de login é bastante simples e neste pondo deveríamos fazer o acesso ao banco de dados para validar, mas neste caso exigimos o usuário guj e a senha Alguns comentários adicionais: Criamos uma interface chamada DisableSecurityAction para que nosso interceptor (você verá mais para frente) de segurança não exija que o usuário esteja logado para executar esta ação, afinal esta ação é que irá cuidar do login; O model desta classe é o próprio User que vimos acima, isso significa que os campos na tela devem ter o mesmo nome das propriedades deste classe; Para utilizarmos o recurso de internacionalização as mensagens que adicionamos durante o processamento da action usam o método gettext(string chave); addactionerror adiciona um erro global a action enquanto addfielderror adiciona um erro diretamente ligado ao campo, a diferença de uso está na forma que você usa esses erros. No caso das tags do próprio framework os erros de campo são adicionados acima dele. package br.com.guj.actions; import org.apache.commons.logging.log; import org.apache.commons.logging.logfactory; import br.com.guj.models.user; import br.com.guj.system.disablesecurityaction; smota public class Login extends SystemAction implements DisableSecurityAction { private static final Log log = LogFactory.getLog(Login.class); private User model = new User(); public String execute() { // --> AQUI deveria validar de verdade o usuário if(!model.getusername().equals("guj")) { addactionerror(gettext("login.invalidcredentials")); addfielderror("username", gettext("login.unknowuser")); return ERROR; if(model.getpassword().intvalue()!=1234) { addactionerror(gettext("login.invalidcredentials")); addfielderror("password", gettext("login.wrongpassword")); return ERROR; //logou com sucesso? Põe o usuário na sessão. this.usersession.setuser(model); return SUCCESS; Grupo de Usuários Java Página 9
11 </html> </ww:i18n> login.properties Este arquivo mantém as mensagens específicas da action de login. # Mensagens da tela de login login.title=entrada do sistema login.saudacao=bem vindo a página de login login.username=nome do usuário login.password=senha login.enter=entrar login.invalidcredentials=dados de login incorretos! login.unknowuser=usuário não encontrado! login.wrongpassword=senha inválida para o usuário! invalid.fieldvalue.password=a senha deve ser numérica! A chave invalid.fieldvalue.fieldname (no exemplo nosso campo é o password) é uma definição padrão do framework e será procurada toda vez que houver um erro de conversão (no exemplo conversão para Integer), caso não exista a chave o Webwork utilizará uma mensagem padrão (em Inglês). login-validation.properties Neste arquivo definimos os validadores que utilizaremos na tela de login. <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0//EN" " s> <field name="username"> <field-validator type="requiredstring"> <message key="requiredfield">campo exigido!</message> </field-validator> </field> <field name="password"> <field-validator type="required"> <message key="requiredfield">campo exigido!</message> </field-validator> <field-validator type="int"> <param name="min">1000</param> <param name="max">9999</param> <message key="outofrangefield">bar must be between ${min and ${max, current value is ${password.</message> </field-validator> </field> </validators> Veja que utilizamos sempre uma chave para aproveitarmos os recursos de localização, caso a chave não exista será usada a mensagem deste arquivo. ApplicationSecurityInterceptor Aproveitando o recurso de interceptors criamos esta classe que tem como função não permitir a execução de ações sem uma sessão do usuário. Grupo de Usuários Java Página 11
13 UserSession Este é nosso componente armazenado na sessão do usuário. O framework é responsável por instancialo e passa-lo para todas as actions que implementem sua interface de marcação UserSessionAware. package br.com.guj.components; import java.io.serializable; import br.com.guj.models.user; smota * * Componente para manipulação da sessão do usuário. * /* * Não é um componente direto com o User para poder colocar * na seção mais objetos relacionados ao usuário. * public class UserSession implements Serializable { private User user; Returns the user. public User getuser() { return user; user The user to set. public void setuser(user user) { this.user = user; components.xml Este arquivo define os componentes, e suas configurações, do sistema. <?xml version="1.0" encoding="iso "?> <components> <component> <scope>session</scope> <class>br.com.guj.components.usersession</class> <enabler>br.com.guj.components.usersessionaware</enabler> </component> </components> xwork.xml Grupo de Usuários Java Página 13
15 </xwork> Conclusão É importante que o leitor esteja a vontade com todos os conceitos envolvidos em um framework MVC para tirar melor proveito do Webwork ou seja qual for o framework MVC que escolher usar. Este tutorial apresentou um exemplo com muitos recursos do framework, mas ele de maneira alguma está limitado a estes recursos e muitas vezes pode permitir o mesmo resultado com abordagens diferentes. O melhor agora é baixar o código do tutorial e explora-lo adicionando novos recursos à aplicação. Espero que este tutorial seja útil e as dúvidas surgidas em sua leitura poderão e deverão ser sanadas no fórum do GUJ. Samuel Mota é programador Java à 2 anos e atua como consultor de desenvolvimento e projeto em diversas empresas principalmente com plataformas Unix utilizando C e Java. Grupo de Usuários Java Página 15