Как реструктурировать мультимодульный проект 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 проблемы.

  1. Каждый раз, когда мне нужно изменить версию для свойства в родительском объекте, мне приходится обновлять номер версии parent-pom, а также версию всех родительских pom дочерних модулей и все версии дочерних модулей (так как родитель изменился).
  2. Всякий раз, когда мне нужно развернуть цикл выпуска, 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.

Другие вопросы по тегам