Разрешение зависимости Maven (конфликтует) - PullRequest
62 голосов
/ 24 августа 2011

Допустим, у меня есть четыре проекта:

  • Проект A (зависит от B и D)
  • Проект B (зависит от D)
  • Проект C (зависит от D)
  • Проект D

В этом сценарии, если я запускаю проект A, Maven правильно разрешит зависимость от D. Если я правильно понимаю, Maven всегда берет зависимость с кратчайшим путем. Поскольку D является прямой зависимостью от A, она будет использоваться вместо D, который указан в B.

Но теперь предположим, что это структура:

  • Проект A (зависит от B и C)
  • Проект B (зависит от D)
  • Проект C (зависит от D)
  • Проект D

В этом случае пути к разрешению D имеют одинаковую глубину. То, что происходит, - то, что у Maven будет конфликт. Я знаю, что можно сказать Мавену, что он должен исключить зависимости. Но мой вопрос, как решить такие проблемы. Я имею в виду, что в реальных приложениях у вас много зависимостей и, возможно, много конфликтов.

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

Я использую maven 2.1-SNAPSHOT.

Ответы [ 5 ]

73 голосов
/ 24 августа 2011

Традиционный способ разрешения подобных ситуаций - включить раздел <dependencyManagement> в корневой раздел вашего проекта, где вы указываете, какая версия какой библиотеки будет использоваться.

РЕДАКТИРОВАТЬ:

<dependencyManagement>
  <dependencies>
    <dependency>
        <groupId>foo</groupId>
        <artifactId>bar</artifactId>
        <version>1.2.3</version>
    </dependency>
   </dependencies>
</dependencyManagement>

Теперь независимо от того, какая версия библиотеки foo: bar запрашивается зависимостью, версия 1.2.3 всегда будет использоваться для этого проекта и всех подпроектов.

Ссылка:

25 голосов
/ 24 августа 2011

Maven может справиться с обеими ситуациями без каких-либо конфликтов.Конфликты будут существовать, когда требуются две версии транзитивной зависимости.ClassNotFoundException, который вы описываете, является результатом того, что приложение (или зависимость) пытается использовать класс, недоступный в версии конфликтующей зависимости, которая фактически используется.Существует несколько способов решения проблемы.

  1. Обновите версии библиотек, которые вы используете, которые зависят от конфликтующей зависимости, чтобы они все зависели от одной и той же версии версии этой зависимости
  2. Объявите конфликтующую зависимость как прямую зависимость вашего проекта с версией, которую вы хотите включить (в примере, с отсутствующим классом, включенным в него)
  3. Укажите, какая версия конфликтующей зависимостичто транзитивные зависимости следует использовать через раздел <dependencyManagement> POM
  4. Явно исключить нежелательные версии конфликтующих зависимостей из включения в зависимости, которые на них полагаются, используя <exclusion>
16 голосов
/ 24 августа 2011

Это принципиально не проблема maven, а проблема java. Если проект B и проект C нуждаются в двух несовместимых версиях проекта D, вы не можете использовать их обе в проекте A.

Мавенский способ разрешения подобных конфликтов, к сожалению, как вы уже знаете, выбирает, какие из них исключать.

Использование mvn dependency:analyze и mvn dependency:tree помогает найти конфликты, которые у вас есть.

12 голосов
/ 16 ноября 2013

Вы можете применять согласованные зависимости во всем проекте с помощью правила Конвергенция зависимостей .

 <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-enforcer-plugin</artifactId>
     <version>1.3.1</version>
     <executions>
        <execution>
           <id>enforce</id>
           <configuration>
              <rules>
                 <DependencyConvergence/>
              </rules>
           </configuration>
           <goals>
              <goal>enforce</goal>
           </goals>
        </execution>
     </executions>
  </plugin>
5 голосов
/ 24 августа 2011

Одна из возможных стратегий - указать для основного проекта, какую версию D использовать (новейшую fg).Однако, если библиотека D не имеет обратной совместимости, у вас есть проблема, заявленная kukudas - невозможно использовать обе библиотеки в вашем проекте.

В такой ситуации может потребоваться использовать B или C в более старой версии, чтобы оба варианта зависели от совместимых версий D.

...