首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Maven插件中调用MavenCli失败

在Maven插件中调用MavenCli失败
EN

Stack Overflow用户
提问于 2016-11-14 11:28:32
回答 3查看 1K关注 0票数 3

我创建了用于包装MavenCli的小util,它使用快速启动原型生成了一个新的Maven项目。

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

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

代码语言:javascript
复制
[ERROR] Error executing Maven.
[ERROR] java.util.NoSuchElementException
  role: org.apache.maven.eventspy.internal.EventSpyDispatcher
  roleHint: 
[ERROR] Caused by: null

它看起来像:

代码语言:javascript
复制
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);
}

与该用途有关的依赖性:

代码语言:javascript
复制
<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代码看起来像:

代码语言:javascript
复制
@Mojo(name = "custommojo", requiresProject = false)
public class CustomMojo extends AbstractMojo {

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

}

mojo的POM只包括对相关Maven工件的依赖(plugin、plugin-注释等)。还有功用。

我提到的第三个项目是一个空的“maven-快速启动”项目,它依赖于mojo -项目,并配置了在编译阶段执行的mojo。

我不知道为什么它在单元测试的上下文中工作,但不知道它为什么在一个mojo上下文中工作。

有人能帮忙吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-11-14 14:16:45

这是一个类加载问题。

MavenCli将尝试从当前线程的上下文类加载器加载类。在Maven插件中,有一种特殊的、受限的类装入器,它可以访问:

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

但是,特定的类org.apache.maven.eventspy.internal.EventSpyDispatcher是Maven核心的一部分,但是它不是导出的APIs的一部分。 (包org.apache.maven.eventspy没有被列为exportedPackage)。所以插件不能加载该类。这也是它在您的测试中工作的原因:您不在插件中,所以类加载程序是不同的,并且可以访问该类。

您甚至都无法通过为插件添加一个对maven-core的依赖说明而逃脱:因为它应该已经提供了,所以它将被删除。

这里有两个解决方案:

  • 不要在插件中使用Maven Embedder,而是使用调用程序API。两者的区别在于,调用方API将在干净的环境中启动Maven,与当前环境完全不同。因为它重新启动了所有东西,所以您不会有任何类加载问题。
  • 使用莫霍-遗嘱执行人库,它提供了一种从Maven插件中调用其他Mojos的简单方法。您可以在这里使用它来调用archetype:generate Mojo。
票数 5
EN

Stack Overflow用户

发布于 2017-12-07 08:21:19

这在自定义maven插件(使用Maven 3.5.0)中适用于我:

代码语言:javascript
复制
ClassRealm classRealm = (ClassRealm) Thread.currentThread().getContextClassLoader();
MavenCli cli = new MavenCli(classRealm.getWorld());
cli.doMain( ... );

丛启动器设置上下文类加载器。到它的ClassRealm,它可以访问“全局”ClassWorld

不确定这个解决方案有多稳定,但到目前为止看起来还不错。

二手进口品:

代码语言:javascript
复制
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.apache.maven.cli.MavenCli;
票数 1
EN

Stack Overflow用户

发布于 2018-12-20 22:58:52

@Alexander:

您的回答

但是,您的代码给了我一个ClassCast异常:

代码语言:javascript
复制
Exception in thread "main" java.lang.ClassCastException: sun.misc.Launcher$AppClassLoader cannot be cast to org.codehaus.plexus.classworlds.realm.ClassRealm
    at com.misys.tools.integration.codegen.cli.cmd.InstallApi.mavenInstallMchApi(InstallApi.java:58)
    at com.misys.tools.integration.codegen.cli.cmd.InstallApi.run(InstallApi.java:50)
    at com.misys.tools.integration.codegen.cli.OpenApiGen.main(OpenApiGen.java:26)

我成功地将代码重写为:

代码语言:javascript
复制
MavenCli cli = new MavenCli(new ClassWorld("maven",Thread.currentThread().getContextClassLoader()));

然后,随后对嵌入式maven的2次doMain调用成功!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40587683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档