Maven2 - проблема с pluginManagement и родительско-дочерними отношениями
Из Maven документации
pluginManagement: элемент, видимый вдоль боковых плагинов. Управление плагинами содержит элементы плагина почти таким же образом, за исключением того, что вместо настройки информации о плагинах для данной конкретной сборки проекта, она предназначена для настройки сборок проекта, которые наследуются от этой. Тем не менее, это только настраивает плагины, на которые фактически ссылаются в элементе plugins в дочерних элементах. Дети имеют полное право переопределять определения pluginManagement.
Теперь: если у меня есть это в моем родительском ПОМ
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<executions>
Some stuff for the children
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
и я запускаю mvn help:ffective-pom в родительском проекте, я получаю то, что хочу, а именно, часть плагинов, находящаяся непосредственно под сборкой (выполняющая работу), остается пустой.
Теперь, если я сделаю следующее:
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<executions>
Some stuff for the children
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<inherited>true</inherited>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
mvn help:ffective-pom Я снова получаю то, что хочу, плагины содержат только то, что объявлено, а раздел pluginManagement игнорируется.
НО меняется со следующим
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<executions>
Some stuff for the children
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<inherited>false</inherited> <!-- this perticular config is NOT for kids... for parent only -->
<executions>
some stuff for adults only
</execution>
</executions>
</plugin>
</plugins>
</build>
и запуск mvn help:ffective-pom, материал из раздела pluginManagement добавляется к тому, что уже объявлено. в качестве таких:
<build>
<pluginManagement>
...
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<inherited>false</inherited> <!-- this perticular config is NOT for kids... for parent only -->
<executions>
Some stuff for the children
</execution>
<executions>
some stuff for adults only
</execution>
</executions>
</plugin>
</plugins>
</build>
Есть ли способ исключить часть для детей из раздела родительского помона? По сути, я хочу, чтобы pluginManagement вел себя точно так, как указано в документации, то есть я хочу, чтобы он применялся только для детей, но не для проекта, в котором он объявлен.
Как следствие, есть ли способ, которым я могу переопределить части из pluginManagement, объявив плагин в разделе нормальной сборки проекта? что бы я ни пытался, я получаю, что этот раздел добавляется к выполнению, но я не могу переопределить тот, который уже существует.
РЕДАКТИРОВАТЬ:
Я никогда не находил приемлемого решения для этого, и как таковая проблема остается открытой. Ниже было предложено наиболее близкое решение, и в настоящее время оно является приемлемым решением для этого вопроса, пока не появится что-то лучшее. Сейчас есть три способа достижения желаемого результата (модулировать поведение плагина в зависимости от того, где в иерархии наследования находится текущее POM):
1 - при использовании профилей это будет работать, но вы должны помнить, что профили не наследуются, что несколько противоречит интуиции. Они (если активированы) применяются к POM, где они объявлены, и затем это сгенерированное POM распространяется вниз. Таким образом, единственный способ активировать профиль для дочернего POM заключается в командной строке (по крайней мере, я не нашел другого способа). Свойство, файл и другие средства активации не могут активировать POM, потому что триггер не находится в POM, где объявлен профиль.
2 - (это то, что я в итоге сделал) Объявите плагин как не унаследованный в родительском объекте и повторно объявите (скопируйте и вставьте) фрагмент в каждом дочернем элементе, где он требуется. Не идеально, но это просто, и это работает.
3 - Разделить природу агрегации и родительскую природу родительского POM. Тогда, поскольку часть, которая относится только к родителю, находится в другом проекте, теперь возможно использовать pluginManagement, как предполагалось вначале. Однако это означает, что должен быть создан новый искусственный проект, который не вносит вклад в конечный продукт, а только обслуживает систему. Это явный случай концептуального кровотечения. Также это относится только к моим конкретным и трудно обобщается, поэтому я отказался от попыток сделать эту работу в пользу не очень красивого, но более содержательного патча вырезания и вставки, описанного в 2.
Если кто-то сталкивался с этим вопросом, имеет лучшее решение, либо из-за моего недостатка знаний о Maven, либо из-за того, что у него появился инструмент, позволяющий это сделать, пожалуйста, опубликуйте решение здесь для дальнейшего использования.
Спасибо за вашу помощь:-)
4 ответа
Добавление конфигурации плагина в pluginManagement означает, что эта конфигурация будет использоваться, если плагин объявлен, но вам все равно нужно объявить плагин в разделе сборки любого POM, который хочет его использовать.
Ключевая часть, которая объясняет это из приведенного вами раздела:
Тем не менее, это только настраивает плагины, на которые действительно ссылаются в элементе плагины в дочерних
Поэтому, если вы сделаете это в дочернем pom, будет применена конфигурация от родителя:
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
</plugins>
</build>
Обновление: чтобы ответить на актуальный вопрос, содержимое раздела pluginManagement всегда объединяется с любым объявлением плагина. Чтобы родитель этого не сделал, вы можете определить раздел pluginManagement в профиле и активировать этот профиль в дочерних проектах, но не в родительском. Затем дочерние проекты должны будут объявить этот профиль.
Например:
<profiles>
<profile>
<id>for-children</id>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<executions>
<!--Some stuff for the children-->
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<inherited>false</inherited> <!-- this perticular config is NOT for kids... for parent only -->
<!--some stuff for adults only-->
</executions>
</plugin>
</plugins>
</build>
Я всегда думал, что дочерний POM может наследовать определение плагина из раздела pluginManagement своего родителя и указывать только те исполнения, которые он хочет запустить из этого плагина, ссылаясь на них по ID и привязывая выполнение к фазе. Пока родительское определение находится в pluginManagement (а не напрямую в плагинах) и не привязано к фазе, на этой фазе будет выполняться только определенное выполнение (с идентификатором).
Из прочтения вышеизложенного и из моей собственной текущей проблемы выглядит, что это не так: похоже, что дочерний POM унаследует всю конфигурацию плагина, включая все исполнения. С точки зрения выполнения, единственное, что может сделать дочерний элемент, это переопределить определенные значения - он не может выбрать, какие выполнения выполнять, а какие нет.
Это ошибка? Какая польза от возможности привязывать каждое выполнение к фазе (или нет), если будут выполняться все исполнения? Я видел это только с maven-dependency-plugin:unpack (привязан к фазе пакета), но с другими плагинами мне просто повезло...
Черт.
В родительском пом вы должны настроить выполнение с <goals>
заявлено, но не объявляется <phase>
, Тогда в детской помете вы объявите:
<plugin>
<artifactId>some-plugin</artifactId>
<executions>
<execution>
<id>execution-id</id>
<phase>partcular-phase</phase>
</execution>
</executions>
</plugin>
Плагин не будет выполнен, пока вы не определите фазу в дочернем пом. Таким образом, вам нужно будет явно привязать выполнение к фазам в каждом дочернем pom (или в середине иерархии), но вам не нужно будет копировать-вставлять конфигурацию этих выполнений.
Обратите внимание, что многие плагины имеют фазу по умолчанию, например, плагин Enforcer связан с validate
по умолчанию. Даже если вы не привязываете плагин к фазе явно, он все равно будет привязан и, следовательно, плагин будет выполнен. Чтобы преодолеть это, используйте несуществующую фазу в вашем родителе:
<execution>
<id>execution-id</id>
<goals><goal>some-goal</goal></goals>
<phase>none</phase>
</execution>
Вы должны назначить ID для выполнения, чтобы maven знал, какие из них перезаписывают друг друга, а какие независимы.