Skip to content

8. Creazione di un plugin

È possibile creare applicazioni chiamate plugin che vengono caricate all'avvio di un'applicazione Struts e scaricate al suo arresto. Ciò consente tipicamente l'inizializzazione all'avvio dell'applicazione e il rilascio delle risorse al suo arresto. Queste operazioni possono essere eseguite anche estendendo la classe ActionServlet del controller, come è stato fatto nell'applicazione precedente. Il plugin è un'alternativa a questa soluzione. Un plugin può essere un'applicazione più complessa di una semplice inizializzazione dell'ambiente. Ne abbiamo visto un esempio nella lezione in cui sono state introdotte le regole di validazione dichiarativa. Un plugin viene dichiarato nel file di configurazione di Struts. Il ValidatorPlugIn è stato dichiarato nel file struts-config.xml dell'applicazione che lo utilizzava come segue:

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

Descriveremo ora un'applicazione Struts che utilizza un plugin.

8.1. Configurazione dell'applicazione Struts /plugin1

Proponiamo di realizzare l'applicazione Struts /plugin1 configurata come segue:

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>

Non ci soffermeremo su questo file, poiché è standard.

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>

Abbiamo aggiunto una sola sezione, quella relativa al plugin. Gli attributi del tag <plug-in> qui utilizzato sono i seguenti:

className
nome della classe del plugin
<set-property>
consente di inizializzare il plugin con coppie (chiave, valore)

Lo scopo di questa applicazione è dimostrare come il plugin possa recuperare i propri parametri di inizializzazione e renderli disponibili ad altri oggetti che condividono lo stesso contesto applicativo. Useremo una semplice vista JSP per visualizzare i valori di inizializzazione del plugin, il che spiega perché non vi sia alcuna azione nel file di configurazione.

8.2. La classe Java del plugin

Una classe Java che funge da plugin per un'applicazione Struts deve implementare l'interfaccia org.apache.struts.action.PlugIn. Questa implementazione comporta la scrittura di due metodi:

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

Quando l'applicazione Struts viene caricata, il suo controller istanzierà tutti i plugin dichiarati nel file struts-config.xml. Eseguirà quindi il metodo init per ciascuno di essi. È all'interno di questo metodo che il plugin esegue la sua inizializzazione. Qui, ci limiteremo a leggere i parametri di inizializzazione del plugin e a inserirli nel contesto dell'applicazione in modo che siano disponibili per tutti gli altri oggetti dell'applicazione. Quando l'applicazione viene scaricata, il controller eseguirà il metodo destroy per ciascuno dei plugin caricati. Questo è il momento di liberare le risorse che non sono più necessarie. Qui, non avremo nulla da fare.

Il codice della classe è il seguente:

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 {

    // method called when application context is deleted
    public void destroy() {
    }

     // method called on initial creation of application context
    public void init(ActionServlet servlet, ModuleConfig conf)
        throws ServletException {
         // class name of this object
        String className=this.getClass().getName();
        // plug-in list
        PlugInConfig[] pluginConfigs = conf.findPlugInConfigs();
         // explore plugins to find the right one
         // which is named after this class
        boolean trouvé=false;
        for (int i = 0; ! trouvé && i < pluginConfigs.length; i++) {
            // plugin name
            String pluginClassName=pluginConfigs[i].getClassName();
             // if it's not the right plugin, continue
            if(! pluginClassName.equals(className)) continue;
            // it's the right one - you memorize its properties in context
            servlet.getServletContext().setAttribute("initialisations",pluginConfigs[i].getProperties());
            trouvé=true;
        }//for i
    } //init
} //class

Si prega di tenere presente quanto segue:

  • Il metodo init accetta un parametro denominato conf (di tipo ModuleConfig) che fornisce l'accesso al contenuto del file struts-config.xml.
  • Il metodo [ModuleConfig].findPlugInConfigs() recupera tutte le sezioni <plug-in> dal file di configurazione Struts sotto forma di un array di oggetti PlugInConfig.
  • La classe PluginConfig rappresenta una sezione <plug-in> del file di configurazione. Il metodo [PlugInConfig].getProperties consente di accedere agli elementi <set-property> della sezione sotto forma di un dizionario java.util.Map.
  • Il dizionario delle proprietà del plugin è collocato nel contesto dell'applicazione.
  • Poiché potrebbero esserci più plugin, dobbiamo trovare quello che ci interessa. È quello con lo stesso nome della classe in esecuzione.

Qui abbiamo scelto di inserire l'intero dizionario nel contesto. Avremmo potuto scegliere di utilizzarlo. Il seguente frammento di codice illustra un modo per farlo:

            Map initialisations = pluginConfigs[i].getProperties();
             // iterate over dictionary entries
            Iterator entrées = initialisations.entrySet().iterator();
            while (entrées.hasNext()) {
                 // retrieve current input (key,value)
                Map.Entry entrée = (Map.Entry) entrées.next();
                String clé = (String) entrée.getKey();
                String valeur = (String) entrée.getValue();
                // exploit (key,value)
                //...
            }

8.3. Il codice per la vista infos.jsp

La vista infos.jsp è responsabile della visualizzazione dei contenuti del dizionario delle proprietà del plugin, che è stato inserito nel contesto dell'applicazione. Poiché la vista infos.jsp fa parte di questo contesto, ha accesso ad esso. Il suo codice è il seguente:

<%@ 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>

Note:

  • Utilizziamo le librerie di tag struts-logic e struts-bean
  • Il tag <logic:iterate> ci permette di visualizzare il dizionario delle inizializzazioni che è stato inserito nel contesto dal metodo init del plugin. L'attributo name specifica l'oggetto su cui eseguire l'iterazione. Dovrebbe trattarsi di qualcosa come una collezione, un iteratore, ecc. L'oggetto viene cercato in tutti gli ambiti (pagina, richiesta, sessione, contesto). In questo caso, verrà trovato nell'ambito del contesto. Il parametro id viene utilizzato per denominare l'elemento corrente della collezione man mano che l'iterazione procede. Qui, all'interno del corpo del tag <logic:iterate>, element rappresenterà l'elemento corrente di un dizionario. Questo è rappresentato da un oggetto java.util.Map.Entry, che è essenzialmente una coppia (chiave, valore) del dizionario.
  • Nel corpo del tag <logic:iterate>, visualizziamo (<bean:write>) il contenuto dell'elemento corrente element. Questo viene trattato come un oggetto con due proprietà: la chiave e il valore. Entrambe queste proprietà vengono visualizzate.

8.4. Distribuzione

Il contesto dell'applicazione è definito nel file di configurazione server.xml di Tomcat:

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

La struttura delle directory dell'applicazione è la seguente:

  
  

8.5. Test

Avviamo Tomcat e inviamo una richiesta all'URL http://localhost:8080/plugin1/infos.jsp:

Image

Notiamo che la vista infos.jsp ha effettuato correttamente l'accesso alle informazioni memorizzate nel contesto dell'applicazione tramite il plugin.

8.6. Conclusione

Abbiamo dimostrato che un'applicazione Struts può essere inizializzata utilizzando un plugin. Ciò può rappresentare un'alternativa alla derivazione della classe ActionServlet per ottenere lo stesso risultato.