En mi oficina, la mera mención de la palabra Xerces es suficiente para incitar la ira asesina de los desarrolladores. Una mirada superficial a las otras preguntas de Xerces sobre SO parece indicar que casi todos los usuarios de Maven están "tocados" por este problema en algún momento. Desafortunadamente, comprender el problema requiere un poco de conocimiento sobre la historia de Xerces ...
Historia
Xerces es el analizador XML más utilizado en el ecosistema Java. Casi todas las bibliotecas o frameworks escritos en Java usan Xerces en cierta capacidad (transitivamente, si no directamente).
Los frascos Xerces incluidos en los binarios oficiales no están, hasta el día de hoy, versionados. Por ejemplo, el jar de implementación Xerces 2.11.0 se nombra
xercesImpl.jar
y noxercesImpl-2.11.0.jar
.El equipo de Xerces no usa Maven , lo que significa que no sube un lanzamiento oficial a Maven Central .
Xerces solía lanzarse como un solo jar (
xerces.jar
), pero se dividió en dos tarros, uno que contenía la API (xml-apis.jar
) y otro que contenía las implementaciones de esas API (xercesImpl.jar
). Muchos POM Maven más antiguos todavía declaran una dependenciaxerces.jar
. En algún momento en el pasado, Xerces también se lanzó comoxmlParserAPIs.jar
, de lo que también dependen algunos POM más antiguos.Las versiones asignadas a los frascos xml-apis y xercesImpl por aquellos que implementan sus frascos en los repositorios de Maven a menudo son diferentes. Por ejemplo, xml-apis podría tener la versión 1.3.03 y xercesImpl podría tener la versión 2.8.0, aunque ambas son de Xerces 2.8.0. Esto se debe a que la gente suele etiquetar el xml-apis jar con la versión de las especificaciones que implementa. Hay un desglose muy agradable, pero incompleto de esto aquí .
Para complicar las cosas, Xerces es el analizador XML utilizado en la implementación de referencia de la API Java para el procesamiento XML (JAXP), incluido en el JRE. Las clases de implementación se vuelven a empaquetar bajo el
com.sun.*
espacio de nombres, lo que hace que sea peligroso acceder a ellas directamente, ya que pueden no estar disponibles en algunos JRE. Sin embargo, no toda la funcionalidad de Xerces se expone a través de las APIjava.*
yjavax.*
; por ejemplo, no hay API que exponga la serialización de Xerces.Además del confuso desorden, casi todos los contenedores de servlets (JBoss, Jetty, Glassfish, Tomcat, etc.) se envían con Xerces en una o más de sus
/lib
carpetas.
Problemas
La resolución de conflictos
Por algunas, o quizás por todas, las razones anteriores, muchas organizaciones publican y consumen compilaciones personalizadas de Xerces en sus POM. Esto no es realmente un problema si tiene una aplicación pequeña y solo está utilizando Maven Central, pero rápidamente se convierte en un problema para el software empresarial donde Artifactory o Nexus está representando múltiples repositorios (JBoss, Hibernate, etc.):
Por ejemplo, la organización A podría publicar xml-apis
como:
<groupId>org.apache.xerces</groupId>
<artifactId>xml-apis</artifactId>
<version>2.9.1</version>
Mientras tanto, la organización B podría publicar lo mismo jar
que:
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.3.04</version>
Aunque B's jar
es una versión más baja que A's jar
, Maven no sabe que son el mismo artefacto porque tienen diferentes
groupId
s. Por lo tanto, no puede realizar la resolución de conflictos y ambos
jar
s se incluirán como dependencias resueltas:
Infierno del cargador de clases
Como se mencionó anteriormente, el JRE se envía con Xerces en el JAXP RI. Mientras que sería bueno para marcar todas las dependencias de Maven como Xerces <exclusion>
s o como<provided>
, el código de terceros del que depende puede o no funcionar con la versión proporcionada en JAXP del JDK que está utilizando. Además, tiene los frascos Xerces enviados en su contenedor de servlets con los que lidiar. Esto le deja con una serie de opciones: ¿Elimina la versión del servlet y espera que su contenedor se ejecute en la versión JAXP? ¿Es mejor dejar la versión de servlet y esperar que los marcos de sus aplicaciones se ejecuten en la versión de servlet? Si uno o dos de los conflictos no resueltos descritos anteriormente logran deslizarse en su producto (fácil de suceder en una organización grande), rápidamente se encuentra en el infierno del cargador de clases, preguntándose qué versión de Xerces está eligiendo el cargador de clases en el tiempo de ejecución y si elegirá el mismo jar en Windows y Linux (probablemente no).
Soluciones?
Hemos intentado marcar todas las dependencias de Maven como Xerces <provided>
o como una <exclusion>
, pero esto es difícil de hacer cumplir (especialmente con un equipo grande) dado que los artefactos tienen tantos alias ( xml-apis
, xerces
, xercesImpl
, xmlParserAPIs
, etc.). Además, nuestros libs / frameworks de terceros pueden no ejecutarse en la versión JAXP o la versión proporcionada por un contenedor de servlet.
¿Cómo podemos abordar mejor este problema con Maven? ¿Tenemos que ejercer un control tan preciso sobre nuestras dependencias y luego confiar en la carga de clases por niveles? ¿Hay alguna forma de excluir globalmente todas las dependencias de Xerces y obligar a todos nuestros frameworks / libs a usar la versión JAXP?
ACTUALIZACIÓN : Joshua Spiewak ha subido una versión parcheada de los scripts de compilación de Xerces a XERCESJ-1454 que permite la carga en Maven Central. Vota / mira / contribuye a este problema y solucionemos este problema de una vez por todas.
fuente
Respuestas:
¡Hay 2.11.0 JAR (y JAR fuente) de Xerces en Maven Central desde el 20 de febrero de 2013! Ver Xerces en Maven Central . Me pregunto por qué no han resuelto https://issues.apache.org/jira/browse/XERCESJ-1454 ...
He usado:
y todas las dependencias se resolvieron bien, ¡incluso las correctas
xml-apis-1.4.01
!Y lo que es más importante (y lo que no era obvio en el pasado): el JAR en Maven Central es el mismo JAR que en la
Xerces-J-bin.2.11.0.zip
distribución oficial .Sin embargo, no pude encontrar la
xml-schema-1.1-beta
versión, no puede ser unaclassifier
versión de Maven debido a dependencias adicionales.fuente
xml-apis:xml-apis:1.4.01
sea más nuevo quexml-apis:xml-apis:2.0.2
?? ver search.maven.org/…Francamente, casi todo lo que hemos encontrado funciona bien con la versión JAXP, por lo que siempre excluimos
xml-apis
yxercesImpl
.fuente
java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal
en tiempo de ejecución.Puede usar el complemento maven enforcer con la regla de dependencia prohibida. Esto le permitiría prohibir todos los alias que no desea y permitir solo el que sí desea. Estas reglas fallarán la construcción maven de su proyecto cuando se violen. Además, si esta regla se aplica a todos los proyectos en una empresa, puede poner la configuración del complemento en un pom padre corporativo.
ver:
fuente
Sé que esto no responde la pregunta exactamente, pero para las personas que vienen de Google que utilizan Gradle para su gestión de dependencia:
Logré deshacerme de todos los problemas de xerces / Java8 con Gradle de esta manera:
fuente
Supongo que hay una pregunta que debes responder:
¿Existe un xerces * .jar con el que todo en su aplicación pueda vivir?
Si no, básicamente estás jodido y tendrías que usar algo como OSGI, que te permite tener diferentes versiones de una biblioteca cargadas al mismo tiempo. Tenga en cuenta que básicamente reemplaza los problemas de la versión jar con problemas del cargador de clases ...
Si existe una versión de este tipo, puede hacer que su repositorio devuelva esa versión para todo tipo de dependencias. Es un truco feo y terminaría con la misma implementación de xerces en su classpath varias veces, pero mejor que tener múltiples versiones diferentes de xerces.
Puede excluir todas las dependencias de xerces y agregar una a la versión que desea usar.
Me pregunto si puedes escribir algún tipo de estrategia de resolución de versión como complemento para Maven. Esta sería probablemente la mejor solución, pero si es posible, necesita algo de investigación y codificación.
Para la versión contenida en su entorno de tiempo de ejecución, deberá asegurarse de que se elimine de la ruta de clase de la aplicación o de que los frascos de la aplicación se consideren primero para la carga de clases antes de considerar la carpeta lib del servidor.
Para concluir: es un desastre y eso no cambiará.
fuente
Hay otra opción que no se ha explorado aquí: declarar las dependencias de Xerces en Maven como opcionales :
Básicamente, lo que hace es obligar a todos los dependientes a declarar su versión de Xerces o su proyecto no se compilará. Si quieren anular esta dependencia, pueden hacerlo, pero serán dueños del problema potencial.
Esto crea un fuerte incentivo para proyectos posteriores para:
No todos los desarrolladores realizan un seguimiento de las dependencias recién introducidas (por ejemplo, con
mvn dependency:tree
). Este enfoque llamará inmediatamente la atención sobre el asunto.Funciona bastante bien en nuestra organización. Antes de su introducción, vivíamos en el mismo infierno que describe el OP.
fuente
Cada proyecto de Maven debería detenerse dependiendo de xerces, probablemente no lo hagan realmente. Las API XML y un Impl han sido parte de Java desde 1.4. No es necesario depender de xerces o API XML, es como decir que depende de Java o Swing. Esto es implícito.
Si fuera el jefe de un repositorio de Maven, escribiría un script para eliminar de forma recursiva las dependencias de xerces y escribiría un mensaje de lectura que diga que este repositorio requiere Java 1.4.
Cualquier cosa que realmente se rompa porque hace referencia a Xerces directamente a través de las importaciones org.apache necesita una corrección de código para llevarlo al nivel Java 1.4 (y lo ha hecho desde 2002) o una solución a nivel JVM a través de bibliotecas respaldadas, no en Maven.
fuente
Primero debe depurar, para ayudar a identificar su nivel de infierno XML. En mi opinión, el primer paso es agregar
a la línea de comando. Si eso funciona, entonces comience a excluir bibliotecas. Si no, entonces agregue
a la línea de comando.
fuente
Lo que ayudaría, a excepción de excluir, son las dependencias modulares.
Con una carga de clase plana (aplicación independiente) o semi-jerárquica (JBoss AS / EAP 5.x) esto fue un problema.
Pero con marcos modulares como los módulos OSGi y JBoss , esto ya no es tanto dolor. Las bibliotecas pueden usar la biblioteca que deseen, independientemente.
Por supuesto, es más recomendable seguir con una sola implementación y versión, pero si no hay otra forma (usando características adicionales de más bibliotecas), la modularización podría salvarlo.
Un buen ejemplo de los módulos JBoss en acción es, naturalmente, JBoss AS 7 / EAP 6 / WildFly 8 , para lo cual se desarrolló principalmente.
Definición de módulo de ejemplo:
En comparación con OSGi, los módulos JBoss son más simples y rápidos. Si bien faltan ciertas características, es suficiente para la mayoría de los proyectos que (en su mayoría) están bajo el control de un proveedor, y permiten un arranque rápido impresionante (debido a la resolución de dependencias paralelizadas).
Tenga en cuenta que hay un esfuerzo de modularización en curso para Java 8 , pero AFAIK es principalmente para modularizar el JRE en sí mismo, no estoy seguro de si será aplicable a las aplicaciones.
fuente
Aparentemente
xerces:xml-apis:1.4.01
ya no está en Maven Central, que sin embargo es lo que hacexerces:xercesImpl:2.11.0
referencia.Esto funciona para mi:
fuente
Mi amigo eso es muy simple, aquí un ejemplo:
Y si desea verificar en la terminal (consola de Windows para este ejemplo) que su árbol maven no tiene problemas:
fuente