Как реструктурировать мультимодульный проект Maven?
Я прошу прощения за длину этого поста, но мне было трудно сделать его более кратким, не представляя картину. Недавно я унаследовал работу build-master для многомодульного проекта maven 3.0. Проблема в том, что структура проекта / модулей является катастрофой. От того, как все в настоящее время хранится в Source Control (мы используем RTC), до структуры pom модулей, я рву голову, пытаясь каждый раз завершить полный цикл сборки.
Поскольку иерархия проекта идет, все модули сохранены "плоскими"; т.е. все на одном уровне. У меня есть родительский pom, и все модули зависят от родительского. Тем не менее, родительский уровень находится на том же уровне, что и все остальные мои модули.
Пример:
c:\dev\MyEarProject
+ parent-pom
- pom.xml
+ module1
- pom.xml (depends on parent-pom)
- src
- main
- ...
+ module2
- pom.xml (depends on parent-pom)
- src
- main
- ...
+ module3
- pom.xml (depends on parent-pom)
- src
- main
- ...
Родительский pom определяет все модули, необходимые для сборки проекта, а также набор свойств для номеров версий артефактов, используемых в различных подмодулях:
<modules>
<module>../module1</module>
<module>../module2</module>
<module>../module3</module>
</modules>
<properties>
<org.springframework.version>3.0.5.RELEASE</org.springframework.version>
<slf4j.version>1.6.4</slf4j.version>
<repositoryAddress>${snapshots.repo.url}</repositoryAddress>
<my.hibernate-module.dao.impl>1.2.3</my.hibernate-module.dao.impl>
<my.hibernate-module.dao.api>1.2.3</my.hibernate-module.dao.api>
</properties>
Pom каждого модуля, в свою очередь, зависит от родительского pom через номер артефакта pom:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
</parent>
Чтобы сделать вещи еще более запутанными, фактическое имя артефакта может или не может (в зависимости от модуля) соответствовать пути к модулю. Например, модуль1 может быть расположен в пути c:\dev\MyEarProject\module1
но есть имя артефакта hibernate-module
, Однако из-за того, как он хранится в RTC, каталог называется module1
когда это проверено.
Конечно, проще всего построить все c:\dev\MyEarProject\parent-pom\
и беги mvn clean deploy
, Это прекрасно работает в режиме SNAPSHOT, поскольку репозиторий SNAPSHOT позволяет использовать несколько версий одной и той же версии артефакта. Но в режиме релиза это не получается.
Эта структура вызывает у меня 2 проблемы.
- Каждый раз, когда мне нужно изменить версию для свойства в родительском объекте, мне приходится обновлять номер версии parent-pom, а также версию всех родительских pom дочерних модулей и все версии дочерних модулей (так как родитель изменился).
- Всякий раз, когда мне нужно развернуть цикл выпуска, mvn выдаст ошибку, если один из модулей не изменился со времени последнего цикла и, следовательно, не может быть повторно развернут в том же репо (репо не позволяет перезаписать существующие артефакты)
Поэтому я ищу лучший способ реструктуризации этого проекта, чтобы избежать этих проблем. Я знаю, что для родительского pom я могу использовать относительный путь, чтобы указать на родителя. Однако, учитывая "плоскую" структуру модулей, является ли это рекомендуемым подходом (то есть: относительный путь родительского pom будет../parent-pom/pom.xml - мне кажется немного странным)? Кроме того, учитывая, что управление версиями родительского элемента не зависит от модулей, использование относительного пути не просто откроет путь к дополнительной путанице (т. Е. Не будет способа узнать, какая версия родительского pom связана с какой версией субмодуля).
Во-вторых, как я могу собрать все ухо, не встречая ошибок развертывания, которые у меня возникают? Поскольку артефакт уже существует в репо, мне не нужно его перестраивать и заново развертывать. Я пытался использовать --projects, но из-за количества задействованных модулей им становится чрезвычайно сложно управлять.
3 ответа
Первое, что я действительно рекомендую, - это реструктурировать папки проектов... что означает, что папка проектов представляет структуру, что означает НЕ выравнивать структуру.
+-- parent-pom (pom.xml)
+--- module1 (pom.xml)
+--- module2 (pom.xml)
+--- module3 (pom.xml)
В результате этого раздел модулей вашего родителя будет упрощен следующим образом:
<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
</modules>
Кроме того, родительские записи в ваших модулях могут быть упрощены так:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
</parent>
... что подводит меня к следующему пункту:
Если все ваши текущие проекты определяют своего родителя, как указано выше, это просто неправильно, причина будет пытаться найти родителя в хранилище, а не в папке верхнего уровня. Другими словами, это вызывает большую часть ваших проблем с выпуском и т. Д.
Если бы мы решили эту проблему, она должна выглядеть так, что я не могу рекомендовать:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
<relativePath>../parent-pom/pom.xml</relativePath>
</parent>
Другая вещь, которую я наблюдаю, это то, что вы не используете SNAPTSHOT
который будет заменен плагином релиза на этапе релиза. В связи с этим он автоматически изменит все версии соответствующих родителей и т. Д.
В идеальном случае ваши модули должны выглядеть так:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
</parent>
<artifactId>module-1</artifactId>
<!-- No Version or groupId -->
Потому что все модули будут наследовать версию и groupId
от их родителей. Иногда полезно или нужно поменять модули groupId
но это исключение.
Одна вещь, которую я перечитал, касается отдельного управления версиями родителя. Это просто не имеет смысла, потому что он является родителем их модулей, поэтому поместите его в ту же структуру и, конечно, в ту же VCS.
Если вы хотите сделать некоторые конфигурации / плагины версии, зависимости, которые должны быть использованы для других проектов, а не сделать отдельный корпоративный pom.xml
который является отдельным проектом и будет выпущен отдельно
После того, как вы закончили изменения структуры, вы можете просто зайти в каталог parent-pom и сделать mvn clean package
или же mvn release:prepare release:perform
из этой папки и все будет проще.
Вы предъявляете противоречивые требования. Вы хотите реструктурировать свой проект, но не можете что-то изменить. Вы хотите упростить циклы развертывания и выпуска, но не хотите использовать одну версию.
Учитывая, что изменения в одном модуле неизбежно повлияют на все зависимые модули, я бы использовал простую схему версий, где все подмодули наследуют версию своего родителя. Maven Release: циклы подготовки и выпуска становятся простыми. Используйте примечания к выпуску, чтобы отслеживать ваши изменения и оправдывать пропуск ненужного тестирования неизмененных модулей (изменения в версии не изменяют выходные данные процесса сборки / двоичные данные, поэтому вы можете использовать это в качестве основного аргумента).
Удачи с вашим проектом.
Если вы публикуете свое POM, вам придется выпускать любые обновления, но вам не нужно изменять версии POM вручную - вы можете обновлять версии автоматически с помощью плагина версий или плагина релиза. Я предпочитаю плагин релиза, так как он будет использовать и SCM для вас.
mvn versions:set
http://mojo.codehaus.org/versions-maven-plugin/
mvn release:prepare release:perform
http://maven.apache.org/plugins/maven-release-plugin/
Ваш менеджер репозитория может также разрешить перезаписывать существующую версию, но лучше просто выпустить новую версию.
Я предпочитаю использовать плоскую структуру модуля, поскольку она позволяет использовать родительскую папку для хранения общих файлов, например, конфигурации контрольного стиля. Я также считаю полезным разделить идентификатор группы по модулям, а затем назвать каталог модулей так же, как artifactId.