In meinem Büro reicht die bloße Erwähnung des Wortes Xerces aus, um Entwickler zu mörderischer Wut anzuregen. Ein flüchtiger Blick auf die anderen Xerces-Fragen zu SO scheint darauf hinzudeuten, dass fast alle Maven-Benutzer irgendwann von diesem Problem "berührt" werden. Leider erfordert das Verständnis des Problems ein wenig Wissen über die Geschichte von Xerces ...
Geschichte
Xerces ist der am häufigsten verwendete XML-Parser im Java-Ökosystem. Fast jede in Java geschriebene Bibliothek oder jedes in Java geschriebene Framework verwendet Xerces in irgendeiner Form (transitiv, wenn nicht direkt).
Die in den offiziellen Binärdateien enthaltenen Xerces-Gläser sind bis heute nicht versioniert. Beispielsweise wird das Implementierungsglas für Xerces 2.11.0 benannt
xercesImpl.jar
und nichtxercesImpl-2.11.0.jar
.Das Xerces-Team verwendet Maven nicht, dh es wird keine offizielle Version auf Maven Central hochgeladen .
Xerces wurde früher als einzelnes jar (
xerces.jar
) veröffentlicht, wurde jedoch in zwei Jars aufgeteilt, von denen eines die API (xml-apis.jar
) und eines die Implementierungen dieser APIs (xercesImpl.jar
) enthielt . Viele ältere Maven POMs erklären immer noch eine Abhängigkeit vonxerces.jar
. Irgendwann in der Vergangenheit wurde Xerces auch als veröffentlichtxmlParserAPIs.jar
, von dem auch einige ältere POMs abhängen.Die Versionen, die den JARs xml-apis und xercesImpl von denjenigen zugewiesen werden, die ihre Jars in Maven-Repositorys bereitstellen, sind häufig unterschiedlich. Beispielsweise könnte xml-apis die Version 1.3.03 und xercesImpl die Version 2.8.0 erhalten, obwohl beide von Xerces 2.8.0 stammen. Dies liegt daran, dass Benutzer das xml-apis-Glas häufig mit der Version der von ihm implementierten Spezifikationen versehen. Es ist eine sehr schöne, aber unvollständige Aufteilung dieses hier .
Xerces ist der XML-Parser, der in der Referenzimplementierung der in der JRE enthaltenen Java-API für die XML-Verarbeitung (JAXP) verwendet wird. Die Implementierungsklassen werden unter dem
com.sun.*
Namespace neu gepackt, was den direkten Zugriff auf sie gefährlich macht, da sie in einigen JREs möglicherweise nicht verfügbar sind. Es wird jedoch nicht die gesamte Xerces-Funktionalität über die APIsjava.*
undjavax.*
bereitgestellt. Beispielsweise gibt es keine API, die die Xerces-Serialisierung verfügbar macht.Zusätzlich zu dem verwirrenden Durcheinander werden fast alle Servlet-Container (JBoss, Jetty, Glassfish, Tomcat usw.) mit Xerces in einem oder mehreren ihrer
/lib
Ordner ausgeliefert.
Probleme
Konfliktlösung
Aus einigen - oder vielleicht allen - der oben genannten Gründe veröffentlichen und verwenden viele Unternehmen benutzerdefinierte Builds von Xerces in ihren POMs. Dies ist kein wirkliches Problem, wenn Sie eine kleine Anwendung haben und nur Maven Central verwenden, aber es wird schnell zu einem Problem für Unternehmenssoftware, bei der Artifactory oder Nexus mehrere Repositorys (JBoss, Hibernate usw.) als Proxy verwenden:
Beispielsweise könnte Organisation A Folgendes veröffentlichen xml-apis
:
<groupId>org.apache.xerces</groupId>
<artifactId>xml-apis</artifactId>
<version>2.9.1</version>
In der Zwischenzeit könnte Organisation B dasselbe veröffentlichen jar
wie:
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.3.04</version>
Obwohl B jar
eine niedrigere Version als A ist jar
, weiß Maven nicht, dass sie dasselbe Artefakt sind, weil sie unterschiedliche
groupId
s haben. Daher kann keine Konfliktlösung durchgeführt werden, und beide
jar
s werden als gelöste Abhängigkeiten aufgenommen:
Klassenlader Hölle
Wie oben erwähnt, wird die JRE mit Xerces im JAXP RI ausgeliefert. Es wäre zwar schön, alle Xerces Maven-Abhängigkeiten als <exclusion>
s oder als zu markieren<provided>
Der Code eines Drittanbieters, von dem Sie abhängig sind, funktioniert möglicherweise nicht mit der in JAXP des von Ihnen verwendeten JDK bereitgestellten Version. Außerdem haben Sie die Xerces-Gläser in Ihrem Servlet-Container, um damit fertig zu werden. Sie haben also eine Reihe von Möglichkeiten: Löschen Sie die Servlet-Version und hoffen, dass Ihr Container auf der JAXP-Version ausgeführt wird? Ist es besser, die Servlet-Version zu verlassen und zu hoffen, dass Ihre Anwendungsframeworks auf der Servlet-Version ausgeführt werden? Wenn es einem oder zwei der oben beschriebenen ungelösten Konflikte gelingt, in Ihr Produkt einzudringen (was in einer großen Organisation leicht vorkommt), befinden Sie sich schnell in der Hölle der Klassenlader und fragen sich, welche Version von Xerces der Klassenlader zur Laufzeit auswählt und ob dies der Fall ist oder nicht wird das gleiche Glas in Windows und Linux auswählen (wahrscheinlich nicht).
Lösungen?
Wir haben versucht , alle Xerces Maven Abhängigkeiten als Markierung <provided>
oder als ein <exclusion>
, aber das ist schwer durchzusetzen (vor allem mit einem großen Team) gegeben , dass die Artefakte haben so viele Aliase ( xml-apis
, xerces
, xercesImpl
, xmlParserAPIs
, etc.). Darüber hinaus können unsere Bibliotheken / Frameworks von Drittanbietern möglicherweise nicht auf der JAXP-Version oder der von einem Servlet-Container bereitgestellten Version ausgeführt werden.
Wie können wir dieses Problem am besten mit Maven lösen? Müssen wir unsere Abhängigkeiten so genau kontrollieren und uns dann auf das gestufte Laden von Klassen verlassen? Gibt es eine Möglichkeit, alle Xerces-Abhängigkeiten global auszuschließen und alle unsere Frameworks / Bibliotheken zur Verwendung der JAXP-Version zu zwingen?
UPDATE : Joshua Spiewak hat eine gepatchte Version der Xerces-Build-Skripte auf XERCESJ-1454 hochgeladen , die das Hochladen auf Maven Central ermöglicht. Stimmen Sie ab / schauen Sie zu / tragen Sie zu diesem Problem bei und lassen Sie uns dieses Problem ein für alle Mal beheben.
quelle
Antworten:
Seit dem 20. Februar 2013 gibt es in Maven Central 2.11.0 JARs (und Quell-JARs!) Von Xerces! Siehe Xerces in Maven Central . Ich frage mich, warum sie https://issues.apache.org/jira/browse/XERCESJ-1454 nicht gelöst haben ...
Ich habe verwendet:
und alle Abhängigkeiten haben sich gut aufgelöst - sogar richtig
xml-apis-1.4.01
!Und was am wichtigsten ist (und was in der Vergangenheit nicht offensichtlich war) - die JAR in Maven Central ist dieselbe JAR wie in der offiziellen
Xerces-J-bin.2.11.0.zip
Distribution .Ich konnte jedoch keine
xml-schema-1.1-beta
Version finden - es kannclassifier
aufgrund zusätzlicher Abhängigkeiten keine Maven- Version sein.quelle
xml-apis:xml-apis:1.4.01
es neuer ist alsxml-apis:xml-apis:2.0.2
?? siehe search.maven.org/…Ehrlich gesagt, so ziemlich alles , dass wir funktionieren gut w / die JAXP Version begegnet sind, so wir immer ausschließen
xml-apis
undxercesImpl
.quelle
java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal
zur Laufzeit geworfen .Sie können das Maven Enforcer-Plugin mit der Regel für gesperrte Abhängigkeiten verwenden. Auf diese Weise können Sie alle Aliase sperren, die Sie nicht möchten, und nur den Aliase zulassen, den Sie möchten. Diese Regeln schlagen beim Erstellen des Maven-Builds Ihres Projekts fehl. Wenn diese Regel für alle Projekte in einem Unternehmen gilt, können Sie die Plugin-Konfiguration in ein übergeordnetes Unternehmen einfügen.
sehen:
quelle
Ich weiß, dass dies die Frage nicht genau beantwortet, aber für Leute, die von Google kommen und Gradle für ihr Abhängigkeitsmanagement verwenden:
Ich habe es geschafft, alle xerces / Java8-Probleme mit Gradle wie folgt zu beseitigen:
quelle
Ich denke, es gibt eine Frage, die Sie beantworten müssen:
Gibt es eine xerces * .jar, mit der alles in Ihrer Anwendung leben kann?
Wenn nicht, sind Sie im Grunde genommen geschraubt und müssten so etwas wie OSGI verwenden, wodurch Sie verschiedene Versionen einer Bibliothek gleichzeitig laden können. Seien Sie gewarnt, dass es im Grunde JAR-Versionsprobleme durch Classloader-Probleme ersetzt ...
Wenn es eine solche Version gibt, können Sie Ihr Repository veranlassen, diese Version für alle Arten von Abhängigkeiten zurückzugeben. Es ist ein hässlicher Hack und würde mehrmals dieselbe xerces-Implementierung in Ihrem Klassenpfad haben, aber besser als mehrere verschiedene Versionen von xerces.
Sie können jede Abhängigkeit von xerces ausschließen und eine zu der Version hinzufügen, die Sie verwenden möchten.
Ich frage mich, ob Sie eine Art Versionsauflösungsstrategie als Plugin für Maven schreiben können. Dies wäre wahrscheinlich die schönste Lösung, erfordert aber, wenn überhaupt, einige Nachforschungen und Codierungen.
Für die in Ihrer Laufzeitumgebung enthaltene Version müssen Sie sicherstellen, dass sie entweder aus dem Anwendungsklassenpfad entfernt wird oder die Anwendungsgläser zuerst für das Laden der Klasse berücksichtigt werden, bevor der lib-Ordner des Servers berücksichtigt wird.
Um es zusammenzufassen: Es ist ein Chaos und das wird sich nicht ändern.
quelle
Es gibt eine andere Option, die hier nicht untersucht wurde: Deklarieren von Xerces-Abhängigkeiten in Maven als optional :
Im Grunde bedeutet dies, dass alle abhängigen Personen gezwungen werden, ihre Version von Xerces zu deklarieren, da sonst ihr Projekt nicht kompiliert wird. Wenn sie diese Abhängigkeit überschreiben möchten, können sie dies gerne tun, aber dann besitzen sie das potenzielle Problem.
Dies schafft einen starken Anreiz für nachgelagerte Projekte:
Nicht alle Entwickler verfolgen neu eingeführte Abhängigkeiten (z
mvn dependency:tree
. B. mit ). Dieser Ansatz wird sie sofort auf die Angelegenheit aufmerksam machen.In unserer Organisation funktioniert das ganz gut. Vor seiner Einführung lebten wir in derselben Hölle, die das OP beschreibt.
quelle
Jedes Maven-Projekt sollte abhängig von xerces aufhören, wahrscheinlich nicht wirklich. XML-APIs und ein Impl sind seit 1.4 Teil von Java. Es ist nicht erforderlich, sich auf Xerces oder XML-APIs zu verlassen. Dies bedeutet, dass Sie von Java oder Swing abhängig sind. Dies ist implizit.
Wenn ich Chef eines Maven-Repos wäre, würde ich ein Skript schreiben, um xerces-Abhängigkeiten rekursiv zu entfernen, und ein Read-Me schreiben, das besagt, dass für dieses Repo Java 1.4 erforderlich ist.
Alles, was tatsächlich kaputt geht, weil es direkt über org.apache-Importe auf Xerces verweist, benötigt einen Code-Fix, um es auf Java 1.4-Ebene (und seit 2002) oder eine Lösung auf JVM-Ebene über indossierte Bibliotheken zu bringen, nicht in Maven.
quelle
Sie sollten zuerst debuggen, um Ihre XML-Hölle zu identifizieren. Meiner Meinung nach ist der erste Schritt das Hinzufügen
zur Kommandozeile. Wenn dies funktioniert, schließen Sie Bibliotheken aus. Wenn nicht, dann hinzufügen
zur Kommandozeile.
quelle
Was helfen würde, außer auszuschließen, sind modulare Abhängigkeiten.
Bei einer flachen Klassenladung (eigenständige App) oder halbhierarchisch (JBoss AS / EAP 5.x) war dies ein Problem.
Bei modularen Frameworks wie OSGi und JBoss Modules ist dies jedoch nicht mehr so schmerzhaft. Die Bibliotheken können unabhängig voneinander die gewünschte Bibliothek verwenden.
Natürlich ist es immer noch am empfehlenswertesten, sich nur an eine einzige Implementierung und Version zu halten. Wenn es jedoch keinen anderen Weg gibt (zusätzliche Funktionen aus mehr Bibliotheken verwenden), können Sie durch Modularisierung sparen.
Ein gutes Beispiel für JBoss-Module in Aktion ist natürlich JBoss AS 7 / EAP 6 / WildFly 8 , für das es hauptsächlich entwickelt wurde.
Beispiel für eine Moduldefinition:
Im Vergleich zu OSGi sind JBoss-Module einfacher und schneller. Obwohl bestimmte Funktionen fehlen, ist dies für die meisten Projekte ausreichend, die (meistens) von einem Anbieter kontrolliert werden, und ermöglicht einen erstaunlich schnellen Start (aufgrund der Auflösung von parallelen Abhängigkeiten).
Beachten Sie, dass für Java 8 Modularisierungsbemühungen im Gange sind, AFAIK jedoch hauptsächlich die JRE selbst modularisiert und nicht sicher ist, ob sie für Apps anwendbar ist.
quelle
Anscheinend
xerces:xml-apis:1.4.01
ist nicht mehr in Maven Central, was jedoch daraufxerces:xercesImpl:2.11.0
verweist.Das funktioniert bei mir:
quelle
Mein Freund, das ist sehr einfach, hier ein Beispiel:
Und wenn Sie im Terminal (Windows-Konsole für dieses Beispiel) überprüfen möchten, ob Ihr Maven-Baum keine Probleme hat:
quelle