Atualizando minhas antigas vídeo-aulas de Struts2

Há muitos anos, antes de começar a escrever artigos para a Java Magazine, eu gravava vídeo-aulas que eram publicadas no portal da DevMedia, editora da revista. Comecei gravando um mini-curso sobre Desenvolvimento de aplicações Java Web no Eclipse e esta acabou sendo mesmo minha única contribuição em vídeo para o portal.

Até hoje recebo alguns comentários e dúvidas sobre os vídeos deste mini-curso. O grande problema é que tanto o Eclipse, IDE utilizada durante o mini-curso, quanto o Struts2, framework Web utilizado, mudaram bastante com novas versões desde o tempo que gravei as aulas. Muitas vezes, os problemas que as pessoas que assistem as vídeo-aulas e tentam repeti-la em seus computadores enfrentam são devidos a esta diferença de versões: quando eu gravei a aula as coisas eram feitas de uma forma, hoje não são mais.

Dado um comentário recente do leitor Flávio, resolvi escrever um post com uma atualização das instruções para a versão atual do Eclipse (Helios) e do Struts2 (2.2.1.1). Mais especificamente, vou focar no conteúdo da parte 4 do mini-curso, que é a “instalação” do Struts2.

Assumindo que o Eclipse Helios encontra-se instalado e integrado com algum servidor Web Java (ex.: Tomcat), obtenha a versão 2.2.1.1 do Struts em http://struts.apache.org/downloads.html e descompacte o arquivo obtido em alguma pasta em seu computador. Um diretório com o mesmo nome do arquivo (porém sem a extensão .zip) será criado e chamaremos este diretório de $STRUTS_HOME. Por exemplo, no meu computador, $STRUTS_HOME equivale a /home/vitor/Workspaces/libraries/struts-2.2.1.1, pois o arquivo struts-2.2.1.1-all.zip obtido no site do Struts foi descompactado no diretório /home/vitor/Workspaces/libraries/.

Abra o Eclipse na perspectiva Java EE (se já não estiver aberta, clique em Window > Open Perspective… > Other) e crie um novo projeto Web: clique em File > New > Other… e escolha Dynamic Web Project dentro da categoria Web e clique Next. Preencha o nome do projeto com StrutsApp, assegure-se de ter escolhido o servidor Web em Target runtime e clique Next duas vezes. Na última tela do assistente, marque a opção Generate web.xml deployment descriptor e clique em Finish.

O Eclipse irá criar um novo projeto Web chamado StrutsApp. Para testar se tudo correu bem até aqui, abra o projeto StrutsApp, clique com o botão direito do mouse na pasta WebContent e escolha New > JSP File. Dê a ele o nome de index.jsp e clique em Finish. Preencha-o com o seguinte conteúdo:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Test</title>
</head>
<body>

<h1>JSP Test</h1>

<p><%= new java.util.Date() %></p>

</body>
</html>

Em seguida, clique com o botão direito em StrutsApp e escolha Run As > Run on Server. O Eclipse deve iniciar seu servidor Web, em seguida seu navegador e a página que acabamos de criar deverá aparecer, mostrando a data atual abaixo do título JSP Test. Recarregue a página para ver que a data é atualizada a cada execução.

Estando tudo certo até aqui, é hora de “instalar” o Struts2 em nossa aplicação Web. Faremos isso analisando uma das aplicações de exemplo: $STRUTS_HOME/apps/struts2-blank.war (aplicação em branco Struts2). Como qualquer aplicação Web empacotada em um arquivo WAR, o arquivo struts2-blank.war pode ser descompactado como um arquivo ZIP normal. Em seguida, analisaremos sua estrutura interna e faremos de modo equivalente em nossa aplicação.

Em primeiro lugar, examine o diretório WEB_INF/lib da aplicação em branco para saber quais são os JARs necessários para utilizar o Struts2. Na versão 2.2.1.1, são os seguintes:

  • commons-fileupload-1.2.1.jar;
  • commons-io-1.3.2.jar;
  • freemarker-2.3.16.jar;
  • javassist-3.7.ga.jar;
  • ognl-3.0.jar;
  • struts2-core-2.2.1.1.jar;
  • xwork-core-2.2.1.1.jar.

Para adicionar estes JARs à aplicação Web no Eclipse utilizaremos a configuração de implantação da IDE. Clique com o botão direito em seu projeto e escolha New > Folder para criar uma pasta lib na raiz do projeto. Após isso, copie os JARs listados acima para esta pasta (se efetuar a cópia por fora do Eclipse, lembre-se de dar um Refresh no seu projeto). Em seguida, clique novamente com o botão direito no projeto e escolha Properties. Abra o item Deployment Assembly e clique em Add…. Escolha a opção Folder e clique em Next. Selecione a pasta lib e clique em Finish. O Eclipse irá mapear a pasta lib para a raiz — / — da sua aplicação Web. Clique no mapeamento e altere de / para /WEB-INF/lib.

Em seguida, precisamos declarar o filtro do Struts2 em nossa aplicação Web. Faremos isso baseado na configuração da aplicação em branco: WEB_INF/web.xml. Basta copiar a definição do filtro e seu mapeamento para o nosso web.xml. No Eclipse, abra com um duplo-clique o item Deployment Descriptor: StrutsApp que encontra-se na raiz do projeto e adicione a configuração do filtro do Struts2, ficando assim:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
   
    <display-name>StrutsApp</display-name>
   
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
   
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Com o Struts2 configurado, podemos fazer uma ação de exemplo para testar seu funcionamento. Crie a classe strutsapp.HelloAction estendendo a classe com.opensymphony.xwork2.ActionSupport provida pelo framework. Esta classe deve ter dois atributos — uma mensagem e o nome do usuário — com seus respectivos métodos get/set, além de um método de ação (execute()), que será chamado por um formulário que escreveremos na página Web. Veja abaixo o seu código-fonte:

