在 Maven 插件中调用 MavenCli 失败 [英] Invocation of MavenCli fails within a Maven plugin

查看:91
本文介绍了在 Maven 插件中调用 MavenCli 失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个小 util 来包装 MavenCli,它使用快速入门原型生成一个新的 Maven 项目.

I've created small util to wrap MavenCli, which generates a new Maven project, using the quickstart archetype.

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

When executing the Util as a unit test, it is working quite well (just generating an empty Maven project).

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

Now I want to integrate this small wrapper into a Maven plugin. But when I execute the mojo (within a third Maven project), the invocation of MavenCli fails with exception:

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

util 看起来像:

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 的相关依赖:

relevant dependency of the 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 工件(插件 API、插件注释等)和 util 的依赖.

The POM of the mojo just includes dependencies to relevant Maven artifacts (plugin-api, plugin-annotation, etc.) and the util.

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

The third project I mentioned, is an empty "maven-quickstart" project which have dependency to the mojo-project and a configuration for the mojo to execute in compile phase.

我不知道为什么它在单元测试的上下文中有效,而不是在 mojo 的上下文中.

I have no idea why it works in context of unit test, but not in context of a mojo.

有人可以帮忙吗?

推荐答案

这是一个类加载问题.

MavenCli 将尝试从当前线程的上下文类加载器加载类.在 Maven 插件内部,有 一个特殊的、受限的类加载器,它可以访问:

MavenCli will try to load classes from the context classloader of the current thread. Inside of a Maven plugin, there is a special, restricted, classloader, which has access to:

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

然而,特定的类 org.apache.maven.eventspy.internal.EventSpyDispatcher 是 Maven 核心的一部分,但是 它不是导出的 API 的一部分(包 org.apache.maven.eventspy 未列为 exportedPackage).因此插件无法加载该类.这也是它在您的测试中工作的原因:您不在插件内部,因此类加载器不同并且可以访问该类.

However, the specific class org.apache.maven.eventspy.internal.EventSpyDispatcher is part of Maven core, but it is not part of the exported APIs (the package org.apache.maven.eventspy is not listed as an exportedPackage). So the plugin cannot load that class. This is also why it works in your tests: you're not inside of a plugin, so the classloader is different and has access to that class.

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

You won't even be able to get away with adding explictly a dependency on maven-core for the plugin: it will be disgarded since it is supposedly already provided.

这里有两种解决方案:

  • Don't use the Maven Embedder API from within a plugin, but the Invoker API. The difference between the two is that the Invoker API will launch Maven in a clean environment, completely distinct with regard to the current one. Since it starts everything anew, you won't have any classloading issue.
  • Use the mojo-executor library, that provides an easy way to invoke other Mojos from within a Maven plugin. You could use it here to invoke the archetype:generate Mojo.

这篇关于在 Maven 插件中调用 MavenCli 失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