web-dev-qa-db-fra.com

Résolution des problèmes de convergence des dépendances Maven

J'utilise le plug-in maven -forcer pour vérifier les problèmes de convergence des dépendances. Une sortie typique serait:

[WARNING] Rule 1: org.Apache.maven.plugins.enforcer.DependencyConvergence failed 
  with message:
Failed while enforcing releasability the error(s) are [
Dependency convergence error for junit:junit:3.8.1 paths to dependency are:
+-foo:bar:1.0-SNAPSHOT
  +-ca.juliusdavies:not-yet-commons-ssl:0.3.9
    +-commons-httpclient:commons-httpclient:3.0
      +-junit:junit:3.8.1
and
+-foo:bar:1.0-SNAPSHOT
  +-junit:junit:4.11
]

En voyant ce message, je le "résoudrais" normalement en excluant la dépendance transitive, par ex.

<dependency>
  <groupId>ca.juliusdavies</groupId>
  <artifactId>not-yet-commons-ssl</artifactId>
  <version>0.3.9</version>
  <exclusions>
    <!-- This artifact links to another artifact which stupidly includes 
      junit in compile scope -->
    <exclusion>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
    </exclusion>
  </exclusions>
</dependency>

J'aimerais comprendre si c'est vraiment un correctif et les risques impliqués dans l'exclusion des bibliothèques de cette façon. Comme je le vois:

  • Le "correctif" est normalement sûr, à condition que je choisisse d'utiliser la version la plus récente. Cela dépend des auteurs de la bibliothèque qui maintiennent la compatibilité descendante.

  • Il n'y a généralement aucun impact sur la construction de Maven (puisque la définition la plus proche l'emporte), cependant en excluant la dépendance, je dis à Maven que je connais ce problème et apaisant ainsi le plugin maven -forcer.

Mes pensées sont-elles correctes et existe-t-il une autre façon de gérer ce problème? Je suis intéressé par les réponses qui se concentrent sur le cas général - je me rends compte que l'exemple junit ci-dessus est un peu étrange.

36
Duncan Jones

Nous convenons tous que JUnit ne doit jamais être défini sur une autre étendue que test. De manière générale, je ne pense pas non plus qu'il existe une autre solution que l'exclusion de la dépendance indésirable, nous sommes donc tous d'accord pour dire que vous avez raison de le faire.

N CAS SIMPLE:

Comme le dit Andreas Krueger, il peut y avoir un risque avec les versions (je l'ai effectivement rencontré). Disons que les dépendances du projet sont les suivantes:

+-foo:bar:1.0-SNAPSHOT
  +-group1:projectA:2.0
     +-group2:projectB:3.8.1
  +-group2:projectB:4.11

Notez que ce n'est qu'une simple simplification de votre cas. En voyant cet arbre de dépendances, vous excluriez la dépendance projectB donnée par projectA:

<dependency>
  <groupId>group1</groupId>
  <artifactId>projectA</artifactId>
  <version>2.0</version>
  <exclusions>
    <exclusion>
      <groupId>group2</groupId>
      <artifactId>projectB</artifactId>
    </exclusion>
  </exclusions>
</dependency>

Après avoir empaqueté le projet avec maven, la dépendance restante serait group2-someProjectB-4.11.jar, version 4.11 et non 3.8.1. Tout irait bien et le projet se déroulerait sans aucun problème.

Puis, un peu après, disons que vous décidez de passer à la prochaine version du projet A, la version 3.0 qui ajoute de nouvelles fonctionnalités intéressantes:

<dependency>
  <groupId>group1</groupId>
  <artifactId>projectA</artifactId>
  <version>3.0</version>
  <exclusions>
    <exclusion>
      <groupId>group2</groupId>
      <artifactId>projectB</artifactId>
    </exclusion>
  </exclusions>
</dependency>

Le problème est que vous n'êtes pas encore au courant que la version 3.0 de projectA a également mis à niveau sa dépendance de projetB vers la version 5.0:

+-foo:bar:1.0-SNAPSHOT
  +-group1:projectA:3.0
     +-group2:projectB:5.0
  +-group2:projectB:4.11

Dans ce cas, l'exclusion que vous auriez faite il y a quelque temps exclut la version 5.0 de projectB.

Cependant, projectA version 3.0 a besoin des améliorations de project B version 5.. En raison de l'exclusion, après avoir empaqueté le projet avec maven, la dépendance restante serait group2-someProjectB-4.11.jar, version 4.11 et non 5.0. Au moment où vous utilisez l'une des nouvelles fonctionnalités de projectA, le programme ne fonctionnerait pas correctement.

QUELLE ÉTAIT LA SOLUTION?

J'ai rencontré ce problème dans un projet Java-EE.

Une équipe a développé des services de bases de données. Ils l'ont emballé en tant que projectA. Chaque fois qu'ils ont mis à jour les services, ils ont également mis à jour un fichier répertoriant toutes leurs dépendances actuelles et les versions actuelles.

ProjectA était une dépendance du projet Java-EE sur lequel je travaillais. Chaque fois que l'équipe de service mettait à jour ProjectA, je vérifiais également les mises à jour des versions.

En fait, il n'y a aucun mal à exclure une dépendance. Mais à chaque fois que vous mettez à jour une dépendance où une exclusion a été définie, vous devez vérifier:

  • si cette exclusion a encore du sens.
  • si vous devez mettre à niveau la version de la dépendance exclue dans votre propre projet.

Je suppose que les exclusions Maven sont comme des couteaux de cuisine. Il est tranchant, coupe les légumes sans effort, mais nécessite des soins lors de sa manipulation ...

49
user2015707

Si JUnit en tant qu'artefact apparaît comme une dépendance dans la portée de compilation, il s'agit d'un bogue de l'une de vos bibliothèques, ici: ca.juliusdavies.

JUnit doit toujours être inclus dans la portée du test. Ainsi, il est pas compressé dans le fichier .jar, .war ou .ear produit, lors de la construction réussie.

D'une manière générale, il n'y a aucun mal à exclure les dépendances déjà incluses, comme lorsque la bibliothèque 1 et la bibliothèque 2 partagent une dépendance commune.

Le seul problème, bien sûr, qui peut se produire, est lorsque la bibliothèque 1 et la bibliothèque 2 incluent des versions différentes du même artefact dépendant. Cela peut provoquer des erreurs d'exécution, lorsque les fonctionnalités de la bibliothèque ont changé. Heureusement, ce n'est pas souvent le cas, sauf si la différence dans les numéros de version est grande. En général, il est conseillé d'inclure la dernière version de dépendance et d'exclure l'ancienne. C'est la plupart du temps viable.

Sinon, vérifiez s'il existe des mises à jour des dépendances de premier niveau de votre projet.

3
Andreas Krueger