2016-11-14 6 views
2

quickstartのアーキタイプを使用して新しいMavenプロジェクトを生成するMavenCliをラップする小さなutilを作成しました。Mavenプラグイン内でのMavenCliの呼び出しが失敗しました

ユニットテストとしてUtilを実行すると、非常にうまくいっています(空のMavenプロジェクトを生成するだけです)。

今、この小さなラッパーをMavenプラグインに統合したいと考えています。しかし、私は(第3 Mavenプロジェクト内)モジョを実行すると、MavenCliの呼び出しが例外で失敗します。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); 
} 

関連する依存関係:

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

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(name = "custommojo", requiresProject = false) 
public class CustomMojo extends AbstractMojo { 

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

} 

mojoのPOMには関連するMaven成果物(plugin-api、plugin-annotationなど)とutilの依存関係が含まれています。

私が言及した3番目のプロジェクトは、mojoプロジェクトに依存する空の "maven-quickstart"プロジェクトと、mojoがコンパイル段階で実行するための設定です。

私は単体テストのコンテキストでは動作するが、mojoのコンテキストでは動作しない理由は知らない。

誰でも手伝いできますか?

答えて

3

これはクラス読み込みの問題です。

MavenCliは、現在のスレッドのコンテキストクラスローダーからクラスをロードしようとします。 Mavenプラグインの内部には、a special, restricted, classloaderがあります。

  • 独自のクラスです。
  • 依存関係ブロックで使用されるクラス。
  • プロジェクトのビルド拡張の一部としてエクスポートされたクラス。
  • Mavenコアとコア拡張からエクスポートされたクラス。
  • であり、ブートストラップクラスローダーが親として存在します。

しかし、特定のクラスorg.apache.maven.eventspy.internal.EventSpyDispatcherはMavenのコアの一部であるが、it is not part of the exported APIs(パッケージorg.apache.maven.eventspyexportedPackageとしてリストされていません)。そのため、プラグインはそのクラスをロードできません。これはあなたのテストでも動作します:プラグインの中にいないので、クラスローダーは違っていて、そのクラスにアクセスできます。

maven-coreにプラグインの依存関係を明示的に追加することもできません。すでに提供されているため、廃止されます。

2つの解決策はここにあります

  • は、プラグインの中からMavenのエンベッダのAPIを使用しますが、Invoker APIしないでください。 2つの違いは、Invoker APIがクリーンな環境でMavenを起動し、現在のものとはまったく異なる点です。新しいものがすべて始まるので、クラスローディングの問題はありません。
  • mojo-executorライブラリを使用すると、Mavenプラグイン内から他のモホを簡単に呼び出すことができます。こちらを使用してarchetype:generateモジョを呼び出すことができます。
+0

あなたにたくさんありがとう - 私が示唆したようにAPIを呼び出し側に切り替え - そしてそれはかなりうまく動作します。注:Embedder APIを使用する前に、私はすでにmojo-executorを使用しようとしましたが、成功しなかったので、ライフサイクル全体(例えば "install")を実行するのが難しいため、mojo-executorは "archetype:generate"他のプロジェクトでmojoを呼び出そうとすると設定が難しい(特に、この他のプロジェクトが現在のビルドの範囲外にある場合) –

+0

実際にはクラスローディングの問題を処理し、 'MavenCli'を使用することができます。回答。 –

0

これは(Mavenの3.5.0を使用して)カスタムのMavenプラグイン内で私の作品: "グローバル" ClassWorldへのアクセス権を持っているそのClassRealmに叢ランチャーsets the context class loader

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

その解決策はどれくらい安定しているのかは分かりませんが、これまでよく見ています。

使用される輸入:

import org.codehaus.plexus.classworlds.ClassWorld; 
import org.codehaus.plexus.classworlds.realm.ClassRealm; 
import org.apache.maven.cli.MavenCli; 
関連する問題