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

Как разрешать зависимости между модулями в рамках мультимодульного проекта?

После работы с Maven некоторое время я в восторге от многих функций, которые Maven привносит в архитектуру сборки, особенно управление зависимостями. Тем не менее, я снова и снова сталкивался с одной проблемой - как Maven разрешает зависимости между многомодульными проектами. Мне интересно, если это большой недостаток текущей реализации Maven и/или если есть удовлетворительное обходное решение.

Скажем, у меня мультимодульный проект Maven. Parent pom содержит три модуля - moduleA (jar), moduleB (jar) и moduleC (war). B зависит от A и C зависит от B. Прост достаточно? Теперь, когда я хочу запустить mvn dependency:go-offline в родительском проекте, который должен разрешить все зависимости и привести их в локальный каталог .m2. Он терпит неудачу, потому что Maven жалуется, что он не может решить зависимость для модуляA, когда он действует на moduleB. Поскольку все эти модули принадлежат к одной группе Id, я даже пытаюсь использовать -DexcludeGroupIds=x.y.z для исключения этих зависимостей модулей, но он все равно терпит неудачу в одной и той же точке.

Я понимаю, почему Maven жалуется - moduleA еще не построен, и, таким образом, в моем локальном или внутреннем репозитории нет объекта moduleA: jar artifact, когда выполняется статическая цель. Но IMHO плагин должен относиться к этим межмодульным зависимостям по-разному. В этом случае он должен просто игнорировать его. Можно утверждать, что я могу просто сделать mvn clean install, который установит moduleA: jar в локальный репозиторий. После этого работает mvn dependency:go-offline. Но это обходное решение поражает цель этой цели в оффлайне. Этот плагин позволяет нам разрешать и вытаскивать зависимости в наш локальный репозиторий без создания всего проекта. Я использовал цель dependency:copy-dependencies в другом случае и имел ту же проблему.

Я также столкнулся с аналогичной проблемой в других сценариях: "mvn clean source-source" не удалось разрешить зависимости. Когда я запускал mvn clean compile, все работает нормально, но когда я запускал mvn clean generate-source, он терпит неудачу, потому что Maven не может разрешить зависимость между модулями. В этом случае это было вызвано @requiresDependencyResolution в планете antrun.

Поскольку оба плагина antrun и плагин зависимостей очень популярны в мире Maven, я уверен, что я не единственный, кто столкнулся с этой проблемой. Кто-нибудь находит какое-либо решение/обходное решение?

4b9b3361

Ответ 1

Я сомневаюсь, что такая функциональность будет возможна с Maven. Хотя ваши проекты имеют общий родитель и зависят друг от друга, Maven не может знать, где найти эти проекты, чтобы их построить. Он также не может определить, нужно ли просто создавать проекты, или вы указали неверный номер версии для своей зависимости.

Ответ 2

Maven имеет концепцию "реактора", где артефакты, которые были построены за один проход (например, maven package), доступны для разрешения зависимостей во время сборки. Например, если ваш график зависимостей дает модуль модуля сборки модуля moduleB moduleC, и вы выполняете mvn package, Maven будет строить модульA, упаковывать его артефакт и добавлять его в реактор, а затем строить модуль B, упаковывать его и добавлять в реактор, то то же самое для модуля C. Это означает, что модуль B имеет доступ к артефакту moduleA для разрешения зависимостей, а moduleC имеет доступ к модулям A и модулю B. Это работает только в том случае, если артефакты фактически построены, то есть когда вы запускаете цель пакета.

Проблема заключается в том, что если вы не запускаете цель пакета, потому что вас не интересуют артефакты (например, для вашего примера dependency:go-offline), артефакты для обработанных модулей не создаются и, следовательно, не добавляется в реактор. Я нахожу это раздражающим; Я думаю, что Maven должен смотреть на файлы POM в своем списке модулей для сборки и просмотра там; но это не так.

Короче говоря, решение вашей проблемы - сделать mvn package dependency:go-offline. Это не приведет к установке артефактов в вашем локальном хранилище (что, по моему мнению, является очень плохой практикой), но оно будет помещать их в реактор на время сборки, а это значит, что Maven сможет разрешать зависимости от вашего модуля B до модуля A, который имеет уже построены. Недостатком является то, что каждый модуль будет протестирован и упакован, что очень важно, если вы хотите только dependency:go-offline.

В любом случае, надеюсь, что это поможет.

Ответ 3

Вы объяснили, почему это не работает, поэтому вы понимаете проблемы. Проблема для вас в том, что она останавливается, когда она не может найти A.jar, но это произойдет только тогда, когда вы доберетесь до здания B. Таким образом, есть своего рода, иногда полезная стратегия.

Вы должны возиться с A сами по себе. Просто создайте A. Используйте свой план загрузки зависимостей, а затем создайте его.

Как только он будет создан, вы можете перейти к тому же, что и B, а затем C. Шаг за шагом.

Одна вещь, которую следует помнить здесь, - это то, что иногда можно построить B со старым снимком A в локальном репо. Вам нужен только новый снимок сборки A в репо, если есть изменения подписи или новые вещи, необходимые для B.

Здесь также есть некоторые обсуждения: Модули Maven + Создание единого специализированного модуля

В конечном итоге не так обычно возникают такие вопросы, когда люди строят слишком долго. Существует несколько способов ускорения сборки:

  • Получить более быстрое оборудование. Компьютер сборки, дисковое хранилище или скорость сети являются типичными компонентами, которые дешевле модернизировать, чем тратить время, затраченное на медленные сборки.
  • Сделайте сборку быстрее, не строя вещи, которые не нуждаются в перестройке. (Например, у меня была сборка, которая каждый раз перестраивала весь сгенерированный код. Я добавил некоторые вещи в сборку, которые не позволяли ей это делать, кроме случаев, когда менялись зависимости от сгенерированного кода.)
  • Ускорьте тесты. Иногда это означает разбить тесты на две части. Часть 1 - это быстрые тесты, а часть 2 - медленные тесты. Запускайте быстрые тесты при каждой сборке и медленных тестах перед любой проверкой кода или выпуском артефактов.
  • Разбейте многомодульную сборку на 2 или более отдельные сборки и используйте человеческий интеллект, чтобы решить, когда нужно перестраивать вещи. Это хорошо работает, когда некоторые банки стабильны и больше не меняются.
  • Заполните свой собственный метод, чтобы сделать сборку быстрее.