Maven: jak zastąpić zależność dodaną przez bibliotekę

116

Oto mój ogólny problem:

Mój projekt P zależy od A, który zależy od B, który zależy od C, który zależy od wersji 1.0.1 D.

Wystąpił problem z wersją 1.0.1 D i chcę wymusić użycie innego modułu. Nie wiem, jak to zadeklarować w plikach POM mojego projektu, ponieważ nie dodałem bezpośrednio zależności od D. To C zadeklarował zależność od D.

Ważne: w tym przypadku zmienia się nie tylko wersja, ale także grupa i artefakt. Więc nie chodzi tylko o nadpisanie wersji zależności, ale raczej o wykluczenie modułu i dołączenie innego.

W konkretnym przypadku D to StAX, którego 1.0.1 ma błąd . Zgodnie z uwagami w błędzie „problemy zostały rozwiązane poprzez zastąpienie stax-api-1.0.1 (maven GroupId = stax) przez stax-api-1.0-2 (maven GroupId = javax.xml.stream)”, więc ja Właśnie tego próbuję.

Zatem D = stax: stax-api: jar: 1.0.1 i C = org.apache.xmlbeans: xmlbeans: jar: 2.3.0

Używam maven 2.0.9 na wypadek, gdyby miało to znaczenie.

Wynik zależności mvn: drzewo "

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

W POM mojego projektu mam następującą zależność od „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>

Z góry dziękuję.

Wishihadabettername
źródło

Odpowiedzi:

101

Po prostu określ wersję w aktualnym pliku pom. Wersja określona tutaj zastąpi inne.

Wymuszanie wersji
Wersja będzie zawsze honorowana, jeśli zostanie zadeklarowana w aktualnym POM z konkretną wersją - należy jednak zauważyć, że wpłynie to również na inne poms w dalszej części, jeśli sama jest zależna od użycia zależności przechodnich.


Zasoby :

Colin Hebert
źródło
5
nie jest jasne, w jaki sposób mogę określić wersję, ponieważ nie deklaruję zależności od D. Ponadto, pierwszy podany link ma „Ten dokument opisuje pozostałe wymagania dotyczące zarządzania zależnościami, które NIE zostały jeszcze zaimplementowane w Maven 2.0, szczególnie w odniesieniu do zależności przechodnich. " na górze.
Wishihadabettername
@wishihadabettername, Jak powiedziano w innym dokumencie: „Możesz jawnie dodać zależność do D 2.0 w A, aby wymusić użycie D 2.0”
Colin Hebert
1
W rzeczywistości powielałeś ten sam wpis <dependency> w swoim własnym pom. W swojej zależności określ odpowiednią <wersję>. To przesłoni każdą wersję używaną przez „głębsze” zależności.
Keith Tyler,
27

Alternatywnie możesz po prostu wykluczyć zależność, której nie chcesz. STAX jest zawarty w JDK 1.6, więc jeśli używasz 1.6, możesz go całkowicie wykluczyć.

Mój poniższy przykład jest dla Ciebie trochę błędny - potrzebujesz tylko jednego z dwóch wyjątków, ale nie jestem pewien, które z nich. Istnieją inne wersje Staxa, w moim przykładzie poniżej importowałem A, który zaimportował B, który zaimportował C & D, z których każdy (przez jeszcze więcej zależności przechodnich) importował różne wersje Stax. Więc w mojej zależności od „A” wykluczyłem obie wersje Stax.

<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>
Szkot
źródło
1
Należy zauważyć, że ta zależność przechodnia może być używana, a wykluczenie może spowodować awarię kompilacji, jeśli jest to konieczne.
Bernhard Colby
Jeśli używasz nowoczesnego JDK (tj. 1.6+) i potrzebujesz dużo starszej wersji stax zawartej poprzez zależność przechodnią, prawdopodobnie napotkasz różnego rodzaju straszne problemy z ładowaniem klas w czasie wykonywania. Moja rada: użyj tego z JDK. Jeśli dostaniesz „błąd kompilacji”, polegasz na starym API w jakiejś formie, które powinno zostać zaktualizowane. Lub: przywróć JDK do wersji 1.5. Powodzenia z tym.
scot
11

To, co umieścisz w </dependencies>tagu głównego pom, zostanie uwzględnione we wszystkich modułach potomnych głównego pom. Jeśli wszystkie twoje moduły używają tej zależności, to jest droga do zrobienia.

Jeśli jednak tylko 3 z 10 modułów podrzędnych używają jakiejś zależności, nie chcesz, aby ta zależność była uwzględniona we wszystkich modułach podrzędnych. W takim przypadku możesz po prostu umieścić zależność wewnątrz </dependencyManagement>. Zapewni to, że każdy moduł potomny, który potrzebuje zależności, musi zadeklarować ją we własnym pliku pom, ale użyje tej samej wersji tej zależności, co określono w </dependencyManagement>tagu.

Możesz również użyć </dependencyManagement>do zmodyfikowania wersji używanej w zależnościach przechodnich, ponieważ wersja zadeklarowana w najwyższym pliku pom jest tą, która będzie używana. Może to być przydatne, jeśli projekt A zawiera projekt zewnętrzny B w wersji 1.0, który zawiera inny projekt zewnętrzny C w wersji 1.0. Czasami zdarza się, że w projekcie C v1.0 znaleziono naruszenie bezpieczeństwa, które jest poprawiane w wersji 1.1, ale twórcy B powoli aktualizują swój projekt, aby używał wersji 1.1 z C. W takim przypadku możesz po prostu zadeklarować zależność od C v1.1 w głównym pom w twoim projekcie wewnątrz `i wszystko będzie dobrze (zakładając, że B v1.0 nadal będzie w stanie skompilować się z C v1.1).

Kent Munthe Caspersen
źródło
10

Miałem również problem z zastąpieniem zależności w bibliotece innej firmy. Użyłem podejścia scota z wykluczeniem, ale dodałem również zależność z nowszą wersją w pom. (Użyłem Maven 3.3.3)

Więc dla przykładu stAX wyglądałoby to tak:

<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
źródło
1

Przyjęta odpowiedź jest prawidłowa, ale chciałbym dodać moje dwa centy. Napotkałem problem polegający na tym, że miałem projekt A z projektem B jako zależnością. Oba projekty używają slf4j, ale projekt B używa log4j, podczas gdy projekt A używa logback. Projekt B używa slf4j 1.6.1, podczas gdy projekt A używa slf4j 1.7.5 (ze względu na już uwzględnioną zależność logback 1.2.3).

Problem: Projekt A nie mógł znaleźć funkcji, która istnieje w slf4j 1.7.5, po sprawdzeniu zakładki hierarchii zależności eclipe dowiedziałem się, że podczas kompilacji używa slf4j 1.6.1 z projektu B, zamiast używać slf4j 1.7.5 logbacka .

Rozwiązałem problem, zmieniając kolejność zależności w projekcie A pom, kiedy przeniosłem wpis projektu B poniżej wpisu logback, a następnie maven zaczął budować projekt przy użyciu slf4j 1.7.5.

Edycja: dodanie zależności slf4j 1.7.5 przed działaniem zależności projektu B.

Fernando Maia
źródło