716 votes

Traitant de « L’enfer Xerces » en Java/Maven ?

Dans mon bureau, la simple mention du mot Xerces est suffisant pour inciter à la rage meurtrière des développeurs. Un rapide coup d'œil à l'autre Xerces questions sur de SORTE que semblent indiquer que presque tous les utilisateurs de Maven sont "touchés" par ce problème à un certain point. Malheureusement, la compréhension du problème nécessite un peu de connaissances sur l'histoire de Xerces...

L'histoire

  • Xerces est le plus largement utilisé analyseur XML dans l'écosystème Java. Presque chaque bibliothèque ou un framework écrit en Java utilise Xerces dans une certaine mesure (transitivement, si pas directement).

  • La Xerces pots inclus dans les binaires officiels sont, à ce jour, pas de version. Par exemple, la Xerces 2.11.0 mise en œuvre pot est nommé xercesImpl.jar et pas xercesImpl-2.11.0.jar.

  • La Xerces de l'équipe de ne pas utiliser Maven, ce qui signifie qu'ils ne sont pas télécharger une version officielle de Maven Central.

  • Xerces utilisé pour être publié comme un seul bocal (xerces.jar), mais a été divisé en deux pots, l'un contenant l'API (xml-apis.jar) et un contenant les implémentations de ces interfaces Api (xercesImpl.jar). De nombreux anciens Maven POMs encore déclarer une dépendance sur xerces.jar. À un certain moment dans le passé, Xerces a également été publié en xmlParserAPIs.jar, dont certains âgés de Chrysanthèmes dépendent également.

  • Les versions affectées à la xml-api et xercesImpl pots par ceux qui déploient leurs pots à Maven dépôts sont souvent différents. Par exemple, xml, api peut être donné de la version 1.3.03 et xercesImpl peut-être donné la version 2.8.0, même si les deux sont de Xerces 2.8.0. C'est parce que les gens ont souvent de la balise xml api pot avec la version du cahier des charges qu'elle met en œuvre. Il est très gentil, mais incomplète ventilation de ce ici.

  • Pour compliquer les choses, Xerces est l'analyseur XML utilisés dans l'implémentation de référence de Java API for XML Processing (JAXP), inclus dans le JRE. La mise en œuvre des classes sont reconditionnés en vertu de l' com.sun.* d'espace de noms, ce qui le rend dangereux d'accéder directement à eux, comme ils peuvent ne pas être disponibles dans certains Jre. Cependant, pas tous de la Xerces fonctionnalité est accessible via l' java.* et javax.* Api; par exemple, il n'y a pas d'API qui expose Xerces de sérialisation.

  • Ajoutant à la confusion de désordre, presque tous les conteneurs de servlet (JBoss, Jetée, Glassfish, Tomcat, etc.), navire avec Xerces dans un ou plusieurs de leurs /lib des dossiers.

Problèmes

La Résolution Des Conflits

Pour certains, ou peut-être tous -- les raisons ci-dessus, de nombreux les organisations de publier et de consommer personnalisé de Xerces dans leur Pdm. Ce n'est pas vraiment un problème si vous avez une petite application et sont uniquement à l'aide de Maven Central, mais il devient rapidement un problème pour les logiciels d'entreprise où Artifactory ou Nexus est l'utilisation de proxy plusieurs référentiels (JBoss, Hibernate, etc.): xml-apis proxied by Artifactory

Par exemple, Une organisation peut publier xml api:

<groupId>org.apache.xerces</groupId>
<artifactId>xml-apis</artifactId>
<version>2.9.1</version>

Pendant ce temps, l'organisation B pourrait publier le même pot que:

<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.3.04</version>

Bien que B jar est une version la plus basse qu'Un pot d', Maven ne sais pas qu'ils sont le même objet, parce qu'ils ont de différent groupIds. Ainsi, il ne peut pas effectuer la résolution des conflits et à la fois les pots seront inclus comme résolu dépendances:

resolved dependencies with multiple xml-apis

Chargeur De Classe De L'Enfer

Comme mentionné ci-dessus, le JRE est livré avec Xerces dans le JAXP RI. Alors qu'il serait bien de marquer tous les Xerces les dépendances Maven comme <exclusion>s ou <provided>,- la troisième partie du code dont vous dépendez peut ou peut ne pas fonctionner avec la version fournie dans JAXP du JDK que vous utilisez. En outre, vous avez la Xerces pots livrés dans votre conteneur de servlet pour composer avec. Cela vous laisse avec un certain nombre de choix: voulez-vous supprimer la servlet version et j'espère que votre conteneur s'exécute sur l'JAXP version? Est-il préférable de laisser le servlet version, et j'espère que votre application de cadres de courir sur de la servlet version? Si un ou deux des conflits non résolus décrites ci-dessus parviennent à se glisser dans votre produit (facile d'arriver dans une grande entreprise), vous allez rapidement vous trouver vous-même dans le chargeur de classe de l'enfer, vous vous demandez quelle est la version de Xerces le chargeur de classe est de choisir au moment de l'exécution et de savoir si ou non il va choisir le même pot dans Windows et Linux (probablement pas).

Des Solutions?

Nous avons essayé le marquage de tous les Xerces les dépendances Maven comme <provided> ou en tant que <exclusion>, mais c'est difficile à respecter (en particulier avec une grande équipe) étant donné que les objets ont donc beaucoup d'alias (xml, api, xerces, xercesImpl, xmlParserAPIs, etc.). En outre, notre troisième partie libs/cadres peut ne pas fonctionner sur le JAXP version ou la version fournie par un conteneur de servlet.

