8. Creación de un plugin
Es posible crear aplicaciones denominadas plugins que se cargan al iniciar una aplicación Struts y se descargan al cerrarla. Esto permite, de forma habitual, realizar inicializaciones al iniciar la aplicación y liberar recursos al cerrarla. Estas operaciones también pueden realizarse derivando la clase ActionServlet del controlador, y eso es lo que se ha hecho en la aplicación anterior. El plugin es una alternativa a esta solución. El plugin puede ser una aplicación más compleja que una simple inicialización del entorno. Hemos visto un ejemplo de ello en la lección en la que se introdujeron los conceptos de reglas de validación declarativas. Un plugin se declara en el archivo de configuración de Struts. El plugin ValidatorPlugIn se declaraba así en el archivo struts-config.xml de la aplicación que lo utilizaba:
<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 continuación describimos una aplicación Struts que utiliza un plugin.
8.1. Configuración de la aplicación Struts /plugin1
Nos proponemos construir la aplicación Struts /plugin1 configurada de la siguiente manera:
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>
No nos detendremos en este archivo, que es estándar.
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>
Solo hemos introducido una sección, la del plugin. Los atributos de la etiqueta <plug-in> utilizados aquí son los siguientes:
nombre de la clase del plugin | |
permite inicializar el plugin con pares (clave, valor) |
El objetivo de esta aplicación es mostrar cómo el plugin puede recuperar sus parámetros de inicialización y ponerlos a disposición de otros objetos que comparten el mismo contexto de aplicación. Utilizaremos una vista sencilla JSP para mostrar los valores de inicialización del plugin, lo que explica que no haya ninguna acción en el archivo de configuración.
8.2. La clase Java del plugin
Una clase Java que sirva de plugin para una aplicación Struts debe implementar la interfaz org.apache.struts.action.PlugIn. Esta implementación consiste en escribir dos métodos:
- public void init(ActionServlet servlet, ModuleConfig conf)
- public void destroy()
Cuando se cargue la aplicación Struts, su controlador instanciará todos los complementos declarados en el archivo struts-config.xml. A continuación, ejecutará el método init de cada uno de ellos. Es en este método donde el complemento realiza sus inicializaciones. Aquí, nos limitaremos a leer los parámetros de inicialización del plugin y a colocarlos en el contexto de la aplicación para que estén disponibles para todos los demás objetos de la misma. Cuando la aplicación vaya a descargarse, el controlador ejecutará el método destroy de cada uno de los plugins cargados. Es el momento de liberar los recursos que ya no son necesarios. Aquí, no tendremos nada que hacer.
El código de la clase es el siguiente:
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 llamado al eliminar el contexto de la aplicación
public void destroy() {
}
// método llamado durante la creación inicial del contexto de la aplicación
public void init(ActionServlet servlet, ModuleConfig conf)
throws ServletException {
// nombre de la clase de este objeto
String className=this.getClass().getName();
// lista de complementos
PlugInConfig[] pluginConfigs = conf.findPlugInConfigs();
// búsqueda entre los complementos para encontrar aquel
// que lleva el nombre de esta clase
boolean trouvé=false;
for (int i = 0; ! trouvé && i < pluginConfigs.length; i++) {
// nombre del plugin
String pluginClassName=pluginConfigs[i].getClassName();
// si no es el complemento correcto, continuamos
if(! pluginClassName.equals(className)) continue;
// es el correcto: memorizamos sus propiedades en el contexto
servlet.getServletContext().setAttribute("initialisations",pluginConfigs[i].getProperties());
trouvé=true;
}//for i
} //init
} //classe
Cabe destacar los siguientes puntos:
- el método init recibe un parámetro denominado aquí conf, de tipo ModuleConfig, que da acceso al contenido del archivo struts-config.xml.
- El método [ModuleConfig].findPlugInConfigs() permite recuperar todas las secciones <plug-in> del archivo de configuración de Struts en forma de una matriz de objetos PlugInConfig.
- La clase PluginConfig representa una sección <plug-in> del archivo de configuración. El método [PlugInConfig].getProperties nos permite acceder a los elementos <set-property> de la sección en forma de un diccionario java.util.Map.
- El diccionario de propiedades del plugin se coloca en el contexto de la aplicación.
- Dado que puede haber varios complementos, debemos encontrar el que nos interesa. Es aquel que lleva el mismo nombre que la clase que se ejecuta.
En este caso, hemos preferido colocar todo el diccionario en el contexto. Podríamos haber querido utilizarlo. La siguiente secuencia de código ilustra una forma de hacerlo:
Map initialisations = pluginConfigs[i].getProperties();
// recorrer las entradas del diccionario
Iterator entrées = initialisations.entrySet().iterator();
while (entrées.hasNext()) {
// recuperar la entrada (clave, valor) actual
Map.Entry entrée = (Map.Entry) entrées.next();
String clé = (String) entrée.getKey();
String valeur = (String) entrée.getValue();
// procesar (clave, valor)
//...
}
8.3. El código de la vista infos.jsp
La vista infos.jsp se encarga de visualizar el contenido del diccionario de propiedades del complemento que se ha incluido en el contexto de la aplicación. Dado que la vista infos.jsp forma parte de este contexto, tiene acceso a él. Su código es el siguiente:
<%@ 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>
Notas:
- utilizamos las bibliotecas de etiquetas struts-logic y struts-bean
- La etiqueta <logic:iterate> nos permite mostrar el diccionario de inicializaciones que ha sido colocado en el contexto por el método init del plugin. El atributo name designa el objeto sobre el que hay que iterar. Debe ser algo parecido a una colección, un iterador, etc. El objeto se busca en todos los ámbitos (página, solicitud, sesión, contexto). En este caso, se encontrará en el ámbito «context». El parámetro id sirve para asignar un nombre al elemento actual de la colección a lo largo de las iteraciones. Aquí, en el cuerpo de la etiqueta <logic:iterate>, element representará el elemento actual de un diccionario. Este está representado por un objeto java.util.Map.Entry que es, a grandes rasgos, un par (clave, valor) del diccionario.
- En el cuerpo de la etiqueta <logic:iterate>, se muestra (<bean:write>) el contenido del elemento actual element. Este se considera un objeto con dos propiedades (property): la clave key y el valor value. Se muestran estas dos propiedades.
8.4. Implementación
El contexto de la aplicación se define en el archivo de configuración server.xml de Tomcat:
<Context path="/plugin11" reloadable="true" docBase="E:\data\serge\web\struts\plugins\1" />
La estructura de la aplicación es la siguiente:
![]() ![]() | ![]() | |
![]() | ||
8.5. Las pruebas
Iniciamos Tomcat y solicitamos el URL http://localhost:8080/plugin1/infos.jsp:

Observamos que la vista infos.jsp ha accedido correctamente a la información almacenada en el contexto de la aplicación por el plugin.
8.6. Conclusión
Hemos demostrado que se puede inicializar una aplicación Struts mediante un plugin. Esto puede ser una solución alternativa a derivar la clase ActionServlet para realizar la misma tarea.



