java - 在 Maven 插件中调用 MavenCli 失败

标签 java maven maven-plugin maven-embedder

我创建了一个小工具来包装 MavenCli,它使用 quickstart 原型(prototype)生成一个新的 Maven 项目。

当作为单元测试执行 Util 时,它运行良好(只是生成一个空的 Maven 项目)。

现在我想将这个小包装器集成到 Maven 插件中。但是当我执行 mojo(在第三个 Maven 项目中)时,MavenCli 的调用失败并出现异常:

[ERROR] Error executing Maven.
[ERROR] java.util.NoSuchElementException
  role: org.apache.maven.eventspy.internal.EventSpyDispatcher
  roleHint: 
[ERROR] Caused by: null

实用程序看起来像:

public void createProject() {
    final MavenCli cli = new MavenCli();
    System.setProperty("maven.multiModuleProjectDirectory", "/usr/share/maven");
    cli.doMain(new String[] { "archetype:generate", "-DgroupId=com.my.company",
            "-DartifactId=hello-world", "-DarchetypeArtifactId=maven-archetype-quickstart",
            "-DinteractiveMode=false" }, "/tmp", System.out, System.out);
}

util的相关依赖:

<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-embedder</artifactId>
    <version>3.3.9</version>
</dependency>
<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-core</artifactId>
    <version>3.3.9</version>
</dependency>

mojo 代码如下:

@Mojo(name = "custommojo", requiresProject = false)
public class CustomMojo extends AbstractMojo {

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        Util.createProject();
    }

}

mojo 的 POM 仅包含对相关 Maven Artifact (插件 API、插件注释等)和实用程序的依赖项。

我提到的第三个项目是一个空的“maven-quickstart”项目,它依赖于 mojo-project 和 mojo 在编译阶段执行的配置。

我不知道为什么它在单元测试的上下文中有效,但在 mojo 的上下文中却无效。

有人可以帮忙吗?

最佳答案

这是一个类加载问题。

MavenCli 将尝试从当前线程的上下文类加载器加载类。在 Maven 插件内部,有 a special, restricted, classloader ,它可以访问:

  • 自己的类(class);
  • 在其依赖 block 中使用的类;
  • 导出类作为项目可能构建扩展的一部分;
  • 从 Maven 核心和核心扩展中导出类;
  • 并将引导类加载器作为父级。

但是,特定类 org.apache.maven.eventspy.internal.EventSpyDispatcher 是 Maven 核心的一部分,但是 it is not part of the exported APIs (包 org.apache.maven.eventspy 未列为 exportedPackage)。所以插件无法加载那个类。这也是它在您的测试中起作用的原因:您不在插件内部,因此类加载器不同并且可以访问该类。

您甚至无法为插件显式添加对 maven-core 的依赖:它将被丢弃,因为它应该已经提供了。

这里有两种解决方案:

  • 不要在插件中使用 Maven Embedder API,而是使用 Invoker API .两者之间的区别在于 Invoker API 将在干净的环境中启动 Maven,与当前环境完全不同。由于它重新开始一切,因此您不会遇到任何类加载问题。
  • 使用mojo-executor库,它提供了一种从 Maven 插件中调用其他 Mojo 的简单方法。您可以在此处使用它来调用 archetype:generate Mojo。

关于java - 在 Maven 插件中调用 MavenCli 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40587683/

相关文章:

java - Android:抽屉导航图标

java - Ant 使用了错误的 java 版本

maven - 如何使用 Maven 组合 jar?

java - 在 debain 6.0.1 亚马逊 EC2 实例中安装 selenium webdriver

java - Maven 插件 MOJO 在解决依赖关系时会停止构建

java - 是否可以使用 Nexus 镜像私有(private) Maven S3 存储库?

java - 如何使用spinner和image传递之前的数据?

java - 线程中的异常 "main"java.lang.IndexOutOfBoundsException : Index: 10, 大小:10

string - Java/Maven无法编译简单代码

java - 获取jmeter功能测试代码覆盖率