Подтвердить что ты не робот

Определите плагины Maven в родительском помпе, но только вызывайте плагины в дочерних проектах

У меня есть набор проектов, которые все должны запускать ту же серию исполнений плагинов Maven во время их сборки. Я бы хотел избежать повторного объявления всей этой конфигурации в каждом проекте, поэтому я сделал их все наследуемыми от родительского проекта "шаблон", который содержит только те плагины (8 разных моджо). Но я хочу, чтобы эти плагины выполнялись только для дочерних проектов, а не для родительского проекта во время сборки Maven.

Я попытался выполнить четыре разных способа, каждый из которых имеет побочный эффект, который мне не нравится.

  • Объявите выполнение плагинов в родительском pom build/plugins и используйте свойства-maven-plugin для включить свойства skip на других плагинов в родительском проекте. Это не сработало, потому что одна из целей плагина (maven-dependency-plugin: build-classpath) не имеет свойства skip.

  • Объявите выполнение плагинов в родительском pom build/pluginManagement. К сожалению, для этого требуется, чтобы я обновил каждый из восьми плагинов в элементе build/plugins каждого дочернего проекта pom, например:

    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
    </plugin>
    ...
    

    Это слишком повторяющееся и проблематичное, если мне когда-либо понадобится изменить плагины в шаблоне pom.

  • Объявлять выполнение плагинов в профиле родительского пом, который активируется отсутствием файла nobuild.txt (который существует в родительском помпе, поэтому плагины там не выполняются):

    <profiles>
        <profile>
            <activation>
                <file>
                    <missing>nobuild.txt</missing>
                </file>
            </activation>
            <build>
                ....
            </build>
        </profile>
    </profiles>
    

    Это работает по большей части, за исключением того, что путь к файлу в элементе missing, по-видимому, основан на текущем рабочем каталоге, а не на проекте. Это нарушает некоторые из многомодульных построений, которые я хотел бы сделать. Изменить:, чтобы прояснить, родительский "шаблонный" проект фактически сам является модулем в проекте с несколькими модулями, а сборка ломается, когда я пытаюсь, например, сделать mvn install в корне. Структура проекта выглядит следующим образом:

    + job
    |- job-core
    |- job-template
    |- job1                   inherits from job-template
    |- job2                   inherits from job-template
    
  • Настройте собственный жизненный цикл и упаковку. Это позволяет мне привязывать плагины к фазам жизненного цикла, но не указывать какую-либо конфигурацию.

Итак, есть ли другой способ указать кучу плагинов Maven, которые можно повторно использовать в нескольких проектах (с минимальным повторением в каждом из этих попов)?

4b9b3361

Ответ 1

В итоге я написал свой собственный плагин, который использует mojo-executor для вызова других моджо. Это позволяет мне: 1) централизовать конфигурацию сборки и 2) минимизировать объем конфигурации, который дублируется в каждом из дочерних проектов.

(Если вам интересно узнать причину всего этого: каждый дочерний проект - это задание, которое будет выполняться из командной строки. Строка устанавливает оболочку invoker script и присоединяет ее к поэтому он будет проверен в нашем репозитории артефактов. Развертывание script позже вытащит их на машину, на которой они будут работать.)

Соответствующие части шаблона project pom:

<project ...>
    <parent> ... </parent>
    <artifactId>job-template</artifactId>
    <packaging>pom</packaging>
    <name>job project template</name>
    <build>
        <pluginManagement>
            <plugin>
                <groupId>...</groupId>
                <artifactId>job-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>generate-sources-step</id>
                        <goals><goal>job-generate-sources</goal></goals>
                    </execution>
                    <execution>
                        <id>package-step</id>
                        <goals><goal>job-package</goal></goals>
                    </execution>
                    ... (a couple more executions) ...
                </executions>
            </plugin>
        </pluginManagement>
    </build>
</project>

Пришлось создать новый проект maven-plugin (job-maven-plugin). Pom выглядит так:

<project ...>
    <parent> ... </parent>
    <artifactId>job-maven-plugin</artifactId>
    <packaging>maven-plugin</packaging>
    <name>job maven executor plugin</name>
    <dependencies>
        <dependency>
            <groupId>org.twdata.maven</groupId>
            <artifactId>mojo-executor</artifactId>
            <!-- version 1.5 supports Maven 2, while version 2.0 only supports Maven 3 -->
            <version>1.5</version>
        </dependency>
    </dependencies>
</project>

Как вы можете видеть из проекта шаблона, в моем плагине было несколько моджо (по одной на фазу, в которой нуждались вещи). В качестве примера, mojo-пакет заданий связан с фазой пакета и использует библиотеку mojo-executor для запуска двух других mojos (которые просто присоединяют некоторые артефакты сборки):

