【问题标题】:Error when execute MavenCli in the loop (maven-embedder)?在循环(maven-embedder)中执行 MavenCli 时出错?
【发布时间】:2014-03-14 16:27:58
【问题描述】:

当我在循环中执行maven命令时有什么问题?目标是更新包列表的 pom.xml 版本。第一次迭代,maven 执行正确(更新 pom.xml),但之后的所有项目都会出错。

for (String bundlePath: bundlesToUpdate)
{
    MavenCli cli = new MavenCli();
String[] arguments = {
    "-Dtycho.mode=maven", 
        "org.eclipse.tycho:tycho-versions-plugin:set-version", 
    "-DgenerateBackupPoms=false", 
    "-DnewVersion=" + version};
    int result = cli.doMain(arguments, bundlePath, System.out, System.err);
}

与代码相同的错误:

`MavenCli cli = new MavenCli();
for (String bundlePath: bundlesToUpdate) 
{
    String[] arguments = {
    "-Dtycho.mode=maven", 
    "org.eclipse.tycho:tycho-versions-plugin:set-version", 
    "-DgenerateBackupPoms=false", 
    "-DnewVersion=" + version};
int result = cli.doMain(arguments, bundlePath, System.out, System.err);
}`

第一次,没关系:

[main] INFO org.eclipse.tycho.versions.manipulation.PomManipulator -   pom.xml//project/version: 2.2.6-SNAPSHOT => 2.2.7-SNAPSHOT
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - ------------------------------------------------------------------------
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - Reactor Summary:
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - 
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - XXXX project   ....................... SUCCESS [  0.216 s]
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - com.sungard.valdi.bus.fixbroker.client.bnp ........ SKIPPED
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - XXX project Feature ...................... SKIPPED
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - ------------------------------------------------------------------------
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - BUILD SUCCESS

之后的错误是:

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

【问题讨论】:

  • 我在下面的答案中找到了解决方案。

标签: java maven maven-embedder


【解决方案1】:

我找到的解决方案是使用 Maven Invoker,它适用于相同的功能:

    public class MavenInvoker {

    public static void main(String[] args) throws IOException, NoHeadException, GitAPIException 
{
    MavenInvoker toto = new MavenInvoker();

    toto.updateVersionMavenInvoker("2.2.8-SNAPSHOT", "TECHNICAL\\WEB" );
}

private InvocationRequest request = new DefaultInvocationRequest();
private DefaultInvoker invoker = new DefaultInvoker();

public InvocationResult updateVersionMavenInvoker(String newVersion, String folderPath)
{
    InvocationResult result = null;
    request.setPomFile( new File(folderPath+"\\pom.xml" ) );

    String version =  "-DnewVersion="+newVersion;
    request.setGoals( Arrays.asList("-Dtycho.mode=maven", 
            "org.eclipse.tycho:tycho-versions-plugin:set-version", 
            "-DgenerateBackupPoms=false", 
            version) );
    try {
        result = invoker.execute( request );
    } catch (MavenInvocationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return result;
}

}

【讨论】:

    【解决方案2】:

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

    ClassRealm classRealm = (ClassRealm) Thread.currentThread().getContextClassLoader();
    MavenCli cli = new MavenCli(classRealm.getWorld());
    cli.doMain( ... );
    

    plexus Launcher sets the context class loader 到它的ClassRealm,它可以访问“全局”ClassWorld

    不确定该解决方案的稳定性如何,但目前看起来不错。

    使用过的进口:

    import org.codehaus.plexus.classworlds.ClassWorld;
    import org.codehaus.plexus.classworlds.realm.ClassRealm;
    import org.apache.maven.cli.MavenCli;
    

    【讨论】:

    • 它给出了类转换异常
    • 这很有用,但我发现了我必须做的艰难方法: final ClassRealm classRealm = (ClassRealm) Thread.currentThread().getContextClassLoader(); final ClassWorld classWorld = classRealm.getWorld(); classWorld.disposeRealm("maven.ext"); final MavenCli cli = new MavenCli(classWorld);
    • 很遗憾官方文档太小了以至于几乎没用,包括Javadocs(!),可悲的是很多Apache,Maven似乎是最糟糕的部分之一,但至少我可以在 Github 上查看 Maven 插件源代码...
    • 我得出了一个痛苦的结论,MavenCli 在插件中不可用,日志被弄乱了,所以 IDEA 认为它已经过早停止了!我查看了 Maven Invoker 插件使用的 Apache Maven Invoker 库,它为 Maven EXE 构建了一个 CLI 字符串并运行它!这明显是对自己的库缺乏信心!!!
    • 我感觉到你了。我假设解决方案可能长期不稳定。不幸的是,我不知道更多,没有在较新的 Maven 版本中再次使用该代码。
    【解决方案3】:

    更详细的解释请参见邮件主题:https://dev.eclipse.org/mhonarc/lists/sisu-users/msg00063.html

    似乎正确的方法是在构造时给MainCli 一个ClassWorld 实例,以便它可以通过多次调用保持正确的状态。

    例子:

    final ClassWorld classWorld = new ClassWorld("plexus.core", getClass().getClassLoader());
    MavenCli cli = new MavenCli(classWorld);
    String[] arguments = {
        "-Dtycho.mode=maven", 
            "org.eclipse.tycho:tycho-versions-plugin:set-version", 
        "-DgenerateBackupPoms=false", 
        "-DnewVersion=" + version};
    int result = cli.doMain(arguments, bundlePath, System.out, System.err);
    

    【讨论】:

    • 这在 Maven 插件中对我不起作用。但这将我引向正确的方向,请参阅我的答案。谢谢!
    猜你喜欢
    • 2016-01-28
    • 1970-01-01
    • 1970-01-01
    • 2020-02-21
    • 2013-06-12
    • 2016-02-04
    • 1970-01-01
    • 1970-01-01
    • 2017-08-21
    相关资源
    最近更新 更多