Maven: So überschreiben Sie die von einer Bibliothek hinzugefügte Abhängigkeit

116

Hier ist mein allgemeines Problem:

Mein Projekt P hängt von A ab, was von B abhängt, was von C abhängt, was von Version 1.0.1 von D abhängt.

Es gibt ein Problem mit Version 1.0.1 von D und ich möchte die Verwendung eines anderen Moduls erzwingen. Ich weiß nicht, wie ich dies in den POMs meines Projekts deklarieren soll, da ich keine direkte Abhängigkeit von D hinzugefügt habe. Es ist C, das die Abhängigkeit von D erklärt.

Wichtig: In diesem Fall wird nicht nur die Version geändert, sondern auch die Gruppe und das Artefakt. Es geht also nicht nur darum, die Version der Abhängigkeit zu überschreiben, sondern ein Modul auszuschließen und ein anderes einzuschließen.

Im konkreten Fall ist D StAX, dessen 1.0.1 einen Fehler aufweist . Gemäß den Anmerkungen im Fehler "wurden die Probleme gelöst, indem stax-api-1.0.1 (maven GroupId = stax) durch stax-api-1.0-2 (maven GroupId = javax.xml.stream) ersetzt wurde", also I. Ich versuche genau das.

Somit ist D = stax: stax-api: jar: 1.0.1 und C = org.apache.xmlbeans: xmlbeans: jar: 2.3.0

Ich benutze Maven 2.0.9, falls es darauf ankommt.

Ausgabe der MVN-Abhängigkeit: Baum "

mvn dependency:tree
[..snip..]
[INFO] +- org.apache.poi:poi-ooxml:jar:3.6:compile
[INFO] |  +- org.apache.poi:poi-ooxml-schemas:jar:3.6:compile
[INFO] |  |  +- org.apache.xmlbeans:xmlbeans:jar:2.3.0:compile
[INFO] |  |  |  \- stax:stax-api:jar:1.0.1:compile

Im POM meines Projekts habe ich die folgende Abhängigkeit von "A":

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.6</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.6</version>
</dependency>

Danke im Voraus.

Wishihadabettername
quelle

Antworten:

100

Geben Sie einfach die Version in Ihrem aktuellen POM an. Die hier angegebene Version überschreibt andere.

Erzwingen einer Version
Eine Version wird immer berücksichtigt, wenn sie im aktuellen POM mit einer bestimmten Version deklariert ist. Es sollte jedoch beachtet werden, dass dies auch andere Poms im nachgelagerten Bereich betrifft, wenn sie selbst von der Verwendung transitiver Abhängigkeiten abhängig ist.


Ressourcen:

Colin Hebert
quelle
5
Es ist nicht klar, wie ich die Version angeben kann, da ich keine Abhängigkeit von D deklariere. Außerdem lautet der erste von Ihnen angegebene Link "Dieses Dokument beschreibt die restlichen Anforderungen für das Abhängigkeitsmanagement, die für Maven 2.0 noch NICHT implementiert wurden." insbesondere in Bezug auf transitive Abhängigkeiten. " oben.
Wishihadabettername
@wishihadabettername, Wie im anderen Dokument gesagt: "Sie könnten explizit eine Abhängigkeit zu D 2.0 in A hinzufügen, um die Verwendung von D 2.0 zu erzwingen"
Colin Hebert
1
Sie duplizieren tatsächlich denselben <dependency> -Eintrag in Ihrem eigenen pom. Geben Sie in Ihrer Abhängigkeit eine gewünschte <Version> an. Dadurch wird jede Version überschrieben, die von "tieferen" Abhängigkeiten verwendet wird.
Keith Tyler
27

Alternativ können Sie einfach die Abhängigkeit ausschließen, die Sie nicht möchten. STAX ist in JDK 1.6 enthalten. Wenn Sie also 1.6 verwenden, können Sie es einfach vollständig ausschließen.