package strutsapp;

import com.opensymphony.xwork2.ActionSupport;

public class HelloAction extends ActionSupport {
    private String mensagem;
    private String nome;
   
    public String getMensagem() {
        return mensagem;
    }
    public void setMensagem(String mensagem) {
        this.mensagem = mensagem;
    }
    public String getNome() {
        return nome;
    }
    public void setNome(String nome) {
        this.nome = nome;
    }
   
    @Override
    public String execute() throws Exception {
        if ((nome != null) && (nome.length() > 0))
            mensagem = "Olá, " + nome + "!";
        else
            mensagem = "Olá, estranho!";
       
        return SUCCESS;
    }
}

Nossa classe de ação irá verificar no método execute() se o nome do usuário foi fornecido. Em caso positivo, irá construir uma mensagem utilizando este nome. Caso contrário, a mensagem será “Olá, estranho!”. O próximo passo é configurar esta classe de ação para responder em um determinado endereço de sua aplicação, assim o formulário Web que construiremos em seguida saberá como chamá-la. Esta configuração é feita no arquivo struts.xml, que deve ser colocado junto do código-fonte da aplicação (classes Java), porém na raiz do classpath.

Abra, então, o projeto StrutsApp, clique em File > New > Other, na categoria XML, escolha XML File e clique Next. Selecione StrutsApp/src como parent folder e dê ao arquivo o nome struts.xml, clicando em seguida em Finish. Com base no arquivo WEB-INF/src/java/struts.xml que encontra-se na aplicação em branco do Struts2, configure a classe de ação HelloAction da seguinte forma:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <package name="default" namespace="/" extends="struts-default">
        <action name="hello" class="strutsapp.HelloAction">
            <result>/hello.jsp</result>
        </action>
    </package>
</struts>

A configuração acima declara um pacote de ações chamado default associado à raiz da aplicação Web, o que faz com o que o Struts2 procure neste pacote por qualquer ação evocada pelo cliente. Nosso pacote possui apenas uma ação, chamada hello, implementada pela classe que criamos anteriormente e que, como resultado, abre a página /hello.jsp. Para finalizar nosso exemplo, é preciso adicionar à página index.jsp que já criamos um formulário que execute a ação hello e a página hello.jsp que será exibida como resultado. Seguem os códigos-fonte destas duas páginas abaixo:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Strust2 Test</title>
</head>
<body>

<h1>Struts2 Test</h1>

<s:form action="hello" namespace="/">
    <s:textfield name="nome" size="15" label="Digite seu nome" />
    <s:submit value="OK" />
</s:form>

</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Strust2 Test</title>
</head>
<body>

<h1>Struts2 Test</h1>

<p><s:property value="mensagem" /></p>

</body>
</html>

E assim completamos nossa ação de exemplo. Ao executar a aplicação no servidor Web, a página index.jsp será apresentada com o formulário pedindo ao usuário seu nome. Este formulário será formatado automaticamente com campos e botões alinhados como em uma tabela, graças às tags de formulário do Struts2.

Ao preenchermos o formulário e clicarmos em OK, a página chamará a ação hello, que foi definida no arquivo struts.xml como sendo implementada pela classe HelloAction. O Struts2, então, cria uma instância dessa classe e, primeiro, para cada campo do formulário, chama o método set apropriado. Como só temos um campo chamado nome, o Struts2 chamará o método setNome() passando como parâmetro o que foi preenchido naquele campo (o nome do usuário). Em seguida, o Struts2 chama o método execute().

O método é executado, criando a mensagem “Olá, <nome do usuário>!” e retornando a constante SUCCESS. Esta constante, que tem como valor a String "success", é utilizada pelo Struts2 para determinar qual resultado deve ser mostrado. Esta ação, no caso, só tem um resultado (que por padrão é mapeado para "success") que consiste em mostrar a página hello.jsp. Nesta página, existe uma tag <s:property /> que faz referência à propriedade mensagem. Isso faz com que o Struts2 chame o método getMensagem() no objeto que acabou de ser executado (ou seja, a instância de HelloAction que foi criada), mostrando o resultado deste método na página.

Enfim, se você preencher seu nome no campo e clicar em OK, o Struts2 fará todo este processo para mostrar, ao final, a mensagem “Olá, <seu nome>!”. Obviamente utilizar um framework como o Struts2 para fazer exemplos simples como este é um exagero. Os frameworks Web ajudam na separação do modelo (os dados, como por exemplo o nome do usuário), do controle (a classe de ação) e da visão (as páginas JSP) de forma a auxiliar na organização de aplicações mais complexas.

Espero com este post auxiliar na criação inicial da aplicação Web com Struts2 para que aqueles que assistem minhas antigas vídeo-aulas possam continuar e experimentar os exemplos seguintes. Como não tenho usado o Struts2 há muito tempo, eu não sei se mais alguma coisa do mini-curso precisará de adaptação para a versão mais recente do framework. Caso você encontre alguma coisa, me mande um e-mail e, assim, posso esclarecer alguma outra parte específica do mini-curso em outro post.

Sugiro, também, a leitura do artigo WebApps com Struts2, parte 1 e parte 2, publicados, respectivamente, nas edições 74 e 75 da Java Magazine. Nele, utilizei uma versão mais recente do framework comparada com a versão usada nas vídeo-aulas, e neste artigo apresentamos outras funcionalidades do Struts2 que não foram abordadas neste post.

Bons estudos!