/**
 * @goal job-package
 * @phase package
 */
public class PackageMojo extends AbstractMojo {
    /**
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    protected MavenProject project;
    /**
     * @parameter expression="${session}"
     * @required
     * @readonly
     */
    protected MavenSession session;
    /**
     * @component
     * @required
     */
    protected PluginManager pluginManager;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        ExecutionEnvironment environment = executionEnvironment(project, session, pluginManager);

        // Attach script as a build artifact
        executeMojo(
            plugin(
                groupId("org.codehaus.mojo"),
                artifactId("build-helper-maven-plugin"),
                version("1.7")
            ),
            goal("attach-artifact"),
            configuration(
                element("artifacts",
                    element("artifact",
                        element("file", "${project.build.directory}/script.shl"),
                        element("type", "shl")
                    )
                )
            ),
            environment
        );

        // Zip up the jar and script as another build artifact
        executeMojo(
            plugin(
                groupId("org.apache.maven.plugins"),
                artifactId("maven-assembly-plugin"),
                version("2.3")
            ),
            goal("single"),
            configuration(
                element("descriptors",
                    element("descriptor", "${project.build.directory}/job/descriptor.xml")
                )
            ),
            environment
        );
    }
}

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

<project ...>
    <parent>
        <groupId> ... </groupId>
        <artifactId>job-template</artifactId>
        <version> ... </version>
        <relativePath>../job-template</relativePath>
    </parent>
    <artifactId>job-testjob</artifactId>
    <name>test job</name>
    <build>
        <plugins>
            <plugin>
                <groupId> ... </groupId>
                <artifactId>job-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Кроме того, теперь структура всего многомодального каталога выглядит следующим образом:

+- job
  +- job-core
  +- job-maven-plugin
  +- job-template
  +- job-testjob1               (inherits from job-template)
  +- job-testjob2               (inherits from job-template)

На мой взгляд, это решение не совсем оптимально, так как теперь у меня теперь есть плагиновая конфигурация, встроенная в серию mojos вместо pom, но она отвечает моим целям для централизации конфигурации и минимизации дублирования среди дочерних проектов poms.

(последнее примечание: я только что обнаружил maven-aggregate-plugin, который, похоже, позволяет группировать несколько плагинов в pom. Это, возможно, решило проблему в немного более желательным образом, но я не в настроении повторить последние несколько часов работы. Возможно, это будет полезно для кого-то еще.)

Ответ 2

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

Проект должен быть построен правильно, просто выполнив mvn (clean) install.

Ответ 3

Здесь другой вариант я обнаружил здесь, ища решение той же проблемы. Я размещаю его здесь, потому что это уже хорошая коллекция опций - в надежде, что это может помочь другим не тратить часы на решение этой проблемы:

Учитывая, что плагин имеет возможность пропустить выполнение, этот параметр может быть включен в родительском pom (разделе), флаг "inherit" установлен в false, чтобы он не распространялся на детей:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
            <inherited>true</inherited>
            <configuration>
               ...
            </configuration>
        </execution>
    </executions>
    <!-- Skip plugin execution for parent pom but enable it for all children -->
    <configuration>
        <skipAssembly>true</skipAssembly>
    </configuration>
    <inherited>false</inherited>
</plugin>

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

Ответ 4

Еще один вариант: вместо использования свойства "skip" вы можете изменить фазу, выполнение связано с несуществующим значением, например never.

Это работает очень хорошо вместе с подходом <inherited>false</inherited>, предложенным @Timi

Ответ 5

Вот пятый путь. Я думаю, что у него есть минимальные недостатки: нет профилей, нет пользовательского жизненного цикла, нет деклараций в дочерних POM, нет необходимости пропускать плагины.

Скопировал его с fooobar.com/info/35559/... - много спасибо конечному пользователю !

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <!-- Main declaration and configuration of the plugin -->
                <!-- Will be inherited by children -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-checkstyle-plugin</artifactId>
                <version>2.9.1</version>
                <executions>
                    <execution>
                        <!--This must be named-->
                        <id>checkstyle</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
                <!-- You may also use per-execution configuration block -->
                <configuration...>
            </plugin>
        </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
            <!-- This declaration makes sure children get plugin in their lifecycle -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-checkstyle-plugin</artifactId>
            <!-- Configuration won't be propagated to children -->
            <inherited>false</inherited>
            <executions>
                <execution>
                    <!--This matches and thus overrides execution defined above -->
                    <id>checkstyle</id>
                    <!-- Unbind from lifecycle for this POM -->
                    <phase>none</phase>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>