Tomcat, Xerces y yo
Tratando de utilizar la, por el momento, mejor implementación de XForms, Chiba, me he topado con los problemas que tiene meter distintas aplicaciones en un mismo Tomcat, utilizar Xerces y aplicaciones web que dependen de Xerces.
¿Has tenido tú problemas con Tomcat, Xerces y TUs aplicaciones web?
XDD. Je, je.
No me sorprende en absoluto, hay bastante literatura escrita al respecto. Yo voy a intentar de resumir aquí los principales problemas que me he encontrado, supongo que si el servidor de aplicaciones que utilizas no es Tomcat (Weblogic, WebSphere, etc) tendrás similiares problemas que *tendrán* similares soluciones.
Pues eso, según he estado leyendo en la web de Tomcat este servidor de aplicaciones utiliza diferentes classloaders para la carga de clases, y se relacionan en forma de árbol. De forma que cuando un classloader necesita cargar una clase, primero delega este trabajo al padre, y si éste no consigue la carga de la clase entonces delega el trabajo al hijo (el classloader en cuestión).
Bootstrap
|
System
|
Common
/ \
Catalina Shared
/ \
Webapp1 Webapp2 ...
Tomcat añade una particularidad, y es que el classloader de cada webapp siempre va a tener preferencia sobre el resto. Así pues, desde el punto de vista de tu aplicación, la búsqueda de clases se realiza de la siguiente forma:
* /WEB-INF/classes en tu webapp
* /WEB-INF/lib/*.jar en tu webapp
* Bootstrap classes en tu JVM
- Runtime Java
- $JAVA_HOME/jre/lib/ext
* System class loader classes
- $CATALINA_HOME/bin/bootstrap.jar
- $JAVA_HOME/lib/tools.jar
* $CATALINA_HOME/common/classes
* $CATALINA_HOME/common/endorsed/*.jar
* $CATALINA_HOME/common/lib/*.jar
* $CATALINA_HOME/shared/classes
* $CATALINA_HOME/shared/lib/*.jar
Además de estas reglas, hay una particularidad con respecto a las clases que forman parte de J2SE y que son cargadas por el classloader de cada webapp:
javax.".
En este caso se delega la carga al classloader padre sin tener en cuenta la configuración establecida anteriormente. Además el classloader de cada webapp no va a cargar nunca las clases estándar java, aquellas que empiezan por java.*.
¿Queda claro el sistema de classloaders de Tomcat? ¿Sí? Bien, sigamos con las particularidades de la versión del JDK.
Xerces y JDK 1.4
Entre otros cambios, a Sun se le ocurrió la *feliz* idea de empaquetar la API JAXP junto con una versión de Xerces en su versión 1.4 del JDK. Esto supone un gran inconveniente en aquellas aplicaciones que quieran utilizar sus propias versiones de parseadores SAX y DOM, puesto que la versión incluida en el JDK tiene preferencia en la carga. Por ejemplo, cuando se ejecuta Tomcat con JDK 1.4 el proceso de delegación de classloaders va a elegir siempre la implementación presente dentro del JDK y no la existente en Tomcat.
Sun, para permitir que se pueda reemplazar versiones incluidas en el JDK, ideó un mecanismo llamado Endorsed Standards Override Mechanism que consiste en situar paquetes de clases Java (*.jar) en determinados directorios que reemplacen a los definidos por la JVM. Estos directorios suelen tener el nombre endorsed y para la JVM, por ejemplo se sitúa en $JAVA_HOME/jre/lib/endorsed. Tomcat tambien dispone de un directorio de paquetes endorsed: $CATALINA_HOME/common/endorsed, carga estos paquetes de forma que sustituyen a los definidos en el JDK.
Tercer problema: ¿Qué versión de Xerces necesitan nuestras aplicaciones?
Este suele ser el punto más crítico, ya que por la experiencia que he tenido NO todas las aplicaciones web soportan cualquier versión de Xerces y puede obligarnos a tener que instalar varias instancias de Tomcat para conseguir que todo funcione.
Conclusión
Para poder utilizar Xerces correctamente en nuestras aplicaciones web y Tomcat tendremos en cuenta las siguientes recomendaciones:
- Averiguar la versión de Xerces que necesita cada una de nuestras webapps
- Obtener las versiones de Xerces y Xalan (u otra API JAXP de transformación compatible) más recientes que cumplan los requisitos de las webapps
- Instalar las versiones más recientes en
$CATALINA_HOME/common/endorseddentro del directorio de Tomcat- Quitar cualquier versión citada del directorio
WEB-INF/libde nuestra webapp- Rezar para que todo funcione (XDDDDD, NO, en serio... que sí que va... pffffffff)
Tengo que ver todavía el caso de Cocoon, que no sé por qué no me funciona con la última versión de Xerces...