Решение проблем конвергенции зависимостей 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-plugin.

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

2 ответов


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

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

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

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

обратите внимание, что это просто упрощение вашего дела. Увидев это дерево зависимостей, вы исключите зависимость projectB, заданную 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 также обновили свою зависимость projectB до версии 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 нуждается в улучшениях от project B версии 5.0. Из-за исключения, после упаковки проекта с maven, оставшаяся зависимость будет group2-someProjectB-4.11.jar, версия 4.11, а не 5.0. На данный момент Вы используете любую из новых функций projectA, программа не будет работать правильно.

КАКОВО БЫЛО РЕШЕНИЕ ?

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

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

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

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

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

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


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

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

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

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

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