2009-09-08 50 views
14

以下のようなプロジェクトで2つのMaven依存関係が定義されているとします。異なるスコープの依存関係内のMaven依存関係

<dependency> 
     <groupId>com.thoughtworks.xstream</groupId> 
     <artifactId>xstream</artifactId> 
     <version>1.3.1</version> 
     <scope>test</scope> 
    </dependency> 
    <dependency> 
     <groupId>mycompany.library</groupId> 
     <artifactId>mylibrary</artifactId> 
     <version>1.0.1</version> 
     <scope>compile</scope> 
    </dependency> 

次に、mylibrary内で、以下のように定義された依存関係もあります。

<dependency> 
     <groupId>com.thoughtworks.xstream</groupId> 
     <artifactId>xstream</artifactId> 
     <version>1.3.1</version> 
     <scope>compile</scope> 
    </dependency> 

プロジェクトをパッケージ化すると、xstreamがパッケージ化されて表示されません。私は、プロジェクトのxstream依存関係のスコープ、 'test'がmylibraryのxstream依存スコープである 'compile'をオーバーライドしていると思います。

このような状況では、プロジェクト全体にxstreamを含めると、サブモジュールはプロジェクト内にパッケージ化されたときにアクセスできるようになります。

私は、Transitive依存性に関するApache MavenのWebサイトの説明を読んだが、その意味を理解し、この状況でのベストプラクティスを見つけるのには苦労している。

答えて

11

これは本当に私にとって奇妙で、「機能」本当に危険なものです。 とにかく、これはMavenのバグではなく、Mavenのドキュメントhereにあります。

この問題に関するベストプラクティスに関して、私は何も聞いていませんが、最も安全な方法は推移依存に依存して、あなたのポームから完全にxstreamを削除することです。これを行うと、mylibraryへの依存関係が削除された場合にビルドに失敗します。これは、あなたが何かを修正する必要があるという通知として機能します。必要な依存関係を静かに緩和することはなく、もはや必要のない依存関係を静かに持ちません。

mvn dependency:analyzeを使用すると、含まれているが使用されていない依存関係をチェックできます。

0

パッケージ化したい場合、なぜあなたは範囲を宣言していますか?コンパイルと実行時に必要な場合は、スコープを空白のままにしてはいけませんか?あなたがそれをした場合、必要なのは

<dependency> 
    <groupId>mycompany.modules</groupId> 
    <artifactId>submodule</artifactId> 
    <version>1.0.1</version> 
</dependency> 

です。コンパイル時にそれを記述する理由はないが、パッケージ化中ではないのでないか?

+0

Apache Maven Webサイトから: - コンパイル これはデフォルトのスコープで、指定されていない場合に使用されます。コンパイルの依存関係は、プロジェクトのすべてのクラスパスで使用できます。さらに、これらの依存関係は依存するプロジェクトに伝播されます。 –

+0

「サブモジュール」を使用したため、私のオリジナルの質問が混乱を引き起こしたのかもしれません。上記の私の編集した質問をご覧ください。 –

+0

はい、私はテストの範囲についてもっと疑問に思っていました。 – aperkins

4

独自のxstreamへの依存関係を宣言し、スコープをテストに設定することによって、mylibraryで宣言された依存関係をオーバーライドします。

これは実際にはMavenの機能です。これにより、自分のプロジェクト内の推移的依存関係の新しいバージョンに依存し、同じアーティファクトの2つの異なるバージョンをパッケージ化することはできません。たとえば、log4jのバージョン1.2.15に依存するかもしれませんが、log4j-1.2.14に応じてlibraryXを使用するため、log4j-1.2.15log4j-1.2.14の両方をプロジェクトにパッケージ化することは望ましくありません。

実際にxstreamをプロジェクト内にパッケージ化する場合は、スコープをtestと宣言しないでください。実際にxstreamに対する依存関係を削除した場合、mylibraryにコンパイルの依存関係があるため、何でもうまくいくでしょう。

+1

そのような場合、将来的にはmylibraryを使用する必要はなく、xstreamへの依存関係を別のものに変更すると、プロジェクトがテストに合格しなくなります。次に、プロジェクトのテストスコープのxstreamを再度指定する必要があります。このMavenの機能/制限はありますか?私はMavenの制限を受け入れて、ベストプラクティスが何であるかを見極めようとしています。 –

+0

これが正しいとは確信していません。望ましくない過渡的な依存関係を排除するためには、より強力なメカニズムがあり、それはブロックです。 – Buhb

+0

"今後、mylibraryを使用する必要はなく、xstreamへの依存性を他のものに変更すると、プロジェクトがテストに合格しなくなります。その時点で依存関係を元に戻すだけです。同じバージョンのmylibraryに引き続き依存している限り、予期しない変更は起こりません。あなたのプロジェクトの新しいバージョンは異なるニーズを持っているかもしれません - それは全く正常です。 –

5

回答:mattbの答えによれば、依存関係をtestスコープとして宣言すると、推移的コンパイルスコープ依存宣言が上書きされ、その結果依存関係はパッケージ化された戦争に含まれません。

'mylibrary'が実行する必要があるためにテストで依存関係が必要な場合は、プロジェクトのpomのという依存関係を宣言するべきではありません。推移的依存性解決プロセスでそれを処理させます。

プロジェクトでxstream jarを直接使用する場合は、互換性のあるバージョンのプロジェクトが必要であり、 'mylibrary'が両方ともxstream jarに対して実行されるため、推移的な依存関係に依存することができます。機能を実行する単体テストが必要です。また、mylibraryがxstreamのバージョンを互換性のないバージョンに変更すると、ビルドが失敗し、その時点で問題を解決できます。

一般に、私はあなたがマルチモジュールプロジェクトで直接依存バージョンを宣言しないようにするべきだと言いたいと思います。子がgroupId/artifactIdだけを宣言する必要があるように、親POMのdependencyManagementセクションにバージョンを宣言します。

この範囲のみセクションのタイプのPOMの依存性に使用されます。あるいは、Mavenの2.0.9から以降importの追加の依存範囲があります。指定されたPOMをそのPOMのセクションの依存関係に置き換える必要があることを示します。それらが置き換えられるため、インポートのスコープに依存することは、依存関係の推移性を制限することに実際には関与しません。だから、あなたは、単一POMであなたの一般的な依存関係のバージョンを定義し、あなたのdependencyManagementセクションにそのPOMの依存関係をインポートし、ちょうどあなたの他のPOMに依存するのgroupId /たartifactIdを宣言することができますインポートスコープを使用して