【问题标题】:How to use Maven Exec Plugin as Library in another plugin?如何在另一个插件中使用 Maven Exec 插件作为库?
【发布时间】:2016-10-10 12:20:35
【问题描述】:

我目前正在使用 Exec Maven 插件,它适用于:

<plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>1.4.0</version>
      <executions>
        <execution>
          <id>myExec</id>
          <goals>
            <goal>exec</goal>
          </goals>
          <phase>generate-sources</phase>
          <configuration>
            <executable>myExec</executable>
            <arguments>
              <argument>--foo=${basedir}/src/test/resources/test.xml</argument>
              <argument>--output-directory=target/generated-sources/output</argument>
            </arguments>
          </configuration>
        </execution>
      </executions>
    </plugin> 

我也在使用 build helper 插件,如下:

<plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <version>1.10</version>
        <executions>
          <execution>
            <phase>generate-sources</phase>
            <goals>
              <goal>add-source</goal>
            </goals>
            <configuration>
              <sources>
                <source>${project.build.directory}/generated-sources/output</source>
              </sources>
            </configuration>
          </execution>
        </executions>
      </plugin>

然而,这非常冗长,我希望多个 maven 模块能够使用这个程序,而不必重新键入所有 exec 插件特定的 XML 以及构建器 XML。

问题:我如何将这两个组合到另一个插件中?

我已经使用 maven 原型生成器生成了一个示例 maven 插件并有一个 Mojo 类:

@Mojo(name = "touch", defaultPhase = LifecyclePhase.PROCESS_SOURCES)
public class MyMojo
        extends AbstractMojo
{


    public void execute()
            throws MojoExecutionException
    {
        ExecMojo exec = new ExecMojo();
    }
}

并且已经弄清楚如何创建一个新的 ExecMojo。

问题如何像在上面的 XML 中一样在此处添加参数?以及如何将这些参数集成到我的插件中?

【问题讨论】:

标签: java maven maven-plugin exec-maven-plugin


【解决方案1】:

您可以考虑以下方法,而不是创建自己的 Maven 插件,这可能会降低项目的可移植性和可维护性:

  • 有一个共同的parent pom
  • 配置给定的插件配置,可选在Maven profile
  • 在相关模块中,指向此父级。可以选择(在配置文件的情况下)在需要时按需激活它。

一个简单的父 pom 如下所示:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sample</groupId>
    <artifactId>sample-maven-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <path.to.myexec>path</path.to.myexec>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.4.0</version>
                <executions>
                    <execution>
                        <id>myExec</id>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                        <phase>generate-sources</phase>
                        <configuration>
                            <executable>${path.to.myexec}\myExec</executable>
                            <arguments>
                                <argument>--foo=${basedir}/src/test/resources/test.xml</argument>
                                <argument>--output-directory=${project.build.directory}/generated-sources/output</argument>
                            </arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.10</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>${project.build.directory}/generated-sources/output</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>myexec-profile</id>
            <build>
                <plugins>
                    <!-- optionally move here the configuration above -->
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

注意我添加的path.to.myexec 属性,如果需要,将在子项目中覆盖,以指向正确的相对路径。

然后,一旦安装在您的机器中(或部署在您公司的 Maven 存储库中),就可以在任何相关的 Maven 项目中引用如下:

<parent>
    <groupId>com.sample</groupId>
    <artifactId>sample-maven-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>

无需重新声明上面的插件配置及其详细方法。它们将自动成为默认构建的一部分,作为从该父级继承的构建配置的一部分。


如果满足以下条件,分析方法也可以是一种解决方案:

  • 您希望重用已由不需要此配置的项目使用的现有父 pom
  • 您并不总是需要在构建中使用此行为,而是希望按需激活它

在这种情况下,您可以通过以下方式激活它,例如:

mvn clean package -Pmyexec-profile

鉴于您已经相应地设置了父级,并且您已将上述配置移至配置文件中。


