web-dev-qa-db-ja.com

Maven依存関係の解決(競合)

私には4つのプロジェクトがあるとしましょう:

  • プロジェクトA(BとDに依存しています)
  • プロジェクトB(Dに依存しています)
  • プロジェクトC(Dに依存しています)
  • プロジェクトD

このシナリオでは、プロジェクトAを実行すると、MavenはDへの依存関係を正しく解決します。これを正しく理解すると、Mavenは常に最短パスで依存関係を取得します。 DはAの直接の依存関係であるため、代わりに使用されます。B内で指定されたD.

しかし、今この構造を仮定します:

  • プロジェクトA(BおよびCに依存しています)
  • プロジェクトB(Dに依存しています)
  • プロジェクトC(Dに依存しています)
  • プロジェクトD

この場合、解決Dへのパスの深さは同じです。起こることは、Mavenが競合することです。 Mavenに依存関係を除外するように伝えることができることは知っています。しかし、私の質問は、そのような種類の問題にどう対処するかです。実際のアプリケーションでは、多くの依存関係があり、場合によっては多くの競合もあります。

ものを除外するのが本当にベストプラクティスの解決策ですか、またはこれに対する他の可能な解決策はありますか?一部のバージョンが変更され、Mavenが別の依存関係を取得したため、突然ClassNotFound例外が発生した場合、対処が非常に困難であることがわかりました。この事実を知っているため、問題が依存関係の競合であると推測するのが少し簡単になります。

私はmaven 2.1-SNAPSHOTを使用しています。

65
kukudas

このような状況を解決するMavenの方法は、<dependencyManagement>プロジェクトのルートポンのセクション。使用するライブラリのバージョンを指定します。

編集:

<dependencyManagement>
  <dependencies>
    <dependency>
        <groupId>foo</groupId>
        <artifactId>bar</artifactId>
        <version>1.2.3</version>
    </dependency>
   </dependencies>
</dependencyManagement>

依存関係によってライブラリfoo:barのどのバージョンが要求されても、このプロジェクトとすべてのサブプロジェクトには常にバージョン1.2.3が使用されます。

参照:

76

Mavenは、競合することなく両方の状況を処理できます。推移的な依存関係の2つのバージョンが必要な場合、競合が発生します。 ClassNotFoundExceptionは、実際に使用される競合する依存関係のバージョンでは使用できないクラスを使用しようとするアプリ(または依存関係)からの結果を記述します。問題を解決する方法は複数あります。

  1. 競合する依存関係に依存する使用中のライブラリのバージョンを更新し、それらがすべてその依存関係の同じバージョンバージョンに依存するようにします
  2. 競合する依存関係を、含めるプロジェクトの直接的な依存関係として宣言します(この例では、欠落しているクラスが含まれているバージョン)。
  3. POMの<dependencyManagement>セクションを介して、推移的依存関係が使用する競合する依存関係のバージョンを指定します
  4. <exclusion>を使用して、競合する依存関係の不要なバージョンを、それらに依存する依存関係に含めることから明示的に除外します。
26
Daniel

これは基本的にMavenの問題ではなく、Javaの問題です。プロジェクトBとプロジェクトCにプロジェクトDの2つの互換性のないバージョンが必要な場合、プロジェクトAで両方を使用することはできません.

残念ながら、これらのような競合を解決するMavenの方法は、ご存じのとおり、除外する競合を選択することです。

mvn dependency:analyzeおよびmvn dependency:treeを使用すると、競合の検出に役立ちます。

17
Buhb

ルール Dependency Convergence を使用すると、プロジェクト全体で一貫した依存関係を 強制 できます。

 <plugin>
     <groupId>org.Apache.maven.plugins</groupId>
     <artifactId>maven-enforcer-plugin</artifactId>
     <version>1.3.1</version>
     <executions>
        <execution>
           <id>enforce</id>
           <configuration>
              <rules>
                 <DependencyConvergence/>
              </rules>
           </configuration>
           <goals>
              <goal>enforce</goal>
           </goals>
        </execution>
     </executions>
  </plugin>
13
MariuszS

考えられる戦略の1つは、メインプロジェクトに使用するDのバージョン(最新バージョンなど)を指定することです。ただし、ライブラリDに下位互換性がない場合は、kukudasに記載されている問題が発生します。プロジェクトで両方のライブラリを使用することはできません。

そのような状況では、古いバージョンでBまたはCのいずれかを使用する必要がある場合があります。そのため、両方がDの互換バージョンに依存します。

5
Stepan Vihor