Maven родитель пом против модулей пом

284

Кажется, есть несколько способов структурировать родительские помпы в многопроектной сборке, и мне интересно, есть ли у кого-нибудь мысли о преимуществах / недостатках каждого из них.

Самый простой способ иметь родительский pom - это поместить его в корень проекта, т.е.

myproject/
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml

где pom.xml является как родительским проектом, так и описывает модули -core -api и -app

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

myproject/
  mypoject-parent/
    pom.xml
  myproject-core/
  myproject-api/
  myproject-app/

Где родительский pom все еще содержит модули, но они являются относительными, например ../myproject-core

Наконец, есть опция, где определение модуля и родительский элемент разделены, как в

myproject/
  mypoject-parent/
    pom.xml
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml

Где родительский pom содержит любую «общую» конфигурацию (dependencyManagement, свойства и т. Д.), А myproject / pom.xml содержит список модулей.

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

Несколько бонусных вопросов:

  • Где лучше всего определить различные общие конфигурации, такие как управление исходным кодом, каталоги развертывания, общие плагины и т. Д. (Я полагаю, что родительский, но я часто укусил это, и они оказались в каждом проекте, а не общий).
  • Как плагин maven-release, hudson и nexus справляется с тем, как вы настраиваете свои мультипроекты (возможно, гигантский вопрос, более важно, если кто-нибудь узнает, когда была настроена мультипроектная сборка)?

Изменить: Каждый из подпроектов имеет свой собственный pom.xml, я оставил его, чтобы сохранить его кратким.

Джейми МакКриндл
источник
У каждого модуля тоже есть свой пом? В моем проекте есть родительский pom, но у каждого модуля также есть pom. (возможно, четвертый путь к тому, что вы описываете)
Harschware
Ах да, я буду редактировать и обновлять. Каждый из подмодулей также имеет свой пом.
Джейми МакКриндл
3
Как обновление, я вижу преимущество второго варианта в том, что им легче управлять в Eclipse, где будет сложно включить корневой файл pom.xml в первом и третьем примере, если подмодули являются отдельными проектами в Eclipse.
Джейми МакКриндл

Ответы:

166

На мой взгляд, чтобы ответить на этот вопрос, нужно мыслить с точки зрения жизненного цикла проекта и контроля версий. Другими словами, имеет ли родительский pom свой жизненный цикл, т. Е. Может ли он быть выпущен отдельно от других модулей или нет?

Если ответ « да» (а это относится к большинству проектов, которые были упомянуты в вопросе или в комментариях), тогда родительский pom нуждается в своем собственном модуле из VCS и с точки зрения Maven, и вы в конечном итоге получите с чем-то вроде этого на уровне VCS:

root
|-- parent-pom
|   |-- branches
|   |-- tags
|   `-- trunk
|       `-- pom.xml
`-- projectA
    |-- branches
    |-- tags
    `-- trunk
        |-- module1
        |   `-- pom.xml
        |-- moduleN
        |   `-- pom.xml
        `-- pom.xml

Это делает оформление заказа немного болезненным и распространенным способом справиться с этим является использование svn:externals. Например, добавьте trunksкаталог:

root
|-- parent-pom
|   |-- branches
|   |-- tags
|   `-- trunk
|       `-- pom.xml
|-- projectA
|   |-- branches
|   |-- tags
|   `-- trunk
|       |-- module1
|       |   `-- pom.xml
|       |-- moduleN
|       |   `-- pom.xml
|       `-- pom.xml
`-- trunks

Со следующим внешним определением:

parent-pom http://host/svn/parent-pom/trunk
projectA http://host/svn/projectA/trunk

Извлечение trunksможет привести к следующей локальной структуре (шаблон № 2):

root/
  parent-pom/
    pom.xml
  projectA/

При желании вы можете даже добавить pom.xmlв trunksкаталог:

root
|-- parent-pom
|   |-- branches
|   |-- tags
|   `-- trunk
|       `-- pom.xml
|-- projectA
|   |-- branches
|   |-- tags
|   `-- trunk
|       |-- module1
|       |   `-- pom.xml
|       |-- moduleN
|       |   `-- pom.xml
|       `-- pom.xml
`-- trunks
    `-- pom.xml

