Skip to content

8. Création d'un plugin

Il est possible de créer des applications appelées plugins qui sont chargées au démarrage d'une application Struts et déchargées lors de son arrêt. Cela permet classiquement d'opérer des initialisations au démarrage de l'application et des libérations de ressources lors de l'arrêt de celle-ci. Ces opérations peuvent être également faites en dérivant la classe ActionServlet du contrôleur et c'est ce qui a été fait dans l'application quiest précédente. Le plugin est une alternative à cette solution. Le plugin peut être une application plus complexe qu'une simple initialisation de l'environnement. Nous en avons vu un exemple dans la leçon où ont été introduites les notions de règles de validation déclaratives. Un plugin est déclaré dans le fichier de configuration de Struts. Le plugin ValidatorPlugIn était ainsi déclaré dans le fichier struts-config.xml de l'application qui l'utilisait :

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

Nous décrivons maintenant une application Struts utilisant un plugin.

8.1. Configuration de l'application Struts /plugin1

On se propose de construire l'application Struts /plugin1 configurée de la façon suivante :

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>

Nous ne nous attarderons pas sur ce fichier qui est 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>

Nous n'avons introduit qu'une section, celle pour le plugin. Les attributs de la balise <plug-in> utilisés ici sont les suivants :

className

nom de la classe du plugin

<set-property>

permet d'initialiser le plugin avec des couples (clé, valeur)

Le but de cette application est de montrer comment le plugin peut récupérer ses paramètres d'initialisation et les rendre disponibles aux autres objets partageant le même contexte d'application. Nous ferons appel à une simple vue JSP pour afficher les valeurs d'initialisation du plugin ce qui explique qu'il n'y a aucune action dans le fichier de configuration.

8.2. La classe java du plugin

Une classe Java servant de plugin à une application Struts doit implémenter l'interface org.apache.struts.action.PlugIn. Cette implémentation consiste à écrire deux méthodes :

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

Lorsque l'application Struts va être chargée, son contrôleur va instancier tous les plugins déclarés dans le fichier struts-config.xml. Puis, il exécutera la méthode init de chacun d'eux. C'est dans cette méthode que le plugin fait ses initialisations. Ici, nous nous contenterons de lire les paramètres d'initialisation du plugin et de mettre ceux-ci dans le contexte de l'application afin qu'ils soient disponibles pour tous les autres objets de celle-ci. Lorsque l'application va être déchargée, le contrôleur exécutera la méthode destroy de chacun des plugins chargés. C'est le moment de libérer des ressources devenues inutiles. Ici, nous n'aurons rien à faire.

Le code de la classe est le suivant :

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éthode appelée à la suppression du contexte de l'application
    public void destroy() {
    }

    // méthode appelée lors de la création initiale du contexte de l'application
    public void init(ActionServlet servlet, ModuleConfig conf)
        throws ServletException {
        // nom de la classe de cet objet
        String className=this.getClass().getName();
        // liste des plugins
        PlugInConfig[] pluginConfigs = conf.findPlugInConfigs();
        // exploration des plugins pour trouver celui
        // qui porte le nom de cette classe
        boolean trouvé=false;
        for (int i = 0; ! trouvé && i < pluginConfigs.length; i++) {
            // nom du plugin
            String pluginClassName=pluginConfigs[i].getClassName();
            // si ce n'est pas le bon plugin, on continue
            if(! pluginClassName.equals(className)) continue;
            // c'est le bon - on mémorise ses propriétés dans le contexte
            servlet.getServletContext().setAttribute("initialisations",pluginConfigs[i].getProperties());
            trouvé=true;
        }//for i
    } //init
} //classe

A noter les points suivants :

  • la méthode init reçoit un paramètre appelé ici conf de type ModuleConfig qui donne accès au contenu du fichier struts-config.xml.
  • la méthode [ModuleConfig].findPlugInConfigs() permet de récupérer toutes les sections <plug-in> du fichier de configuration de Struts sous la forme d'un tableau d'objets PlugInConfig.
  • la classe PluginConfig représente une section <plug-in> du fichier de configuration. La méthode [PlugInConfig].getProperties nous permet d'avoir accès aux éléments <set-property> de la section sous la forme d'un dictionnaire java.util.Map.
  • le dictionnaire des propriétés du plugin est mis dans le contexte de l'application.
  • comme il peut y avoir plusieurs plugins, il nous faut trouver celui qui nous intéresse. C'est celui qui porte le même nom que la classe qui s'exécute.

Nous avons préféré ici mettre la totalité du dictionnaire dans le contexte. Nous aurions pu vouloir exploiter celui-ci. La séquence de code suivante illustre une manière de faire :

            Map initialisations = pluginConfigs[i].getProperties();
            // itérer sur les entrées du dictionnaire
            Iterator entrées = initialisations.entrySet().iterator();
            while (entrées.hasNext()) {
                // récupérer l'entrée (clé,valeur) courante
                Map.Entry entrée = (Map.Entry) entrées.next();
                String clé = (String) entrée.getKey();
                String valeur = (String) entrée.getValue();
                // exploiter (clé,valeur)
                //...
            }

8.3. Le code de la vue infos.jsp

La vue infos.jsp est chargée de visualiser le contenu du dictionnaire des propriétés du plugin qui a été mis dans le contexte de l'application. Comme la vue infos.jsp fait partie de ce contexte, elle y a accès. Son code est le suivant :

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

Points à noter :

  • nous utilisons les bibliothèques de balises struts-logic et struts-bean
  • la balise <logic:iterate> nous permet d'afficher le dictionnaire initialisations qui a été mis dans le contexte par la méthode init du plugin. L'attribut name désigne l'objet sur lequel il faut itérer. C'est quelque chose qui doit ressembler à une collection, un itérateur, ... L'objet est cherché dans toutes les portées (page, request, session, context). Ici il sera trouvé dans la portée context. Le paramètre id sert à donner un nom à l'élément courant de la collection au fil des itérations. Ici, dans le corps de la balise <logic:iterate>, element représentera l'élément courant d'un dictionnaire. Celui-ci est représenté par un objet java.util.Map.Entry qui est grosso modo un couple (clé, valeur) du dictionnaire.
  • dans le corps de la balise <logic:iterate>, on fait afficher (<bean:write>) le contenu de l'élément courant element. Celui-ci est considéré comme un objet à deux propriétés (property) : la clé key et la valeur value. Ces deux propriétés sont affichées.

8.4. Déploiement

Le contexte de l'application est défini dans le fichier de configuration server.xml de Tomcat :

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

L'arborescence de l'application est la suivante :

8.5. Les tests

Nous lançons Tomcat et demandons l'URL http://localhost:8080/plugin1/infos.jsp :

Image

Nous constatons que la vue infos.jsp a bien eu accès aux informations stockées dans le contexte de l'application par le plugin.

8.6. Conclusion

Nous avons montré qu'on pouvait initialiser une application Struts à l'aide d'un plugin. Ce peut être une solution alternative à celle de dériver la classe ActionServlet pour faire le même travail.