Skip to content

8. Criação de um plugin

É possível criar aplicativos chamados plug-ins, que são carregados ao iniciar um aplicativo Struts e descarregados ao encerrá-lo. Isso permite, tradicionalmente, realizar inicializações ao iniciar o aplicativo e liberar recursos ao encerrá-lo. Essas operações também podem ser realizadas herdando-se da classe ActionServlet do controlador, e foi isso que foi feito na aplicação anterior. O plug-in é uma alternativa a essa solução. O plug-in pode ser uma aplicação mais complexa do que uma simples inicialização do ambiente. Vimos um exemplo disso na lição em que foram apresentados os conceitos de regras de validação declarativas. Um plugin é declarado no arquivo de configuração do Struts. O plugin ValidatorPlugIn foi declarado da seguinte forma no arquivo struts-config.xml do aplicativo que o utilizava:

    <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
        <set-property 
        property="pathnames" 
      value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"
    />
    </plug-in>

A seguir, descrevemos um aplicativo Struts que utiliza um plugin.

8.1. Configuração da aplicação Struts /plugin1

Propomos construir a aplicação Struts /plugin1 configurada da seguinte maneira:

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
    <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>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
      <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

  <taglib>
      <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
  </taglib>
  <taglib>
      <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
  </taglib>

</web-app>

Não vamos nos deter neste arquivo, que é padrão.

struts-config.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>

    <plug-in className="istia.st.struts.plugins.MyPlugin">
        <set-property property="passwdFileName" value="data/passwd"/>
        <set-property property="groupFileName" value="data/group"/>        
    </plug-in>

</struts-config>

Incluímos apenas uma seção, a do plugin. Os atributos da tag <plug-in> utilizados aqui são os seguintes:

className
nome da classe do plug-in
<set-property>
permite inicializar o plug-in com pares (chave, valor)

O objetivo desta aplicação é mostrar como o plug-in pode recuperar seus parâmetros de inicialização e disponibilizá-los para outros objetos que compartilham o mesmo contexto de aplicação. Utilizaremos uma vista simples, JSP, para exibir os valores de inicialização do plug-in, o que explica a ausência de qualquer ação no arquivo de configuração.

8.2. A classe Java do plugin

Uma classe Java que funciona como plugin para um aplicativo Struts deve implementar a interface org.apache.struts.action.PlugIn. Essa implementação consiste em escrever dois métodos:

  • public void init(ActionServlet servlet, ModuleConfig conf)
  • public void destroy()

Quando a aplicação Struts for carregada, seu controlador instanciará todos os plug-ins declarados no arquivo struts-config.xml. Em seguida, ele executará o método init de cada um deles. É nesse método que o plug-in realiza suas inicializações. Aqui, nos limitaremos a ler os parâmetros de inicialização do plug-in e colocá-los no contexto da aplicação, para que fiquem disponíveis para todos os outros objetos dela. Quando a aplicação for descarregada, o controlador executará o método destroy de cada um dos plug-ins carregados. Esse é o momento de liberar os recursos que se tornaram desnecessários. Aqui, não teremos nada a fazer.

O código da classe é o seguinte:

package istia.st.struts.plugins;

import javax.servlet.ServletException;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;
import org.apache.struts.config.PlugInConfig;

public class MyPlugin implements PlugIn {

    // método chamado ao excluir o contexto da aplicação
    public void destroy() {
    }

     // método chamado durante a criação inicial do contexto da aplicação
    public void init(ActionServlet servlet, ModuleConfig conf)
        throws ServletException {
         // nome da classe desse objeto
        String className=this.getClass().getName();
        // lista de plug-ins
        PlugInConfig[] pluginConfigs = conf.findPlugInConfigs();
         // análise dos plug-ins para localizar aquele
         // que tenha o nome dessa classe
        boolean trouvé=false;
        for (int i = 0; ! trouvé && i < pluginConfigs.length; i++) {
            // nome do plugin
            String pluginClassName=pluginConfigs[i].getClassName();
             // se não for o plugin correto, continuamos
            if(! pluginClassName.equals(className)) continue;
            // é o plugin correto — armazenamos suas propriedades no contexto
            servlet.getServletContext().setAttribute("initialisations",pluginConfigs[i].getProperties());
            trouvé=true;
        }//for i
    } //init
} //classe