Это pom.xmlсвоего рода «фальшивый» пом: он никогда не выпускается, он не содержит реальной версии, поскольку этот файл никогда не выпускается, он содержит только список модулей. С этим файлом извлечение привело бы к этой структуре (образец # 3):

root/
  parent-pom/
    pom.xml
  projectA/
  pom.xml

Этот «хак» позволяет запустить сборку реактора из корня после проверки и сделать вещи еще более удобными. На самом деле, именно так мне нравится настраивать maven проекты и VCS-репозиторий для больших сборок : он просто работает, хорошо масштабируется, дает всю гибкость, которая может вам понадобиться.

Если ответ « нет» (вернемся к первоначальному вопросу), то я думаю, что вы можете жить с шаблоном № 1 (сделать самое простое, что могло бы сработать).

Теперь о бонусных вопросах:

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

Честно говоря, я не знаю, как не дать здесь общий ответ (например, «используйте уровень, на котором, по вашему мнению, имеет смысл взаимопонимание»). И вообще, дочерние помпы всегда могут переопределить унаследованные настройки.

  • Как плагин maven-release, hudson и nexus справляется с тем, как вы настраиваете свои мультипроекты (возможно, гигантский вопрос, более важно, если кто-нибудь узнает, когда была настроена мультипроектная сборка)?

Настройка, которую я использую, работает хорошо, ничего особенного упоминать.

На самом деле, мне интересно, как плагин maven-release-plugin работает с шаблоном № 1 (особенно с <parent>разделом, поскольку у вас не может быть зависимостей SNAPSHOT во время выпуска). Это похоже на проблему с курицей или яйцом, но я просто не могу вспомнить, работает ли она, и мне было лень это проверять.

Паскаль Тивент
источник
Это очень хорошо, так как я вижу, как оно масштабируется. Svn: externals отвечает на мои опасения, что это громоздко.
Джейми МакКриндл
@jamie Рад, что вы нашли это полезным.
Паскаль Тивент
1
Не могли бы вы рассказать о том, как заставить "взломать" работать? У меня есть проект стволов, и я ожидаю, что вы нацелились на опцию -pl с «запуском сборки реактора», но это представляет проблему при выполнении релиза для структуры, потому что эта опция также не переходит из сборки на корневой уровень. Могу ли я поместить его в параметр <arguments /> плагина release-Plugin. Поэтому релиз: выполнить неудачу, потому что он пытается работать на pom корневого уровня ...
Янв
Взлом svn: externals - самый полезный взлом svn, который я видел за долгое время. Очень полезно с проектами, которые имеют ветвления для каждого проекта в одном и том же хранилище.
омеркудать
1
Привет Паскаль, Как бы вы справились с версией #, если проекты, которые упомянуты в разделе модулей, не используют parent-pom в качестве <parent>, а some-other-project-parent-pom? Какие версии # мы получим для артефакта таких проектов (версия # артефакта в разделе <parent> этих проектов ИЛИ версия # проекта, в которой эти проекты перечислены как модули)? stackoverflow.com/questions/25918593/…
AKS
34

Исходя из моего опыта и лучших практик Maven, есть два вида «родительских помп»

  • «pom» родительский pom - этот pom содержит информацию и конфигурацию вашей компании, которые наследуют каждый pom и его не нужно копировать. Эти данные:

    • хранилища
    • разделы управления распределением
    • общие конфигурации плагинов (например, исходная и целевая версии maven-compiler-plugin)
    • организация, разработчики и т. д.

    Подготовку этого родительского pom следует выполнять с осторожностью, поскольку все pom вашей компании будут наследоваться от него, поэтому этот pom должен быть зрелым и стабильным (выпуск версии pom-родительского пакета не должен влиять на выпуск всех проектов вашей компании!)

  • Второй вид родительского пом - это многомодульный родитель. Я предпочитаю ваше первое решение - это стандартное соглашение maven для многомодульных проектов, очень часто представляющее структуру кода VCS

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

Мутлипроекты имеют структуру деревьев, поэтому вы не ограничены одним уровнем родительского помпа. Постарайтесь найти подходящую структуру проекта для ваших нужд - классический пример - как распределять многомодульные проекты

distibution/
documentation/
myproject/
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml
pom.xml

Несколько бонусных вопросов:

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

Эта конфигурация должна быть разумно разделена на родительский pom «компании» и родительский pom проекта. Вещи, относящиеся ко всему вашему проекту, переходят к «родительскому» предприятию, а это относится к текущему проекту - к одному из них.

  • Как плагин maven-release, hudson и nexus справляется с тем, как вы настраиваете свои мультипроекты (возможно, гигантский вопрос, более важно, если кто-нибудь узнает, когда была настроена мультипроектная сборка)?

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

cetnar
источник
1
Так что есть два типа родительских проектов / poms. Один без объявления <modules>. Это тот, который используется для наследования. И родительский проект с объявлением <multimodule>. Это тот, от которого не наследуются подмодули, это просто для управления созданием проекта Hold. Я прав ?
Лисак
22
  1. Независимый родительский узел - это лучшая практика для совместного использования конфигурации и параметров между несвязанными компонентами. У Apache есть родительский проект pom, чтобы поделиться юридическими уведомлениями и некоторыми распространенными вариантами упаковки.

  2. Если ваш проект верхнего уровня имеет реальную работу, такую ​​как агрегация javadoc или упаковка релиза, то у вас будут конфликты между настройками, необходимыми для этой работы, и настройками, которые вы хотите передать через родительский. Проект только для родителей избегает этого.

  3. Распространенный шаблон (на данный момент игнорирующий № 1): проекты с кодом используют родительский проект в качестве родительского, а верхний уровень - родительский. Это позволяет всем совместно использовать основные вещи, но позволяет избежать проблемы, описанной в # 2.

  4. Плагин сайта очень запутается, если родительская структура не совпадает со структурой каталогов. Если вы хотите создать агрегированный сайт, вам придется немного поиграть, чтобы обойти это.

  5. Apache CXF является примером шаблона в # 2.

bmargulies
источник
2
Я взглянул на ibilio, и многие проекты предпочитают «независимых» родителей. Hibernate, ActiveMQ, Jetty, XStream и т. Д. Это говорит о том, что это механизм defacto.
Джейми МакКриндл
2
Другой недостаток независимого родителя, по-видимому, заключается в том, что плагин релиза maven, по-видимому, хочет, чтобы родитель был прикреплен к версии, прежде чем он сделает релиз. Вероятно, не большая проблема, так как родитель не должен слишком сильно меняться.
Джейми МакКриндл
9

Есть один маленький улов с третьим подходом. Поскольку совокупные POM (myproject / pom.xml) обычно вообще не имеют родителя, они не разделяют конфигурацию. Это означает, что все эти агрегатные POM будут иметь только репозитории по умолчанию.

Это не проблема, если вы используете только плагины из Central, однако это не получится, если вы запустите плагин, используя формат plugin: goal из вашего внутреннего репозитория. Например, вы можете foo-maven-pluginс помощью groupId указать org.exampleцель generate-foo. Если вы попытаетесь запустить его из корня проекта с помощью команды like mvn org.example:foo-maven-plugin:generate-foo, он не сможет работать на агрегатных модулях (см. Примечание по совместимости ).

Возможны несколько решений:

  1. Разверните плагин в Maven Central (не всегда возможно).
  2. Укажите раздел репозитория во всех ваших агрегатных POM (ломает DRY принцип ).
  3. Настройте этот внутренний репозиторий в файле settings.xml (либо в локальных настройках в ~ / .m2 / settings.xml, либо в глобальных настройках в /conf/settings.xml). Сборка не удастся без этих settings.xml (может быть хорошо для больших внутренних проектов, которые никогда не должны создаваться за пределами компании).
  4. Используйте родительский с настройками репозиториев в ваших совокупных POM (может быть слишком много родительских POM?).
Иван Дубров
источник