Dans mon bureau, la simple mention du mot Xerces suffit pour inciter les développeurs à la rage meurtrière. Un coup d'œil rapide aux autres questions de Xerces sur SO semble indiquer que presque tous les utilisateurs de Maven sont "touchés" par ce problème à un moment donné. Malheureusement, comprendre le problème nécessite un peu de connaissance sur l'histoire de Xerces ...
Histoire
Xerces est l'analyseur XML le plus utilisé dans l'écosystème Java. Presque toutes les bibliothèques ou frameworks écrits en Java utilisent Xerces dans une certaine mesure (de manière transitoire, sinon directement).
Les bocaux Xerces inclus dans les binaires officiels ne sont pas, à ce jour, versionnés. Par exemple, le pot d'implémentation Xerces 2.11.0 est nommé
xercesImpl.jar
et nonxercesImpl-2.11.0.jar
.L'équipe de Xerces n'utilise pas Maven , ce qui signifie qu'elle ne télécharge pas de version officielle sur Maven Central .
Xerces était auparavant publié sous la forme d'un seul pot (
xerces.jar
), mais était divisé en deux pots, l'un contenant l'API (xml-apis.jar
) et l'autre contenant les implémentations de ces API (xercesImpl.jar
). De nombreux POM Maven plus anciens déclarent toujours une dépendancexerces.jar
. À un moment donné dans le passé, Xerces a également été publié en tant quexmlParserAPIs.jar
, dont certains POM plus anciens dépendent également.Les versions attribuées aux fichiers xml-apis et xercesImpl par ceux qui déploient leurs fichiers dans les référentiels Maven sont souvent différentes. Par exemple, xml-apis peut recevoir la version 1.3.03 et xercesImpl peut recevoir la version 2.8.0, même si les deux proviennent de Xerces 2.8.0. C'est parce que les gens marquent souvent le pot xml-apis avec la version des spécifications qu'il implémente. Il y a une ventilation très agréable, mais incomplète de cette ici .
Pour compliquer les choses, Xerces est l'analyseur XML utilisé dans l'implémentation de référence de l'API Java pour le traitement XML (JAXP), inclus dans le JRE. Les classes d'implémentation sont reconditionnées sous l'
com.sun.*
espace de noms, ce qui rend leur accès direct dangereux, car elles peuvent ne pas être disponibles dans certains JRE. Cependant, toutes les fonctionnalités de Xerces ne sont pas exposées via lejava.*
javax.*
API et ; par exemple, il n'y a pas d'API qui expose la sérialisation de Xerces.Ajoutant au désordre déroutant, presque tous les conteneurs de servlets (JBoss, Jetty, Glassfish, Tomcat, etc.), sont expédiés avec Xerces dans un ou plusieurs de leurs
/lib
dossiers.
Problèmes
Résolution de conflit
Pour certaines - ou peut-être toutes - des raisons ci-dessus, de nombreuses organisations publient et utilisent des versions personnalisées de Xerces dans leurs POM. Ce n'est pas vraiment un problème si vous avez une petite application et que vous n'utilisez que Maven Central, mais cela devient rapidement un problème pour les logiciels d'entreprise où Artifactory ou Nexus assure le proxy de plusieurs référentiels (JBoss, Hibernate, etc.):
Par exemple, l'organisation A peut publier en xml-apis
tant que:
<groupId>org.apache.xerces</groupId>
<artifactId>xml-apis</artifactId>
<version>2.9.1</version>
Pendant ce temps, l'organisation B pourrait publier les mêmes jar
que:
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.3.04</version>
Bien que les B jar
soient une version inférieure aux A jar
, Maven ne sait pas qu'ils sont le même artefact car ils ont des groupId
s différents
. Ainsi, il ne peut pas effectuer la résolution des conflits et les deux
jar
s seront inclus en tant que dépendances résolues:
Classloader Hell
Comme mentionné ci-dessus, le JRE est livré avec Xerces dans le JAXP RI. Bien qu'il serait bien de marquer toutes les dépendances de Xerces Maven comme<exclusion>
s ou comme<provided>
, le code tiers dont vous dépendez peut ou non fonctionner avec la version fournie dans JAXP du JDK que vous utilisez. De plus, vous avez les pots Xerces expédiés dans votre conteneur de servlet pour faire face. Cela vous laisse un certain nombre de choix: supprimez-vous la version du servlet et espérez-vous que votre conteneur fonctionne sur la version JAXP? Est-il préférable de laisser la version du servlet et d'espérer que vos frameworks d'application fonctionnent sur la version du servlet? Si un ou deux des conflits non résolus décrits ci-dessus parviennent à se glisser dans votre produit (facile à produire dans une grande organisation), vous vous retrouvez rapidement dans l'enfer du chargeur de classe, en vous demandant quelle version de Xerces le chargeur de classe choisit au moment de l'exécution et si oui ou non il choisira le même pot sous Windows et Linux (probablement pas).
Solutions?
Nous avons essayé de marquer toutes les dépendances Xerces Maven <provided>
ou comme <exclusion>
, mais cela est difficile à appliquer ( en particulier avec une grande équipe) étant donné que les objets ont tant d'alias ( xml-apis
, xerces
, xercesImpl
,xmlParserAPIs
, etc.). De plus, nos bibliothèques / frameworks tiers peuvent ne pas fonctionner sur la version JAXP ou la version fournie par un conteneur de servlet.
Comment pouvons-nous résoudre au mieux ce problème avec Maven? Doit-on exercer un contrôle aussi fin sur nos dépendances, puis s'appuyer sur un chargement de classe à plusieurs niveaux? Existe-t-il un moyen d'exclure globalement toutes les dépendances de Xerces et de forcer tous nos frameworks / bibliothèques à utiliser la version JAXP?
MISE À JOUR : Joshua Spiewak a téléchargé une version corrigée des scripts de construction de Xerces sur XERCESJ-1454 qui permet le téléchargement sur Maven Central. Votez / regardez / contribuez à ce problème et résolvons ce problème une fois pour toutes.
la source
Réponses:
Il existe des JAR 2.11.0 (et des JAR source!) De Xerces dans Maven Central depuis le 20 février 2013! Voir Xerces dans Maven Central . Je me demande pourquoi ils n'ont pas résolu https://issues.apache.org/jira/browse/XERCESJ-1454 ...
J'ai utilisé:
et toutes les dépendances se sont bien résolues - même correctement
xml-apis-1.4.01
!Et ce qui est le plus important (et ce qui n'était pas évident dans le passé) - le JAR dans Maven Central est le même JAR que dans la
Xerces-J-bin.2.11.0.zip
distribution officielle .Je n'ai cependant pas pu trouver de
xml-schema-1.1-beta
version - ce ne peut pas être uneclassifier
version Maven à cause de dépendances supplémentaires.la source
xml-apis:xml-apis:1.4.01
est plus récente quexml-apis:xml-apis:2.0.2
?? voir search.maven.org/…Franchement, à peu près tout ce que nous avons rencontré fonctionne très bien avec la version JAXP, donc nous excluons toujours
xml-apis
etxercesImpl
.la source
java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal
à l'exécution.Vous pouvez utiliser le plugin mavenforcer avec la règle de dépendance interdite. Cela vous permettrait d'interdire tous les alias que vous ne voulez pas et d'autoriser uniquement celui que vous voulez. Ces règles échoueront la construction maven de votre projet en cas de violation. De plus, si cette règle s'applique à tous les projets d'une entreprise, vous pouvez placer la configuration du plug-in dans un pom parent d'entreprise.
voir:
la source
Je sais que cela ne répond pas exactement à la question, mais pour les personnes venant de google qui utilisent Gradle pour leur gestion des dépendances:
J'ai réussi à me débarrasser de tous les problèmes xerces / Java8 avec Gradle comme ceci:
la source
Je suppose qu'il y a une question à laquelle vous devez répondre:
Existe-t-il un xerces * .jar avec lequel tout dans votre application peut vivre?
Sinon, vous êtes fondamentalement foutu et devez utiliser quelque chose comme OSGI, qui vous permet d'avoir différentes versions d'une bibliothèque chargées en même temps. Soyez averti qu'il remplace essentiellement les problèmes de version jar par des problèmes de chargeur de classe ...
S'il existe une telle version, vous pouvez demander à votre référentiel de renvoyer cette version pour toutes sortes de dépendances. C'est un hack laid et se retrouverait avec la même implémentation de xerces dans votre chemin de classe plusieurs fois mais mieux que d'avoir plusieurs versions différentes de xerces.
Vous pouvez exclure toutes les dépendances de xerces et en ajouter une à la version que vous souhaitez utiliser.
Je me demande si vous pouvez écrire une sorte de stratégie de résolution de version en tant que plugin pour maven. Ce serait probablement la meilleure solution, mais si cela est possible, cela nécessite des recherches et un codage.
Pour la version contenue dans votre environnement d'exécution, vous devez vous assurer qu'elle soit supprimée du chemin de classe de l'application ou que les fichiers JAR d'application sont considérés en premier pour le chargement de classe avant que le dossier lib du serveur ne soit pris en compte.
Donc, pour résumer: c'est un gâchis et cela ne changera pas.
la source
Il existe une autre option qui n'a pas été explorée ici: déclarer les dépendances de Xerces dans Maven comme facultatives :
Fondamentalement, cela oblige toutes les personnes à charge à déclarer que leur version de Xerces ou leur projet ne sera pas compilé. S'ils veulent outrepasser cette dépendance, ils sont invités à le faire, mais ils seront alors propriétaires du problème potentiel.
Cela incite fortement les projets en aval à:
Tous les développeurs ne suivent pas les dépendances nouvellement introduites (par exemple avec
mvn dependency:tree
). Cette approche portera immédiatement la question à leur attention.Cela fonctionne assez bien dans notre organisation. Avant son introduction, nous vivions dans le même enfer que l'OP décrit.
la source
Chaque projet maven devrait s'arrêter en fonction des xerces, ce n'est probablement pas vraiment le cas. Les API XML et un Impl font partie de Java depuis 1.4. Il n'est pas nécessaire de dépendre de xerces ou d'API XML, c'est comme dire que vous dépendez de Java ou de Swing. C'est implicite.
Si j'étais le patron d'un dépôt maven, j'écrirais un script pour supprimer récursivement les dépendances xerces et j'écrirais un read me qui dit que ce dépôt nécessite Java 1.4.
Tout ce qui casse réellement car il fait référence à Xerces directement via les importations org.apache a besoin d'un correctif de code pour l'amener au niveau Java 1.4 (et c'est le cas depuis 2002) ou d'une solution au niveau JVM via des bibliothèques approuvées, pas dans maven.
la source
Vous devez d'abord déboguer pour identifier votre niveau d'enfer XML. À mon avis, la première étape consiste à ajouter
à la ligne de commande. Si cela fonctionne, commencez à exclure les bibliothèques. Sinon, ajoutez
à la ligne de commande.
la source
Ce qui aiderait, à l'exception de l'exclusion, ce sont les dépendances modulaires.
Avec un chargement de classe plat (application autonome) ou semi-hiérarchique (JBoss AS / EAP 5.x), c'était un problème.
Mais avec des frameworks modulaires comme les modules OSGi et JBoss , ce n'est plus tant la peine. Les bibliothèques peuvent utiliser la bibliothèque de leur choix, indépendamment.
Bien sûr, il est toujours recommandé de s'en tenir à une seule implémentation et une seule version, mais s'il n'y a pas d'autre moyen (en utilisant des fonctionnalités supplémentaires de plus de bibliothèques), la modularisation pourrait vous sauver.
Un bon exemple de modules JBoss en action est, naturellement, JBoss AS 7 / EAP 6 / WildFly 8 , pour lequel il a été principalement développé.
Exemple de définition de module:
Par rapport à OSGi, les modules JBoss sont plus simples et plus rapides. Bien qu'il manque certaines fonctionnalités, cela suffit pour la plupart des projets qui sont (principalement) sous le contrôle d'un fournisseur, et permettent un démarrage rapide époustouflant (en raison de la résolution des dépendances parallèles).
Notez qu'il y a un effort de modularisation en cours pour Java 8 , mais AFAIK qui vise principalement à modulariser le JRE lui-même, je ne sais pas s'il sera applicable aux applications.
la source
Apparemment
xerces:xml-apis:1.4.01
n'est plus dans maven central, ce qui est pourtant ce qui faitxerces:xercesImpl:2.11.0
référence.Cela fonctionne pour moi:
la source
Mon ami c'est très simple, voici un exemple:
Et si vous voulez vérifier dans le terminal (console Windows pour cet exemple) que votre arbre Maven n'a aucun problème:
la source