Зависимость от Maven в зависимости от другой области

Скажем, у меня есть две зависимости Maven, определенные в проекте, как показано ниже.

    <dependency>
        <groupId>com.thoughtworks.xstream</groupId>
        <artifactId>xstream</artifactId>
        <version>1.3.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>mycompany.library</groupId>
        <artifactId>mylibrary</artifactId>
        <version>1.0.1</version>
        <scope>compile</scope>
    </dependency>

Затем в моей библиотеке у меня также есть зависимость, определенная ниже.

    <dependency>
        <groupId>com.thoughtworks.xstream</groupId>
        <artifactId>xstream</artifactId>
        <version>1.3.1</version>
        <scope>compile</scope>
    </dependency>

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

В такой ситуации, какой лучший способ включить xstream для всего проекта, чтобы подмодуль мог иметь к нему доступ при упаковке в проекте?

Я прочитал объяснение веб-сайта Apache Maven в отношении транзитивных зависимостей, но я изо всех сил пытаюсь понять, что это значит, а также найти наилучшую практику в этой ситуации.

Ответ 1

Мне это кажется странным, и если это "особенность", я думаю, что это действительно опасно. Во всяком случае, это не ошибка Maven, а в документации maven здесь.

Что касается лучших практик в этой проблеме, я ничего не слышал, но самый безопасный способ - это полностью удалить xstream от вашего помпеда, опираясь на транзитивную зависимость. Это приведет к сбою сборки при удалении зависимости от mylibrary. Это станет уведомлением о том, что вам нужно что-то исправить. Вы не будете свободно освобождать требуемые зависимости, и у вас не будет никаких зависимостей, которые вам больше не нужны.

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

Ответ 2

Как говорит матовый ответ, объявление зависимости как области test переопределяет декларацию зависимостей транзитивного компиляции, и в результате зависимость не включена в вашу упакованную войну.

Если вам нужна только зависимость в тестах, потому что "mylibrary" нуждается в ее выполнении, вы не должны декларировать зависимость вообще в своем проекте pom. Пусть процесс разрешения транзитивной зависимости обрабатывает его.

Если ваш проект действительно использует баннер xstream напрямую, вы все равно можете полагаться на транзитивную зависимость, так как вам понадобится совместимая версия для вашего проекта и "mylibrary" для запуска с банком xstream. У вас должны быть модульные тесты, которые выполняют функциональные возможности, и если mylibrary изменяет версию xstream на несовместимую версию, ваши сборки должны завершиться неудачно, и вы можете решить проблему в этот момент.

В общем, я бы сказал, что вы должны стараться избегать объявления версий зависимостей непосредственно в многомодульных проектах. Я объявляю версии в разделе dependencyManagement родительского POM, так что ребенку нужно объявить только groupId/artifactId. В качестве альтернативы, начиная с Maven 2.0.9 и далее, существует дополнительная область зависимостей import:

Эта область используется только для зависимости типа pom в этом разделе. Он указывает, что указанный POM должен быть заменен зависимостями в этом разделе POM. Поскольку они заменяются, зависимости с областью импорта фактически не участвуют в ограничении транзитивности зависимости.

Таким образом, используя область импорта, вы можете определить свои общие версии зависимостей в одном POM, импортировать зависимости этого POM в ваш раздел dependencyManagement и просто объявить groupId/artifactId зависимости в других POM.

Ответ 3

Объявляя свою собственную зависимость от xstream и устанавливая область проверки, вы переопределяете зависимости, объявленные mylibrary.

На самом деле это функция Maven - она ​​позволяет вам делать такие вещи, как зависимость от более поздней версии транзитивной зависимости внутри вашего собственного проекта, а не в конечном итоге упаковывать две разные версии одного и того же артефакта. Например, вы можете зависеть от версии 1.2.15 от log4j, но поскольку вы также используете libraryX, который зависит от log4j-1.2.14, вы не хотите, чтобы оба log4j-1.2.15 и log4j-1.2.14 были упакованы вместе с вашим проектом.

Если вы действительно хотите, чтобы xstream был упакован в ваш проект, вы не должны объявлять область как test. Фактически, если вы удалите указанную вами зависимость от xstream, все будет работать так, как вам нравится, поскольку mylibrary имеет зависимость от компиляции.

Ответ 4

Если вы хотите его упаковать, почему вы объявляете область? Если это необходимо во время компиляции и выполнения, не следует ли оставить область пустым? Если вы это сделали, вам понадобится

<dependency>
    <groupId>mycompany.modules</groupId>
    <artifactId>submodule</artifactId>
    <version>1.0.1</version>
</dependency>

в вашем пом. Если не существует причины для его удаления в процессе компиляции, но не во время упаковки?