2012-08-01 52 views
13

Đây là một câu hỏi có vẻ giống như bó của similar questions trên các trang web SE, vì vậy tôi nên khá tiết để làm cho câu hỏi của tôi rõ ràng. Vì vậy, đây là dự án tối thiểu pom.xml:Giải quyết nhiều liên kết SLF4J trong dự án maven

<dependencies> 
    <dependency> 
     <groupId>ch.qos.logback</groupId> 
     <artifactId>logback-classic</artifactId> 
     <version>1.0.6</version> 
    </dependency> 

    <dependency> 
     <groupId>org.codehaus.gmaven.runtime</groupId> 
     <artifactId>gmaven-runtime-1.7</artifactId> 
     <version>1.3</version> 
    </dependency> 

</dependencies> 
<build> 
    <plugins> 
     <plugin> 
      <groupId>org.codehaus.mojo</groupId> 
      <artifactId>exec-maven-plugin</artifactId> 
      <version>1.2.1</version> 
      <configuration> 
       <mainClass>org.shabunc.App</mainClass> 
      </configuration> 
     </plugin> 
    </plugins> 
</build> 

Đây là cây phụ thuộc được sản xuất bởi maven.

mvn dependency:tree -Dverbose -Dincludes=org.slf4j:

[INFO] [dependency:tree {execution: default-cli}] 
[INFO] org.shabunc:logdebug:jar:1.0-SNAPSHOT 
[INFO] \- ch.qos.logback:logback-classic:jar:1.0.6:compile 
[INFO] \- org.slf4j:slf4j-api:jar:1.6.5:compile 

Bây giờ, chúng ta hãy loại bỏ loại trừ và kiểm tra phụ thuộc một lần nữa. Chúng tôi sẽ nhận được:

[INFO] org.shabunc:logdebug:jar:1.0-SNAPSHOT 
[INFO] +- ch.qos.logback:logback-classic:jar:1.0.6:compile 
[INFO] | \- org.slf4j:slf4j-api:jar:1.6.5:compile 
[INFO] \- org.codehaus.gmaven.runtime:gmaven-runtime-1.7:jar:1.3:compile 
[INFO] +- (org.slf4j:slf4j-api:jar:1.5.10:compile - omitted for conflict with 1.6.5) 
[INFO] +- org.codehaus.gmaven.feature:gmaven-feature-support:jar:1.3:compile 
[INFO] | \- (org.slf4j:slf4j-api:jar:1.5.10:compile - omitted for conflict with 1.6.5) 
[INFO] \- org.codehaus.gmaven.runtime:gmaven-runtime-support:jar:1.3:compile 
[INFO]  +- (org.slf4j:slf4j-api:jar:1.5.10:compile - omitted for conflict with 1.6.5) 
[INFO]  \- org.sonatype.gshell:gshell-io:jar:2.0:compile 
[INFO]   \- org.sonatype.gossip:gossip:jar:1.0:compile 
[INFO]    \- (org.slf4j:slf4j-api:jar:1.5.8:compile - omitted for conflict with 1.6.5) 

Vì vậy, như chúng ta có thể thấy, mọi thứ hoạt động như mong đợi và phụ thuộc xung đột thực sự bị loại trừ. Nhưng vấn đề là rằng ngay cả với loại trừ phụ thuộc tôi vẫn nhận được sau thông báo khi biên dịch và gọi mvn exec:java:

SLF4J: Class path contains multiple SLF4J bindings. 
SLF4J: Found binding in [jar:file:/home/shabunc/.m2/repository/ch/qos/logback/logback-classic/1.0.6/logback-classic-1.0.6.jar!/org/slf4j/impl/StaticLoggerBinder.class] 
SLF4J: Found binding in [jar:file:/home/shabunc/.m2/repository/org/sonatype/gossip/gossip/1.0/gossip-1.0.jar!/org/slf4j/impl/StaticLoggerBinder.class] 

Câu hỏi đặt ra là: Tại sao tôi vẫn nhìn thấy cảnh báo này và những gì chính xác nên được thực hiện để làm cho chỉ có một phiên bản của slf4j có thể truy cập trong khi thực hiện?

+1

Không có ý định phạm tội nhưng khai báo sự phụ thuộc vào slf4j-api và sau đó không bao gồm slf4j-api là sai. Tuyên bố sau cũng là không chính xác. "hãy đảm bảo rằng slf4j-api thực sự chỉ được tải một lần, giống như chúng tôi mong đợi khi chúng tôi thêm phần loại trừ/loại trừ vào phụ thuộc thời gian chạy gmaven." Khi dependencioes khai báo các phiên bản khác nhau của một tạo tác, ví dụ: slf4j-api, Maven sẽ không đặt slf4j-api nhiều lần trên đường dẫn lớp. Ngay cả khi Maven đã làm (mà nó không), slf4j-api sẽ không được nạp nhiều lần. Vui lòng chỉnh sửa câu hỏi của bạn để không đánh lừa người đọc trong tương lai. – Ceki

