Как Maven выбирает версию транзитивной зависимости, когда в дереве зависимостей существуют две или более версий этой зависимости? - PullRequest
0 голосов
/ 10 мая 2018

У меня есть проект, который зависит от используемой мной библиотеки, называется microservices-common. Общая библиотека микросервисов в свою очередь зависит от commons-codec:1.11. Однако, когда я пытаюсь использовать microservices-common в моем проекте, commons-codec:1.10 попадает в мой путь к классу, и мой код не компилируется, потому что microservices-common пытается использовать конструктор org.apache.commons.codec.digest.DigestUtils, который был добавлен в commons-codec:1.11 , но отсутствует в commons-codec:1.10.

Вот соответствующая часть дерева зависимостей для общих микросервисов:

[INFO] com.myproject:microservice-common:jar:1.0-SNAPSHOT
[INFO] +- commons-codec:commons-codec:jar:1.11:compile
[INFO] +- org.apache.httpcomponents:httpclient:jar:4.5.5:compile
[INFO] |  \- (commons-codec:commons-codec:jar:1.10:compile - omitted for conflict with 1.11)
[INFO] \- com.myproject:restful:jar:4.1.5-SNAPSHOT:compile
[INFO]    +- com.myproject:restful-common:jar:4.1.5-SNAPSHOT:compile
[INFO]    |  \- (commons-codec:commons-codec:jar:1.8:compile - omitted for conflict with 1.11)
[INFO]    \- (commons-codec:commons-codec:jar:1.8:compile - omitted for conflict with 1.11)

Если я правильно читаю дерево, другие версии зависимости commons-codec, включая v1.8 и v1.10, исключаются из пути к классам в пользу v1.11, чего я и хочу.

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

[INFO] com.myproject:microservice:jar:1.0-SNAPSHOT
[INFO] +- org.apache.httpcomponents:httpasyncclient:jar:4.1.3:compile
[INFO] |  \- org.apache.httpcomponents:httpclient:jar:4.5.3:compile
[INFO] |     \- (commons-codec:commons-codec:jar:1.10:compile - version managed from 1.11; omitted for duplicate)
[INFO] \- com.myproject:microservice-common:jar:1.0-SNAPSHOT:compile
[INFO]    +- commons-codec:commons-codec:jar:1.10:compile
[INFO]    \- com.myproject:restful:jar:4.1.5-SNAPSHOT:compile
[INFO]       +- com.myproject:restful-common:jar:4.1.5-SNAPSHOT:compile
[INFO]       |  \- (commons-codec:commons-codec:jar:1.10:compile - version managed from 1.8; omitted for duplicate)
[INFO]       \- (commons-codec:commons-codec:jar:1.10:compile - version managed from 1.8; omitted for duplicate)

В этом дереве я вижу сообщение "версия, управляемая из 1.x; опущена для дублирования". Я не уверен, что именно это означает, и, более касательно, строка 6 показывает, что commons-codec:1.10 - это то, что заканчивается на моем пути к классам, а не v1.11, что я на самом деле хочу.

Следует отметить, что pom.xml для com.myproject:microservice-common:jar:1.0-SNAPSHOT объявляет зависимость commons-codec:1.11, поэтому единственные места, из которых commons-codec:1.10 мог прийти, это либо org.apache.httpcomponents:httpclient:jar:4.1.3, либо com.myproject:restful:jar:4.1.5-SNAPSHOT (еще одна распространенная библиотека, от которой я не могу избавиться по унаследованным причинам), но мне не ясно, почему эта версия переходной зависимости выбирается для включения в версию, которую объявляет моя общая библиотека микросервисов.

Кто-нибудь может объяснить, как работает выбор зависимостей, когда в дереве зависимостей существует несколько версий одной и той же библиотеки, и почему microservices-common, по-видимому, выбирает правильную версию транзитивной зависимости, когда построена в изоляции, но мой проект микросервисов выбирает другую версия, когда я ее создаю?

1 Ответ

0 голосов
/ 10 мая 2018

Maven выбирает версию зависимости, ближайшую в дереве зависимостей. Это очень хорошо объясняется в документации Maven :

«ближайшее определение» означает, что используемая версия будет ближайшей один для вашего проекта в дереве зависимостей, например. если зависимости для A, B и C определены как A -> B -> C -> D 2.0 и A -> E -> D 1.0, тогда D 1.0 будет использоваться при построении A, потому что путь от A до D через E короче.

Если зависимость встречается несколько раз на одном и том же уровне, выигрывает первое объявление (начиная с Maven 2.0.9).

Лучший и устоявшийся способ обеспечить использование требуемой версии commons-codec - это объявить dependencyManagement в вашем pom 'microservice' (непосредственно под элементом project):

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.11</version>
        </dependency>
    </dependencies>
</dependencyManagement>

Кроме того, убедитесь, что вы используете последнюю версию Maven (рекомендуется 3.5).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...