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

Разрешение зависимостей Maven (конфликтующее)

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

  • Проект 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.

4b9b3361

Ответ 1

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

EDIT:

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

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

Справка:

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 4

Вы можете enforce согласованные зависимости во всем проекте с правилом Dependency Конвергенция.

 <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

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

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