Maven 종속성 해결 (충돌)


78

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을 사용하고 있습니다.


2
DEV 버전 인 2.1-SNAPSHOT 버전은 사용하지 말아야한다고 생각합니다. Maven 2는 최종 버전 2.2.1에서 사용할 수 있습니다.
reef

4
BTW, 메이븐 3.x를 잠시 동안 안정적이었다 훨씬 더 빠르고 안정적인 받는다는 2.x를보다
숀 패트릭 플로이드

3
다이아몬드는 ... 프로그래머의 가장 큰 적이다
토니 Lâmpada

@Sean Patrick Floyd 모든 메이븐 버전은 SNAPSHOT보다 안정적입니다. :)
MariuszS

답변:


88

이와 같은 상황을 해결하는 방법은 <dependencyManagement>프로젝트의 루트 pom에 섹션 을 포함하여 사용할 라이브러리의 버전을 지정하는 것입니다.

편집하다:

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

이제 종속성에 의해 요청 된 라이브러리 foo : bar의 버전에 관계없이 버전 1.2.3이 항상이 프로젝트와 모든 하위 프로젝트에 사용됩니다.

참고:


프로젝트 D, 프로젝트 B의 버전이 다르면 (D1.0에 종 속됨)-D2.0에서 작동 할 수 없음 프로젝트 C (D2.0에 종 속됨)-D1.0에서 작동 할 수 없음
Nitul

2
@Nitul 그러면 기본적으로 망했습니다. 귀하의 유일한 옵션은 다음 받는다는 그늘 플러그인 같은 것을 사용하여 종속성 중 하나 재 포장하는 것입니다
숀 패트릭 플로이드

4
명확히하기 위해에 지정된 버전 번호 dependencyManagement는 전 이적 종속성 및 명시 적 버전이없는 프로젝트 종속성 에 적용됩니다. 그러나 명시 적 버전이있는 프로젝트 종속성은 dependencyManagement섹션 의 버전을 재정의합니다 .
pnewhook dec.

31

Maven은 충돌없이 두 상황을 모두 처리 할 수 ​​있습니다. 두 가지 버전의 전이 종속성이 필요한 경우 충돌이 발생합니다. ClassNotFoundException당신은 실제로 사용됩니다 충돌하는 의존성의 버전에서 사용할 수없는 클래스를 사용하려고 시도하는 응용 프로그램 (또는 종속)의 결과를 설명합니다. 문제를 해결하는 방법에는 여러 가지가 있습니다.

  1. 충돌하는 종속성에 의존하는 사용중인 라이브러리의 버전을 업데이트하여 모두 해당 종속성의 동일한 버전 버전에 의존하도록합니다.
  2. 포함 할 버전 (예제에서 누락 된 클래스가 포함 된 버전)이있는 프로젝트의 직접적인 종속성으로 충돌 종속성을 선언합니다.
  3. <dependencyManagement>POM 섹션을 통해 전이 종속성이 사용해야하는 충돌 종속성의 버전을 지정 합니다.
  4. 충돌하는 종속성의 원치 않는 버전을 종속성에 포함되지 않도록 명시 적으로 제외합니다. <exclusion>

22

이것은 근본적으로 maven 문제가 아니라 Java 문제입니다. 프로젝트 B와 프로젝트 C에 프로젝트 D의 두 가지 호환되지 않는 버전이 필요한 경우 프로젝트 A에서 둘 다 사용할 수 없습니다.

이와 같은 충돌을 해결하는 Maven 방법은 이미 알고 있듯이 제외 할 충돌을 선택하는 것입니다.

mvn dependency:analyze및 사용하여 mvn dependency:tree어떤 갈등이 있는지 찾는 데 도움이됩니다.


+1. 이전 버전과 호환되지 않는 아티팩트는 groupId 및 / 또는 artifactId를 변경해야한다고 말하고 싶습니다.
Sean Patrick Floyd

예,하지만 절반 밖에 걸리지 않습니다. 아티팩트는 동일한 패키지 및 이름을 가진 클래스를 포함하지 않아야합니다.
Buhb

안타깝게도, 맞아. 이 경우 ProGuard 또는 Maven Shade 플러그인이 필요합니다
Sean Patrick Floyd

OSGI가이 가상 시나리오를 해결할 수 있을까요? (즉이의 제안하지 않기 쉬운 솔루션 -. 그냥 물어)
jhericks

혹시. 저는 OSGI를 잘 모르겠습니다.
Buhb 2011-08-24

18

규칙 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>

9

한 가지 가능한 전략은 주 프로젝트에 사용할 D 버전 (최신 fg)을 지정하는 것입니다. 그러나 라이브러리 D가 이전 버전과 호환되지 않는 경우 kukudas에서 설명한대로 문제가 있습니다. 프로젝트에서 두 라이브러리를 모두 사용할 수 없습니다.

이러한 상황에서는 이전 버전에서 B 또는 C를 사용해야 할 수 있으므로 둘 다 호환되는 D 버전에 의존하게됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.