如何以编程方式从 pom.xml 执行特定的插件/Mojo?

Posted

技术标签:

【中文标题】如何以编程方式从 pom.xml 执行特定的插件/Mojo?【英文标题】:How to execute a specific plugin/Mojo from a pom.xml programmatically? 【发布时间】:2015-02-12 08:22:14 【问题描述】:

我是其中一个 Maven 插件(不是 Apache/Codehaus,完全独立)的作者。有时我收到支持请求或测试用例,我真的需要使用现有的pom.xml 调试我的插件的执行。基本上我得到的测试用例是样本/测试项目(pom.xmlsrc/main/resouressrc/main/java 等等)。

我需要的是一种方法:

加载现有的pom.xml。 在那里找到我的插件的特定执行(通常是唯一的)。 获取MyMojo 的实例 - 完全初始化/配置,所有组件和参数都正确注入。 执行MyMojo。 重要的是测试项目是独立的项目,我不想将它们复制到插件的 Maven 模块中。 我希望无需远程调试也能做到这一点。

通过调试,我的意思是能够设置和暂停断点(也是有条件的),在源代码上单步执行/退出/跳过。

理想情况下,我希望能够 executeMyMojoFrom(new File("pom.xml")) - 例如在 JUnit 测试或某个类的 main 方法中。 (我可以提供groupIdartifactId 等。所有其他定义都应该从pom.xml 加载。)

我怎样才能做到这一点?


到目前为止我已经尝试过:

Eclipse 中 pom.xml 上的 Debug As... - 运行不佳(未找到源代码,断点不起作用,因为它不是 Java 项目上下文) Maven Embedder/Invoker 解决方案 - 通过 CLI 在单独的进程中生成事物。忘记断点,无需调试。 使用 mvnDebug 进行远程调试,然后按照 Pascal Thivent here 的建议从 Eclipse 进行远程调试。这是迄今为止最好的选择。但是,远程调试意味着单独启动mvnDebug,也不能保证我在Eclipse 中的JAR 与mvnDebug 使用的完全一样。所以这里有一定的距离。 maven-plugin-testing-harness - 我实际上认为这可以完成任务。但首先我要跳几个小时才能开始。所有重要的依赖项都是“提供”的,所以我首先必须找出这些工件的正确版本组合。然后 - 才发现 AbstractMojoTestCase 仅在您要测试的插件模块中工作。当我认为maven-plugin-testing-harness 是 Maven 插件的测试工具时,可能我错了。似乎它是该插件模块中插件的测试工具。这不是不合逻辑的,但对我的情况没有帮助。我想在 other 模块中测试我的插件。

所以现在我使用远程调试解决方案获得了最好的结果。但我正在寻找的实际上是 maven-plugin-testing-harness 之类的东西,但没有硬连线到插件模块。如果 Maven 工件中某处存在这样的方法,是否有人碰巧有提示?

更具体地说,我想写一些类似的东西:

 public void testSomething()
        throws Exception
    
        File pom = getTestFile( "pom.xml" );
        assertNotNull( pom );
        assertTrue( pom.exists() );

        MyMojo myMojo = (MyMojo) lookupMojo( "myGroupId", "myArtifactid", ...,
                                             "myGoal", pom );
        assertNotNull( myMojo );
        myMojo.execute();

        ...
    

将其与 MyMojoTest here 进行比较 - 它几乎就在那里。不应该硬连线到mymojo Maven 模块中(就像在maven-plugin-testing-harness 中一样)。


更新

cmets中问题的几个答案:

您的意思是您不希望这样的测试类,即MyMojoTestMyMojo 驻留在同一个项目中,即您的插件项目?这是为什么呢?

没错。我想调试现有 Maven 项目中的插件执行,我不想将该项目移动到我的插件项目 first 以便能够运行测试。我希望能够测试/调试现有项目。理想情况下,我只需要在项目的 src/test/jaca 中添加 my-maven-plugin-testing 依赖项和子类 MyMojoTest。这将是调试执行的好工具。将目标项目拖到我的 Mojo 项目中的开销太大——而且大多数情况下,这些并不是我想要长期保留的测试用例。我希望,这个答案,为什么。

无论如何,将project-to-test/pom.xml 保留在插件模块的src/test/resources 内只是一个惯例,而不是规则...

我的问题不是project-to-testpom.xml 的位置,这很容易配置。我的困难是maven-plugin-testing-harness 以某种方式被硬编码为Mojo 的项目。它使用 Mojo 的pom.xml,在包含的项目中查找其他特殊文件/描述符。所以我不能在非 Mojo 项目中使用它,或者我可以吗?这是我的问题。

我不知道为什么Debug as... 没有帮助你...

也不确定,但是 (1) 断点不起作用并且 (2) 源代码由于某种原因没有“附加”。

【问题讨论】:

我建议在这里更深入地了解一下:github.com/ifedorenko/com.ifedorenko.m2e.mavendev BTW:您开发的是哪个插件? @khmarbaise 谢谢,我去看看。我开发了maven-jaxb2-plugin @khmarbaise我查过了,这也太m2e-centric,我可以实现与远程调试相同类型的调试。我想要的是在测试中从特定的pom.xml 执行 mojo 的可能性。不过还是谢谢你的提示。 您的意思是您不希望这样的测试类,即MyMojoTestMyMojo 驻留在同一个项目中,即您的插件项目?这是为什么?无论如何,将project-to-test/pom.xml 保留在插件模块的src/test/resources 中只是一种约定,而不是规则,就像在src/test/java/org/apache/maven/plugin/my 目录中创建MyMojoTest 一样。 我不知道为什么Debug as... 没有帮助你 - 每当我想调试我的插件或任何 maven 插件时,它总是对我有用。 【参考方案1】:

如果 Debug as 对您的工作效果不佳,您可以尝试使用 mojo-executor 并稍作调整。

https://github.com/TimMoore/mojo-executor

这就是您将如何以编程方式执行Maven Dependency Plugincopy-dependencies 目标:

executeMojo(
    plugin(
        groupId("org.apache.maven.plugins"),
        artifactId("maven-dependency-plugin"),
        version("2.0")
    ),
    goal("copy-dependencies"),
    configuration(
        element(name("outputDirectory"), "$project.build.directory/foo")
    ),
    executionEnvironment(
        mavenProject,
        mavenSession,
        pluginManager
    )
);

projectsessionpluginManager 变量应该通过正常的 Mojo 注入来注入。是的,这意味着这应该从另一个 Maven 插件的上下文中执行。现在我想了想,这是否对您有任何帮助仍然是一个问题,因为这仍然依赖于底层plexus 容器对此类组件的注入。

我最初的想法是让你构建一个 maven 插件,它会像上面一样通过 mojo-executor 调用你的 jaxb2 插件,然后序列化 mavenProjectmavenSessionpluginManager,即所有plexus 注入组件,然后使用这些对象在将来从没有您构建的插件的独立类中调用您的 jaxb2 插件。

【讨论】:

以上是关于如何以编程方式从 pom.xml 执行特定的插件/Mojo?的主要内容,如果未能解决你的问题,请参考以下文章

如何从单个父 pom.xml 构建具有不同版本的插件?

在 pom.xml 中使用 Apache CXF Codegen 插件时出错。尝试更新 maven 时执行标记中出错。如何解决这个问题?

如何以编程方式从 NSString 中删除特定字符?

从代码中的 maven pom.xml 检索版本

如何从 .NET 类中以编程方式访问服务器级 IIS 连接设置?

当我有多个用于该目标的配置时,如何在 Maven 插件中使用特定配置运行特定目标