+0

Ceki, nó sẽ được OK ngay cả khi nó sẽ là hành vi phạm tội mà sẽ dạy cho tôi một cái gì đó))) Thực tế là slf4j-api được nạp nhiều thời gian do đó tạo ra xung đột khi tôi đang cố gắng để triển khai như là chiến tranh để tomcat. Một slf4j là logblack và một trong sự phụ thuộc của sự phụ thuộc của gmaven-runtime. Nếu tôi thiếu cái gì đó, nó sẽ rất tốt nếu bạn làm cho nó rõ ràng hơn, vì tất cả sự phụ thuộc này giải quyết không phải là thứ tôi là một chuyên gia. – shabunc

+0

Nếu bạn đang sử dụng Maven, bạn sẽ không gặp rủi ro khi có các phiên bản khác nhau của slf4j-api trên đường dẫn lớp của bạn. Tuy nhiên, nó là phổ biến cho các ràng buộc slf4j * khác nhau *, ví dụ: slf4j-jdj14.jar, slf4j-log4j.jar hoặc logback-classic.jar có mặt đồng thời trên đường dẫn lớp. Trong trường hợp của bạn, bạn có hiện diện logback-classic-1.0.6.jar gossip-1.0.jar. Tom Anderson đã cung cấp một câu trả lời tốt cho việc loại trừ 'tin đồn'. – Ceki

Trả lời

18

Vấn đề của bạn là không nhận được hai bản sao của API SLF4J, nó nhận được hai triển khai SLF4J khác nhau. Bạn cần loại trừ Gossip chứ không phải API. Điều đó có nghĩa là:

<dependency> 
    <groupId>org.codehaus.gmaven.runtime</groupId> 
    <artifactId>gmaven-runtime-1.7</artifactId> 
    <version>1.3</version> 
    <exclusions> 
     <exclusion> 
     <groupId>org.sonatype.gossip</groupId> 
     <artifactId>gossip</artifactId> 
     </exclusion> 
    </exclusions> 
</dependency> 

Phụ thuộc tin đồn được tuyên bố bởi gshell-io; hy vọng, nó không thực sự cần Gossip, nó chỉ cần một SLF4J SLF4J, mà bạn đang cung cấp trong hình dạng của Logback.

+0

vì vậy, bạn có nghĩa là tôi có thể loại trừ phụ thuộc tin đồn miễn phí, mà không có bất kỳ hậu quả đáng kể nào?))) Và nếu có nhiều phụ thuộc hơn nữa, phụ thuộc vào slf4j, nó sẽ nhanh chóng trở thành, một cơn ác mộng (( – shabunc

+1

Cách duy nhất để làm cho hạnh phúc của SLF4J là loại bỏ sự phụ thuộc của bạn vào Logback, hoặc loại trừ sự phụ thuộc của gshell-io vào Gossip, tuy nhiên, tôi không thể hứa rằng điều này sẽ không có hậu quả đáng kể Tôi hy vọng nó không - sẽ rất nghèo cho một thư viện để có sự phụ thuộc trực tiếp vào việc thực hiện khai thác gỗ –

+0

Vấn đề là do 2 nhà cung cấp khác nhau ... tin đồn jar có một thực hiện slf4j bên trong nó .. vì vậy bạn nên loại bỏ logback hoặc tin đồn từ cây phụ thuộc của bạn .. – Byter

1

Tôi đoán bạn cần phải chơi với phạm vi phụ thuộc, xem: http://www.mojohaus.org/exec-maven-plugin/java-mojo.html

classpathScope - xác định phạm vi của classpath truyền cho các plugin. Đặt để biên dịch, kiểm tra, thời gian chạy hoặc hệ thống tùy thuộc vào nhu cầu của bạn.

+0

bạn có thể, cụ thể hơn, tôi vẫn không hiểu cách thiết lập classpathScope sẽ giúp giải quyết vấn đề này. – shabunc

3

Tất cả bạn cần làm là thêm một cái gì đó như thế này

compile "org.sonatype.gossip:gossip:1.0" { 
    exclude module:'slf4j-jcl' 
    exclude module:'slf4j-log4j12' 
} 
+0

Sự cố này xảy ra do sự phụ thuộc quá độ của tin đồn được sử dụng. Đoạn mã trên sẽ loại trừ sự phụ thuộc của việc triển khai sl4j từ tin đồn. – Byter

+2

"Một cái gì đó như thế này" ở đây có nghĩa là "tương đương Maven của mã Gradle này"! –

+0

@TomAnderson ya ... xin lỗi tôi đã không đề cập đến điều đó :) – Byter

Các vấn đề liên quan