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 знал, какие из них перезаписывают друг друга, а какие независимы.

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