Maven: comment remplacer la dépendance ajoutée par une bibliothèque

116

Voici mon problème générique:

Mon projet P dépend de A qui dépend de B qui dépend de C qui dépend de la version 1.0.1 de D.

Il y a un problème avec la version 1.0.1 de D et je veux forcer l'utilisation d'un autre module. Je ne sais pas comment déclarer cela dans les POM de mon projet car je n'ai pas ajouté directement de dépendance à D. C'est C qui a déclaré la dépendance à D.

Important: dans ce cas, non seulement la version est modifiée, mais également le groupe et l'artefact. Il ne s'agit donc pas simplement de remplacer la version de la dépendance, mais plutôt d'exclure un module et d'en inclure un autre.

Dans le cas concret, D est StAX dont la 1.0.1 a un bug . Selon les notes du bogue, "les problèmes ont été résolus en remplaçant stax-api-1.0.1 (maven GroupId = stax) par stax-api-1.0-2 (maven GroupId = javax.xml.stream)" donc je J'essaye juste ça.

Ainsi, D = stax: stax-api: jar: 1.0.1 et C = org.apache.xmlbeans: xmlbeans: jar: 2.3.0

J'utilise maven 2.0.9 au cas où cela importerait.

Sortie de la dépendance mvn: tree "

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

Dans le POM de mon projet, j'ai la dépendance suivante sur "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>

Merci d'avance.

wishihadabettername
la source

Réponses:

100

Spécifiez simplement la version dans votre pom actuel. La version spécifiée ici remplacera l'autre.

Forcer une version
Une version sera toujours honorée si elle est déclarée dans le POM actuel avec une version particulière - cependant, il convient de noter que cela affectera également d'autres poms en aval si elle dépend elle-même de l'utilisation de dépendances transitives.


Ressources :

Colin Hebert
la source
5
je ne sais pas comment spécifier la version car je ne déclare pas de dépendance sur D. De plus, le premier lien que vous avez fourni a "Ce document décrit le reste des exigences pour la gestion des dépendances qui n'ont PAS encore été implémentées pour Maven 2.0, en particulier en ce qui concerne les dépendances transitives. " au sommet.
wishihadabettername
@wishihadabettername, Comme indiqué dans l'autre document: "Vous pouvez explicitement ajouter une dépendance à D 2.0 en A pour forcer l'utilisation de D 2.0"
Colin Hebert
1
Vous dupliquez en fait la même entrée <dependency> dans votre propre pom. Dans votre dépendance, spécifiez une <version> que vous souhaitez. Cela remplacera toute version utilisée par les dépendances "plus profondes".
Keith Tyler
27

Sinon, vous pouvez simplement exclure la dépendance que vous ne souhaitez pas. STAX est inclus dans JDK 1.6, donc si vous utilisez 1.6, vous pouvez simplement l'exclure complètement.

Mon exemple ci-dessous est légèrement faux pour vous - vous n'avez besoin que d'une des deux exclusions, mais je ne sais pas trop laquelle. Il existe d'autres versions de Stax flottant, dans mon exemple ci-dessous, j'importais A qui importait B qui importait C & D qui chacun (à travers encore plus de dépendances transitives) importait différentes versions de Stax. Donc, dans ma dépendance à «A», j'ai exclu les deux versions de 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>
Écossais
la source
1
Il est nécessaire de noter que cette dépendance transitive peut être utilisée et que l'exclusion peut provoquer un échec de construction si elle est nécessaire.
Bernhard Colby
Si vous utilisez un JDK moderne (c'est-à-dire 1.6+) et que vous avez besoin de la version beaucoup plus ancienne de stax incluse via une dépendance transitive, vous allez probablement rencontrer toutes sortes de terribles problèmes de chargeur de classe d'exécution. Mon conseil: utilisez celui du JDK. Si vous obtenez un "échec de construction", vous vous appuyez sur une ancienne API d'une certaine forme qui devrait être mise à niveau. Ou: ramenez votre JDK à la version 1.5. Bonne chance avec ça.
scot le
11

Ce que vous mettez dans la </dependencies>balise du pom racine sera inclus par tous les modules enfants du pom racine. Si tous vos modules utilisent cette dépendance, c'est la voie à suivre.

Cependant, si seulement 3 sur 10 de vos modules enfants utilisent une dépendance, vous ne voulez pas que cette dépendance soit incluse dans tous vos modules enfants. Dans ce cas, vous pouvez simplement placer la dépendance dans le fichier </dependencyManagement>. Cela garantira que tout module enfant qui a besoin de la dépendance doit le déclarer dans son propre fichier pom, mais il utilisera la même version de cette dépendance que celle spécifiée dans votre </dependencyManagement>balise.

Vous pouvez également utiliser le </dependencyManagement>pour modifier la version utilisée dans les dépendances transitives, car la version déclarée dans le fichier pom le plus haut est celle qui sera utilisée. Cela peut être utile si votre projet A comprend un projet externe B v1.0 qui inclut un autre projet externe C v1.0. Parfois, il arrive qu'une faille de sécurité soit trouvée dans le projet C v1.0 qui est corrigé en v1.1, mais les développeurs de B mettent du temps à mettre à jour leur projet pour utiliser la v1.1 de C.Dans ce cas, vous pouvez simplement déclarer une dépendance sur C v1.1 dans la racine de votre projet pom à l'intérieur `, et tout ira bien (en supposant que B v1.0 sera toujours capable de compiler avec C v1.1).

Kent Munthe Caspersen
la source
10

J'ai également eu du mal à annuler une dépendance dans une bibliothèque tierce. J'ai utilisé l'approche de scot avec l'exclusion, mais j'ai également ajouté la dépendance avec la version la plus récente dans le pom. (J'ai utilisé Maven 3.3.3)

Donc, pour l'exemple stAX, cela ressemblerait à ceci:

<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
la source
1

La réponse acceptée est correcte, mais j'aimerais ajouter mes deux cents. J'ai rencontré un problème où j'avais un projet A qui avait un projet B comme dépendance. Les deux projets utilisent slf4j mais le projet B utilise log4j tandis que le projet A utilise le retour de session. Le projet B utilise slf4j 1.6.1, tandis que le projet A utilise slf4j 1.7.5 (en raison de la dépendance logback 1.2.3 déjà incluse).

Le problème: le projet A n'a pas pu trouver une fonction qui existe sur slf4j 1.7.5, après avoir vérifié l'onglet hiérarchie des dépendances d'eclipe, j'ai découvert que pendant la construction, il utilisait slf4j 1.6.1 du projet B, au lieu d'utiliser slf4j 1.7.5 de logback .

J'ai résolu le problème en changeant l'ordre des dépendances sur le projet A pom, lorsque j'ai déplacé l'entrée du projet B sous l'entrée de connexion, maven a commencé à construire le projet en utilisant slf4j 1.7.5.

Edit: Ajout de la dépendance slf4j 1.7.5 avant que la dépendance du projet B ne fonctionne également.

Fernando Maia
la source