这种方法的优点

  • 比编写新的 maven 插件(需要编写、测试、维护、分发等)更轻松的选择
  • 消费者模块更容易定制某些东西:在任何时候他们都可以将父级的配置作为例外覆盖
  • 不那么脆弱:想象一下,如果其中一个插件的另一个版本提供了对您很重要的错误修复,那么配置 XML 很容易,更改自定义的 maven 插件等更不容易。
  • 配置保持集中、透明地访问和进一步治理的入口点
  • 更容易排除故障:消费者模块可以随时运行 mvn help: effective-pom 并查看合并后的完整有效 pom(作为父 pom 和当前 pom 的聚合)并检查它实际运行的内容

如何跳过某些模块中的父插件执行

仅在某些模块中执行此插件的简单(并且经常使用)方法,同时使父模块与其他模块相同:

  • 定义一个新属性,我们称之为skip.script.generation,默认值为true,在父pom中定义。
  • 在上述插件的skip 配置条目中使用此跳过属性。
  • 仅在相关模块中重新定义属性并将其设置为false。这将是他们的 pom.xml 文件所需的唯一配置,因此减少到一行(保持非常低的详细程度)。

exec-maven-plugin 提供了这样的skip 选项,不幸的是build-helper-maven-plugin 没有。但这并没有阻止我们。我们仍然可以跳过使用phase 元素的两个执行,将其设置为不存在的阶段,如none 并因此跳过它们。这是合适的,因为这两个执行实际上已经附加到同一阶段,generate-sources

对于这种方法,让我们将新属性重命名为 script.generation.phase

举个例子:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sample</groupId>
    <artifactId>sample-maven-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <path.to.myexec>path</path.to.myexec>
        <script.generation.phase>none</script.generation.phase>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.4.0</version>
                <executions>
                    <execution>
                        <id>myExec</id>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                        <phase>${script.generation.phase}</phase>
                        <configuration>
                            <executable>${path.to.myexec}\myExec</executable>
                            <arguments>
                                <argument>--foo=${basedir}/src/test/resources/test.xml</argument>
                                <argument>--output-directory=${project.build.directory}/generated-sources/output</argument>
                            </arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.10</version>
                <executions>
                    <execution>
                        <phase>${script.generation.phase}</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>${project.build.directory}/generated-sources/output</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>myexec-profile</id>
            <build>
                <plugins>
                    <!-- optionally move here the configuration above -->
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

注意两个插件的&lt;phase&gt;${script.generation.phase}&lt;/phase&gt; 更改。默认值为none,此属性在默认情况下有效地禁用了它们的执行。

在另一个模块中,您将拥有以下内容:

<parent>
    <groupId>com.sample</groupId>
    <artifactId>sample-maven-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>

<properties>
    <script.generation.phase>generate-sources</script.generation.phase>
</properties>

没有别的了。那是。 Maven 在构建期间会重新定义某个模块的属性,并在从其父模块继承的配置中自动替换它,从而再次启用上述两个执行。

【讨论】:

  • 很好的答案,但我有几个后续问题。如果我使用父 pom 方法,这个可执行文件是否会在每个 maven 子模块中自动调用?我想将其配置为仅在某些子模块中调用此可执行文件。还有一种方法可以在每次构建期间运行配置文件吗?看起来这对我们来说可能是更好的解决方案,但这是我们想要融入特定子模块 pom 并始终运行的东西,因为这会为模块生成所需的代码。
  • @lnunno 是的,默认情况下它们将被所有模块调用,但是有一些方法可以只在某些模块中执行,最简单的方法是默认通过属性跳过它们并重新- 在您希望它们被执行的模块中定义这个属性(并且只有这个属性)。我会用一个例子来更新我的答案。
  • @lnunno 我在答案的底部添加了一种关于如何仅对某些模块启用这些执行的方法,在子模块中的详细程度非常低,只需要一行额外的配置。
  • 我们的构建过程最终变得足够复杂,以至于我们开始了一个纯 XML 实现并很快碰壁,我最终创建了一个 Maven 插件,它并不太复杂,也没有太多代码获得我们正在寻找的功能。
猜你喜欢
  • 2016-02-27
  • 2011-11-11
  • 2014-07-10
  • 1970-01-01
  • 2018-03-07
  • 1970-01-01
  • 2017-05-11
  • 1970-01-01
相关资源
最近更新 更多