Mein Beispiel unten ist etwas falsch für Sie - Sie brauchen nur einen der beiden Ausschlüsse, aber ich bin mir nicht ganz sicher, welcher. Es gibt andere Versionen von Stax, in meinem Beispiel unten habe ich A importiert, das B importiert hat, das C & D importiert hat, die jeweils (durch noch transitivere Abhängigkeiten) unterschiedliche Versionen von Stax importiert haben. In meiner Abhängigkeit von 'A' habe ich beide Versionen von Stax ausgeschlossen.

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>
Schotte
quelle
1
Es ist zu beachten, dass diese transitive Abhängigkeit verwendet werden kann und das Ausschließen bei Bedarf zu einem Build-Fehler führen kann.
Bernhard Colby
Wenn Sie ein modernes JDK (dh 1.6+) verwenden und die viel ältere Version von stax benötigen, die über eine transitive Abhängigkeit enthalten ist, werden Sie wahrscheinlich auf alle möglichen schrecklichen Probleme beim Laden von Laufzeitklassen stoßen. Mein Rat: Verwenden Sie die im JDK. Wenn Sie einen "Build-Fehler" erhalten, verlassen Sie sich auf eine alte API in irgendeiner Form, die aktualisiert werden sollte. Oder: Setzen Sie Ihr JDK auf 1,5 zurück. Viel Glück damit.
Scot
10

Ich hatte auch Probleme, eine Abhängigkeit in einer Bibliothek eines Drittanbieters zu überschreiben. Ich habe den Ansatz von scot mit dem Ausschluss verwendet, aber ich habe auch die Abhängigkeit mit der neueren Version im pom hinzugefügt. (Ich habe Maven 3.3.3 verwendet)

Für das stAX-Beispiel würde es also so aussehen:

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>

<dependency>
    <groupId>javax.xml.stream</groupId>
    <artifactId>stax-api</artifactId>
    <version>1.0-2</version>
</dependency>
Patrick Koorevaar
quelle
10

Was Sie in das </dependencies>Tag des Root-Poms einfügen, wird von allen untergeordneten Modulen des Root-Poms eingeschlossen. Wenn alle Ihre Module diese Abhängigkeit verwenden, ist dies der richtige Weg.

Wenn jedoch nur 3 von 10 Ihrer untergeordneten Module eine Abhängigkeit verwenden, möchten Sie nicht, dass diese Abhängigkeit in allen untergeordneten Modulen enthalten ist. In diesem Fall können Sie die Abhängigkeit einfach in das Feld einfügen </dependencyManagement>. Dadurch wird sichergestellt, dass jedes untergeordnete Modul, das die Abhängigkeit benötigt, diese in seiner eigenen POM-Datei deklarieren muss. Es wird jedoch dieselbe Version dieser Abhängigkeit verwendet, die in Ihrem </dependencyManagement>Tag angegeben ist.

Sie können die auch verwenden </dependencyManagement>, um die in transitiven Abhängigkeiten verwendete Version zu ändern, da die in der obersten POM-Datei deklarierte Version verwendet wird. Dies kann nützlich sein, wenn Ihr Projekt A ein externes Projekt B v1.0 enthält, das ein anderes externes Projekt C v1.0 enthält. Manchmal kommt es vor, dass in Projekt C v1.0 eine Sicherheitsverletzung gefunden wird, die in v1.1 korrigiert wurde. Die Entwickler von B aktualisieren ihr Projekt jedoch nur langsam, um v1.1 von C zu verwenden. In diesem Fall können Sie dies einfach deklarieren eine Abhängigkeit von C v1.1 im Root-Pom Ihres Projekts in `, und alles wird gut (vorausgesetzt, B v1.0 kann weiterhin mit C v1.1 kompiliert werden).

Kent Munthe Caspersen
quelle
1

Die akzeptierte Antwort ist richtig, aber ich möchte meine zwei Cent hinzufügen. Ich bin auf ein Problem gestoßen, bei dem ich ein Projekt A hatte, das ein Projekt B als Abhängigkeit hatte. Beide Projekte verwenden slf4j, aber Projekt B verwendet log4j, während Projekt A logback verwendet. Projekt B verwendet slf4j 1.6.1, während Projekt A slf4j 1.7.5 verwendet (aufgrund der bereits enthaltenen Abhängigkeit von Logback 1.2.3).

Das Problem: Projekt A konnte keine Funktion finden, die in slf4j 1.7.5 vorhanden ist. Nachdem ich die Registerkarte "Abhängigkeitshierarchie" von eclipe überprüft hatte, stellte ich fest, dass während der Erstellung slf4j 1.6.1 aus Projekt B anstelle von slf4j 1.7.5 von logback verwendet wurde .

Ich habe das Problem gelöst, indem ich die Reihenfolge der Abhängigkeiten von Projekt A pom geändert habe. Als ich den Eintrag für Projekt B unter den Logback-Eintrag verschoben habe, hat maven begonnen, das Projekt mit slf4j 1.7.5 zu erstellen.

Bearbeiten: Hinzufügen der Abhängigkeit slf4j 1.7.5, bevor die Abhängigkeit von Projekt B ebenfalls funktioniert hat.

Fernando Maia
quelle