Comment pouvons-nous résoudre ce problème avec Maven? Nous avons à exercer un tel contrôle fin sur nos dépendances, et puis s'appuyer sur les niveaux classloading? Est-il un moyen pour exclure globalement tous les Xerces dépendances, et de la force de l'ensemble de nos cadres/libs pour utiliser le JAXP version?


Mise à JOUR: Joshua Spiewak a mis en ligne une version corrigée de la Xerces des scripts de génération de XERCESJ-1454 qui permet de télécharger sur Maven Central. Vote/regarder/contribuer à ce problème et nous allons résoudre ce problème une fois pour toutes.

107voto

Grzegorz Grzybek Points 2713

Il y a 2.11.0 Pots (et de la source Pots!) 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é:

<dependency>
    <groupId>xerces</groupId>
    <artifactId>xercesImpl</artifactId>
    <version>2.11.0</version>
</dependency>

et toutes les dépendances ont résolu des beaux - même correcte xml-apis-1.4.01!

Et ce qui est le plus important (et ce n'était pas évident dans le passé) - le POT dans Maven Central est le même POT que dans l'officiel Xerces-J-bin.2.11.0.zip de la distribution.

Je ne pouvais pas cependant trouver d' xml-schema-1.1-beta version - elle ne peut pas être un Maven classifier-ed version en raison de dépendances supplémentaires.

63voto

jtahlborn Points 32515
<p>Franchement, peu près tout ce que nous avons croisés fonctionne très bien w / la version JAXP, donc nous <em>toujours</em> exclure xml-apis et xercesImpl.</p>

42voto

Vous pouvez utiliser le maven enforcer plugin avec l'interdit de la dépendance à la règle. Cela vous permettrait d'interdire tous les alias que vous ne voulez pas et autoriser uniquement celui que vous voulez. Ces règles s'échouer le maven build de votre projet en cas de violation. En outre, si cette règle s'applique à tous les projets dans une entreprise que vous pouviez mettre la configuration du plugin dans un pom parent.

voir:

16voto

Jens Schauder Points 23468

Je pense qu'il y a une question que vous devez répondre:

Existe-t-il un xerces*.jar que tout dans votre application peut vivre avec?

Si non, vous êtes fondamentalement vissé et aurait à utiliser quelque chose comme OSGI, qui vous permet d'avoir différentes versions de la bibliothèque est chargé en même temps. Être averti que, essentiellement, il remplace le pot de problèmes de version avec chargeur de classe ...

Si il existe une version que vous pourriez faire de votre référentiel de retour cette version pour tous les types de dépendances. C'est un vilain hack et avec la même xerces mise en œuvre dans votre classpath plusieurs fois, mais mieux que d'avoir plusieurs versions différentes de xerces.

Vous pourriez exclure toute dépendance à xerces et en ajouter un à la version que vous souhaitez utiliser.

Je me demande si vous pouvez écrire une sorte de version de la résolution de la stratégie comme un plugin maven. Ce serait sans doute la plus belle solution, mais si cela est possible les besoins de recherche et de codage.

Pour la version contenue dans votre environnement d'exécution, vous devrez assurez-vous qu'il soit est supprimée depuis le classpath de l'application ou de l'application des pots prise en compte d'abord pour classloading avant le dossier lib du serveur prise en compte.

Donc pour conclure: C'est un gâchis et ça ne changera pas.

2voto

Ondra Žižka Points 8262

Ce qui permettrait, à l'exception de l'exclusion, est modulaire dépendances.

Avec un plat classloading (application autonome), ou semi-hiérarchique (JBoss as/EAP 5.x) c'était un problème.

Mais modulaire avec des cadres comme OSGi et JBoss Modules, ce n'est pas tant la douleur plus. Les bibliothèques peuvent utiliser n'importe quelle bibliothèque qu'ils veulent, indépendamment.

Bien sûr, il est toujours recommandé de s'en tenir à un seul de la mise en œuvre et la version, mais si il n'y a pas d'autre moyen (à l'aide des fonctionnalités supplémentaires de plus libs), puis la modularisation peut vous sauver.

Un bon exemple de JBoss Modules dans l'action est, naturellement, de JBoss as 7 / EAP 6 / WildFly 8, pour lequel il a été principalement développé.

Exemple de définition de module:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.jboss.msc">
    <main-class name="org.jboss.msc.Version"/>
    <properties>
        <property name="my.property" value="foo"/>
    </properties>
    <resources>
        <resource-root path="jboss-msc-1.0.1.GA.jar"/>
    </resources>
    <dependencies>
        <module name="javax.api"/>
        <module name="org.jboss.logging"/>
        <module name="org.jboss.modules"/>
        <!-- Optional deps -->
        <module name="javax.inject.api" optional="true"/>
        <module name="org.jboss.threads" optional="true"/>
    </dependencies>
</module>

En comparaison avec OSGi, JBoss Modules est plus simple et plus rapide. Alors que manque certaines fonctionnalités, il est suffisant pour la plupart des projets, qui sont (pour la plupart) sous le contrôle d'un fournisseur, et de permettre à l'étourdissement de démarrage rapide (en raison de paralelized dépendances de résolution).

Noter qu'il y a une modularisation des efforts en cours pour Java 8, mais autant que je sache, c'est principalement à modulariser le JRE lui-même, ne sachant pas si elle sera applicable pour les apps.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X