Observe os seguintes pontos:

  • o método init recebe um parâmetro chamado aqui de conf, do tipo ModuleConfig, que dá acesso ao conteúdo do arquivo struts-config.xml.
  • O método [ModuleConfig].findPlugInConfigs() permite recuperar todas as seções <plug-in> do arquivo de configuração do Struts na forma de uma matriz de objetos PlugInConfig.
  • A classe PluginConfig representa uma seção <plug-in> do arquivo de configuração. O método [PlugInConfig].getProperties permite acessar os elementos <set-property> da seção na forma de um dicionário java.util.Map.
  • O dicionário de propriedades do plug-in é colocado no contexto do aplicativo.
  • Como pode haver vários plug-ins, precisamos identificar aquele que nos interessa. É aquele que tem o mesmo nome da classe que está sendo executada.

Preferimos, neste caso, colocar o dicionário completo no contexto. Poderíamos ter optado por utilizá-lo. A sequência de código a seguir ilustra uma maneira de fazer isso:

            Map initialisations = pluginConfigs[i].getProperties();
             // iterar pelas entradas do dicionário
            Iterator entrées = initialisations.entrySet().iterator();
            while (entrées.hasNext()) {
                 // recuperar a entrada (chave, valor) atual
                Map.Entry entrée = (Map.Entry) entrées.next();
                String clé = (String) entrée.getKey();
                String valeur = (String) entrée.getValue();
                // processar (chave, valor)
                //...
            }

8.3. O código da visualização infos.jsp

A visualização infos.jsp é responsável por exibir o conteúdo do dicionário de propriedades do plug-in que foi inserido no contexto do aplicativo. Como a visualização infos.jsp faz parte desse contexto, ela tem acesso a ele. Seu código é o seguinte:

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

<html>
    <head>
        <title>Plugin</title>
    </head>
    <body>
        <h3>Infos du plugin<br></h3>
        <table border="1">
            <tr>
                <th>Clé</th><th>Valeur</th>
            </tr>            
            <logic:iterate id="element" name="initialisations">
                <tr>
                    <td><bean:write name="element" property="key"/></td>
                    <td><bean:write name="element" property="value"/></td>
                </tr>
            </logic:iterate>
        </table>
    </body>
</html>

Observações:

  • utilizamos as bibliotecas de tags struts-logic e struts-bean
  • a tag <logic:iterate> nos permite exibir o dicionário de inicializações que foi inserido no contexto pelo método init do plugin. O atributo name indica o objeto sobre o qual deve-se iterar. Trata-se de algo que deve se assemelhar a uma coleção, um iterador, etc. O objeto é procurado em todos os escopos (página, solicitação, sessão, contexto). Aqui, ele será encontrado no escopo context. O parâmetro id serve para atribuir um nome ao elemento atual da coleção ao longo das iterações. Aqui, no corpo da tag <logic:iterate>, element representará o elemento atual de um dicionário. Este é representado por um objeto java.util.Map.Entry, que é, grosso modo, um par (chave, valor) do dicionário.
  • No corpo da tag <logic:iterate>, exibimos (<bean:write>) o conteúdo do elemento atual element. Este é considerado um objeto com duas propriedades (property): a chave key e o valor value. Essas duas propriedades são exibidas.

8.4. Implantação

O contexto da aplicação é definido no arquivo de configuração server.xml do Tomcat:

<Context path="/plugin11" reloadable="true" docBase="E:\data\serge\web\struts\plugins\1" />

A estrutura da aplicação é a seguinte:

 
 

8.5. Os testes

Iniciamos o Tomcat e acessamos a página http://localhost:8080/plugin1/infos.jsp:

Image

Constatamos que a visualização infos.jsp teve acesso às informações armazenadas no contexto da aplicação pelo plug-in.

8.6. Conclusão

Demonstramos que é possível inicializar uma aplicação Struts por meio de um plug-in. Essa pode ser uma solução alternativa à derivação da classe ActionServlet para realizar a mesma tarefa.