Explicitly Managing Maven Dependencies


If we add a library in pom.xml, Maven would automatically include its dependencies. This is cool. But if two libraries depend on a same library, except use different version, problems may happen.

The best way is to declare the library version explicitly.

Here is an example:

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
      <modelVersion>4.0.0</modelVersion>  
      <groupId>com.codeexample</groupId>  
      <artifactId>mvn-example-exclusion</artifactId>  
      <version>1.0-SNAPSHOT</version>  
      <packaging>jar</packaging>  
      <name>mvn-example-exclusion</name>  
      <properties>  
           <slf4j.version>1.6.1</slf4j.version>  
      </properties>  
      <dependencies>  
           <dependency>  
                <groupId>log4j</groupId>  
                <artifactId>log4j</artifactId>  
                <version>1.2.16</version>  
           </dependency>  
           <dependency>  
                <groupId>org.slf4j</groupId>  
                <artifactId>slf4j-log4j12</artifactId>  
                <version>${slf4j.version}</version>  
           </dependency>  
           <dependency>  
                <groupId>net.sf.dozer</groupId>  
                <artifactId>dozer</artifactId>  
                <version>5.3.2</version>  
           </dependency>  
      </dependencies>  
 </project>  
public class App {
    public static void main(String[] args) {
       org.slf4j.LoggerFactory.getLogger(App.class).debug("Hello slf4j");
    }
}

When run the previous code which just use slf4j logger to print a debug message, it would report the following error:
SLF4J: The requested version 1.6 by your slf4j binding is not compatible with [1.5.5, 1.5.6, 1.5.7, 1.5.8, 1.5.9, 1.5.10]

This means we use incorrect version of slf4j-api library. But why and who imports the incorrect slf4j-api jar?

To find the culprit, I run “mvn eclipse:eclipse –X”.
[DEBUG] com.codeexample:mvn-example-exclusion:jar:1.0-SNAPSHOT (selected for null)
[DEBUG]   log4j:log4j:jar:1.2.16:compile (selected for compile)
[DEBUG]   net.sf.dozer:dozer:jar:5.3.2:compile (selected for compile)
[DEBUG]     commons-beanutils:commons-beanutils:jar:1.8.3:compile (selected for compile)
[DEBUG]       commons-logging:commons-logging:jar:1.1.1:compile (selected for compile)
[DEBUG]     commons-lang:commons-lang:jar:2.5:compile (selected for compile)
[DEBUG]     org.slf4j:slf4j-api:jar:1.5.10:compile (selected for compile)
[DEBUG]   org.slf4j:slf4j-log4j12:jar:1.6.1:compile (selected for compile)
[DEBUG]     org.slf4j:slf4j-api:jar:1.6.1:compile (removed - nearer found: 1.5.10)

From the output, we can see slf4j-log4j12-1.6.1 and net.sf.dozer-5.3.2 both depend on slf4j-api, but slf4j-log4j12-1.6.1 needs slf4j-api-1.6.1, net.sf.dozer-5.3.2 depends on slf4j-api-1.5.10.

For somewhat reason, - maybe net.sf.dozer-5.3.2 declares slf4j-api version explicitly-, maven uses slf4j-api-1.5.10.
To fix, we can explicitly declare the version of slf4j-api.
 <dependency>  
      <groupId>org.slf4j</groupId>  
      <artifactId>slf4j-api</artifactId>  
      <version>${slf4j.version}</version>  
 </dependency>  

Or we can exclude slf4j-api dependency from net.sf.dozer.
 <dependency>  
      <groupId>net.sf.dozer</groupId>  
      <artifactId>dozer</artifactId>  
      <version>5.3.2</version>  
      <exclusions>  
           <exclusion>  
                <groupId>org.slf4j</groupId>  
                <artifactId>slf4j-api</artifactId>  
           </exclusion>  
      </exclusions>  
 </dependency>  

I prefer the former solution, as it is clearer and simpler to understand.

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)