В многомодульном проекте Maven, как указать зависимость, необходимую более чем в одном модуле?

Я знаю, что цель многомодульного проекта Maven состоит в том, чтобы каждый модуль можно было скомпилировать и построить отдельно, а также вместе с родителем.

Предположим, два из моих трех модулей должны использовать библиотека Google Guava. Указать ли эту зависимость в POM каждого из двух подмодулей? Если да, то какой "сфера"? Или мне указать зависимость в родительском модуле? Мне нужно, чтобы Гуава была включена в мой конечный продукт, но мне определенно не нужны две копии.


person Basil Bourque    schedule 12.08.2017    source источник
comment
В этом случае распространенным подходом будет использование dependencyManagement в родительском модуле и добавление туда вашей зависимости от Guava. В дочерних модулях вы добавляете зависимость от guava без версии и области действия (это будет обрабатываться родителем). Это предотвратит использование разных модулей с библиотекой разных версий. Насколько я знаю, невозможно сказать maven, чтобы он не генерировал две копии зависимости, если ваши модули генерируют два отдельных JAR-файла. Если это веб-модуль, он не будет создавать копии....   -  person Jorge Campos    schedule 13.08.2017
comment
Я не думаю, что вам нужно беспокоиться об этом, поскольку даже если у вас есть две копии в пути к классам одной и той же банки, одна из них будет проигнорирована при загрузке.   -  person Jorge Campos    schedule 13.08.2017


Ответы (2)


Обычно я объявляю все зависимости в dependencyManagement родительского проекта, а затем использую их в depenencies модулей, но без version. Версии объявляются только в родительском проекте.

Что касается scope, я обычно не объявляю область действия в родительском элементе, если это не что-то очень очевидное, например JUnit.

Указать ли эту зависимость в POM каждого из двух подмодулей?

Если вы используете эту зависимость напрямую, то да. Даже если он будет включен транзитивно.

Если да, то какой "сфера"?

Это зависит от того, что такое зависимость и как вы ее используете. Гуава обычно будет compile.

Или мне указать зависимость в родительском модуле?

Вы можете объявить его в dependencyManagement в родительском файле, чтобы вам не нужно было указывать версию где-либо еще.

Но обычно вы не будете объявлять зависимость в родительском модуле, поскольку она будет унаследована всеми дочерними модулями. Обычно это слишком большое предположение.

Мне нужно, чтобы Гуава была включена в мой конечный продукт, но мне определенно не нужны две копии.

Не произойдет.

person lexicore    schedule 12.08.2017

Предположим, два из трех моих модулей должны использовать библиотеку Google Guava. Указать ли эту зависимость в POM каждого из двух подмодулей?

Это зависит от того, какова связь между этими модулями и тем, что вы с ними делаете; назовем их moduleA, moduleB (модули, которые имеют общую зависимость) и moduleC (третий модуль).

Как вы развертываете moduleA и moduleB? Есть ли смысл в том, чтобы у каждого была своя копия одной и той же библиотеки?

  • Например, если они оба являются WAR, которые работают независимо, вы захотите предоставить каждому свою собственную копию библиотеки.
  • Если они оба являются банками, которые попадают в одну и ту же войну (возможно, представленную moduleC), то вам нужно дать каждой из них зависимость с scope=provided и добавить третью зависимость в moduleC с областью действия по умолчанию.

Или мне указать зависимость в родительском модуле?

Проблема с указанием зависимости в родительском модуле заключается в том, что зависимость также будет выбрана moduleC, что может быть не тем, что вам нужно.

Одна из возможностей решить эту проблему (например, если moduleA и moduleB имеют множество общих зависимостей, общих свойств или настроек) — добавить общего родителя:

  • Дополнительный родительский помпон/реактор для moduleA и moduleB, но НЕ для moduleC.
  • Этот дополнительный родительский pom будет находиться на том же уровне в дереве, что и moduleC (и, таким образом, он, в свою очередь, будет иметь того же родителя, что и moduleC).
  • Он будет содержать все, что есть общего у moduleA и moduleB.
person Andrei    schedule 12.08.2017
comment
Я не вижу, чтобы третий подмодуль подбирал зависимость (хорошо). В родительском я указал зависимость с помощью groupid, artifactid и version. В каждом из двух подмодулей я опускаю version. Панель IntelliJ Maven показывает каждый из двух подмодулей с копией библиотеки Guava, но не показывает третий подмодуль (хорошо). В папке WEB-INF/lib моего построенного проекта Vaadin 8 (Java Servlet) я нахожу список библиотек только с одним Guava. Так что я полагаю, что это достаточно хорошо для меня. Но я еще не реализовал модульное тестирование в каждом модуле. - person Basil Bourque; 13.08.2017
comment
Извините, не уверен, что понимаю на 100%. Если 3 модуля имеют одну зависимость, когда вы предполагали, что она будет только у 2 из них, вы все равно получите только одну банку в WEB-INF/lib, потому что зависимость будет иметь одно и то же имя во всех 3 случаях, поэтому только один из них будет win (другие 2 копии будут перезаписаны из-за файлов с одинаковыми именами). - person Andrei; 13.08.2017
comment
Я имею в виду часть об указании зависимости в родительском модуле. Подмодули получают копию только на промежуточном этапе (IntelliJMaven Projectsmy-sub-moduleDependencies), если в POM для этого подмодуля указан <dependency><groupid><artifactid>, но без номера версии (где родительский POM указывает <version>). - person Basil Bourque; 13.08.2017
comment
Если вы укажете зависимость в родительском элементе, дочерние элементы во всех случаях получат копию (с той же областью действия, что и в родительском). Наследование версии предназначено только для того, чтобы не указывать его дважды. Это не влияет на стратегию включения. Не путайте dependencies с dependencyManagement. - person Andrei; 13.08.2017