Подтвердить что ты не робот

Решение проблем конвергенции зависимостей Maven

Я использую maven-enforcer-plugin для проверки проблем конвергенции зависимостей. Типичным результатом будет:

[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
]

Увидев это сообщение, я обычно "решал" его, исключая транзитивную зависимость, например

<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>

Я хотел бы понять, действительно ли это исправление и риски, связанные с исключением библиотек таким образом. Как я вижу:

  • "Исправление" обычно безопасно, если я предпочитаю использовать более новую версию. Это зависит от авторов библиотеки, поддерживающих обратную совместимость.

  • Как правило, никакого эффекта на сборку Maven не оказывает (так как выигрывает более быстрое определение), однако, исключая зависимость, которую я рассказываю Maven о том, что я знаю об этой проблеме, и таким образом умиротворяет плагин maven-enforcer.

Правильны ли мои мысли и есть ли альтернативный способ решения этой проблемы? Меня интересуют ответы, которые фокусируются на общем случае - я понимаю, что пример junit, приведенный выше, немного странный.

4b9b3361

Ответ 1

Мы все согласны с тем, что JUnit никогда не должен устанавливаться в другой области, кроме test. Вообще говоря, я не думаю, что есть другое решение, кроме исключения нежелательной зависимости, поэтому мы все согласны с тем, что вы правы в этом.

ПРОСТОЙ СЛУЧАЙ:

Как говорит Андреас Крюгер, может возникнуть риск с версиями (я действительно столкнулся с этим). Скажем, что зависимостями проекта являются следующие:

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

Обратите внимание, что это всего лишь упрощение вашего дела. Если вы видите это дерево зависимостей, вы должны исключить проект зависимости b, заданный projectA:

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

После упаковки проекта с maven оставшаяся зависимость будет group2-someProjectB-4.11.jar, версия 4.11, а не 3.8.1. Все будет хорошо, и проект будет работать без каких-либо проблем.

Затем, спустя некоторое время, скажем, что вы решили перейти на следующую версию проекта A, версия 3.0, которая добавляет новые замечательные функции:

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

Проблема в том, что вы еще не знаете, что версия ProjectA 3.0 также обновила проект зависимости b до версии 5.0:

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

В этом случае исключение, которое вы бы сделали за последнее время, исключает версию projectB версии 5.0.

Однако projectA версии 3.0 нуждаются в улучшениях от версии B версии 5.0. Из-за исключения, после упаковки проекта с maven, оставшаяся зависимость будет group2-someProjectB-4.11.jar, версия 4.11, а не 5.0. На данный момент вы используете какие-либо новые функции projectA, программа будет работать неправильно.

ЧТО БЫЛО РЕШЕНИЕ?

Я столкнулся с этой проблемой в проекте Java-EE.

Команда разработала службы баз данных. Они упаковали его как projectA. Каждый раз, когда они обновляли службы, они также обновляли файл, в котором перечислены все их текущие зависимости и текущие версии.

ProjectA был зависимым от проекта Java-EE, над которым я работал. Каждый раз, когда сервис-команда обновляла ProjectA, я также проверял обновления версий.

На самом деле, нет никакого вреда для исключения зависимости. Но каждый раз, когда вы обновляете зависимость, в которой установлено исключение, вы должны проверить:

  • если это исключение все еще имеет смысл.
  • если вам нужно обновить версию исключенной зависимости в своем собственном проекте.

Я думаю, что исключения maven похожи на кухонные ножи. Он острый, безрезультатно режет овощи, но требует осторожного обращения...

Ответ 2

Если JUnit как артефакт происходит как зависимость в области компиляции, это ошибка одной из ваших библиотек, здесь: ca.juliusdavies.

JUnit всегда должен быть включен в область проверки. Таким образом, он не упакован в полученный файл .jar,.war или .ear при успешной сборке.

Вообще говоря, нет никакого вреда в исключении уже включенных зависимостей, так как библиотека 1 и библиотека 2 имеют одну общую зависимость.

Единственная проблема, конечно, может произойти, когда библиотека 1 и библиотека 2 включают разные версии одного и того же зависимого артефакта. Это может привести к ошибкам во время выполнения, когда изменились возможности библиотеки. К счастью, это не так часто, если разница в номерах версий невелика. В общем, рекомендуется включить последнюю версию зависимостей и исключить старшую. Это большая часть времени жизнеспособна.

Если нет, проверьте, есть ли обновления для зависимостей первого уровня вашего проекта.