Почему maven использует более старую версию, когда между дочерними проектами возникает конфликт?

Если у вас есть один дочерний модуль testA, который зависит от vaadin-client-compiler, который зависит от commons-lang3 версии 3.1, он также зависит от другого дочернего модуля testB, который зависит от commons-lang3 версии 3.4.

Я ожидаю, что testA будет использовать версию 3.4, потому что testB зависит от нее, но использует версию 3.1. Я могу решить это, добавив [] к версии в проекте testB, но почему это происходит? Почему maven не разрешает правильную версию без принуждения?

MCVE:

Родитель:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>test</name>
    <packaging>pom</packaging>
    <modules>
        <module>testB</module>
        <module>testA</module>
    </modules>
</project>

Ребенок, который зависит

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>test</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <version>7.6.8</version>
            <artifactId>vaadin-client-compiler</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
  <groupId>testB</groupId>
  <artifactId>testB</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
  <groupId>testA</groupId>
  <artifactId>testA</artifactId>
</project>

И зависимый ребенок

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>test</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <groupId>testB</groupId>
  <artifactId>testB</artifactId>
  <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>
  </dependencies>
</project>

person Black Trans Woman    schedule 02.05.2018    source источник
comment
вы должны установить управление зависимостями в родительском pom и управлять версией там.   -  person Paul Bastide    schedule 02.05.2018
comment
@PaulBastide Это MCVE, мои настоящие проекты сложнее. Как я уже сказал в своем вопросе, у меня есть решение, я спрашиваю, почему это происходит.   -  person Black Trans Woman    schedule 02.05.2018
comment
@PaulBastide Даже в этом примере я не согласен с вашим предложением. Я использую и нуждаюсь в версии 3.4 в testB и именно там она должна быть указана, я не использую ее больше нигде в других модулях. vaadin-client-compiler о необходимости этого я даже не подозревал до того, как столкнулся с этой проблемой.   -  person Black Trans Woman    schedule 02.05.2018
comment
Почему я получаю отрицательные голоса? Это действительно ранит мои чувства.   -  person Black Trans Woman    schedule 02.05.2018
comment
Решение состоит в том, чтобы использовать dependencyManagement, как указано @PaulBastide, объяснение дано в ответе....   -  person khmarbaise    schedule 02.05.2018
comment
@khmarbaise Использование [3.4] также является решением, как я упоминал в своем вопросе.   -  person Black Trans Woman    schedule 02.05.2018
comment
Я не могу рекомендовать использовать это... лучше определить его через dependencyManagement   -  person khmarbaise    schedule 02.05.2018
comment
@khmarbaise Да, я согласен с этим. Имеет ли смысл определить его в testA или в родительском pom?   -  person Black Trans Woman    schedule 02.05.2018
comment
Сделайте это в родительском помпе, чтобы все дети могли использовать его без головной боли...   -  person khmarbaise    schedule 02.05.2018


Ответы (1)


Согласно документации Maven:

[Maven] будет использовать версию ближайшей к вашему проекту зависимости в дереве зависимостей.

а также

если две версии зависимостей находятся на одной глубине в дереве зависимостей, до Maven 2.0.8 не было определено, какая из них выиграет, но начиная с Maven 2.0.9 учитывается порядок в объявлении: выигрывает первое объявление.

Итак, ответ на ваш вопрос: потому что вы определили зависимость vaadin-client-compiler до зависимости testB, а зависимость от commons-lang3 имеет ту же глубину дерева, что и testA.

Если вы измените порядок своих зависимостей в testA, вы увидите, что теперь он использует версию 3.4 commons-lang3 (при условии, что вы используете версию Maven 2.0.9 или новее)

person D.B.    schedule 02.05.2018
comment
Спасибо, я почему-то думал, что maven учитывает версию зависимости и использует более позднюю, вот как я бы это реализовал. Вероятность того, что что-то сломается, меньше, если бы это было сделано таким образом. - person Black Trans Woman; 02.05.2018
comment
Пожалуйста, но я не уверен, что использование последней версии значительно снижает риск возникновения проблем. На самом деле это зависит от того, как разработчики писали код и планировали ли они и тестировали ли они обратную совместимость. - person D.B.; 02.05.2018