vmware-archive/hillview

28 Dependency Conflicts in Platform pom.xml

Closed this issue · 5 comments

There are 28 conflicts based on the dependency tree that I attached below. The tree is generated by running mvn dependency:tree -Dverbose in the platform directory. Cassandra's dependencies are not included when generating this dependency tree.

[INFO] | +- (com.google.protobuf:protobuf-java:jar:2.5.0:compile - omitted for conflict with 3.5.1)
[INFO] | | +- (com.google.guava:guava:jar:11.0.2:compile - omitted for conflict with 27.0.1-jre)
[INFO] | | | +- (commons-logging:commons-logging:jar:1.0.4:compile - omitted for conflict with 1.1.1)
[INFO] | | | - (commons-codec:commons-codec:jar:1.2:compile - omitted for conflict with 1.5)
[INFO] | | +- (commons-codec:commons-codec:jar:1.4:compile - omitted for conflict with 1.5)
[INFO] | | +- (commons-io:commons-io:jar:2.1:compile - omitted for conflict with 2.4)
[INFO] | | +- (commons-lang:commons-lang:jar:2.5:compile - omitted for conflict with 2.6)
[INFO] | | | +- (commons-lang:commons-lang:jar:2.4:compile - omitted for conflict with 2.6)
[INFO] | | +- (org.codehaus.jackson:jackson-core-asl:jar:1.8.8:compile - omitted for conflict with 1.9.11)
[INFO] | | +- (org.codehaus.jackson:jackson-mapper-asl:jar:1.8.8:compile - omitted for conflict with 1.9.11)
[INFO] | | | - (commons-codec:commons-codec:jar:1.4:compile - omitted for conflict with 1.5)
[INFO] | | - (org.apache.commons:commons-compress:jar:1.4.1:compile - omitted for conflict with 1.19)
[INFO] | | +- (commons-codec:commons-codec:jar:1.4:compile - omitted for conflict with 1.5)
[INFO] | | +- (commons-lang:commons-lang:jar:2.5:compile - omitted for conflict with 2.6)
[INFO] | | +- (org.codehaus.jackson:jackson-core-asl:jar:1.8.8:compile - omitted for conflict with 1.9.11)
[INFO] | | +- (org.codehaus.jackson:jackson-mapper-asl:jar:1.8.8:compile - omitted for conflict with 1.9.11)
[INFO] | | - (org.slf4j:slf4j-api:jar:1.7.10:compile - omitted for conflict with 1.7.5)
[INFO] | +- com.google.guava:listenablefuture:jar:9999.0-empty-to-avoid-conflict-with-guava:compile
[INFO] | +- (com.google.code.findbugs:jsr305:jar:3.0.2:compile - omitted for conflict with 3.0.1)
[INFO] | +- (com.google.code.gson:gson:jar:2.7:compile - omitted for conflict with 2.8.5)
[INFO] | +- (com.google.guava:guava:jar:20.0:compile - omitted for conflict with 27.0.1-jre)
[INFO] | +- (com.google.code.findbugs:jsr305:jar:3.0.0:compile - omitted for conflict with 3.0.2)
[INFO] | +- (com.google.protobuf:protobuf-java:jar:3.5.1:compile - omitted for conflict with 2.5.0)
[INFO] | +- (com.google.guava:guava:jar:20.0:compile - omitted for conflict with 27.0.1-jre)
[INFO] | - (com.google.guava:guava:jar:20.0:compile - omitted for conflict with 27.0.1-jre)
[INFO] | - (org.apache.commons:commons-lang3:jar:3.8.1:compile - omitted for conflict with 3.8)
[INFO] | - (org.apache.commons:commons-lang3:jar:3.7:compile - omitted for conflict with 3.8)

deps-tree.txt

One way to avoid such conflicts is to explicitly declare exclusions (based on the above tree) to prevent platform dependencies from pulling in certain transitive dependencies (like guava, or commons-lang3).

See: https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html

As an example, when declaring a dependency, you can configure an exclusion like this:

    <dependency>
      <groupId>sample.ProjectA</groupId>
      <artifactId>Project-A</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>  <!-- declare the exclusion here -->
          <groupId>sample.ProjectB</groupId>
          <artifactId>Project-B</artifactId>
        </exclusion>
      </exclusions> 
    </dependency>

Of course, this assumes that the dependencies will work correctly with a different version of the transitive dependency. :) Else, we'll need to resort to shading.

Either way, this would need some hygiene going forward (like making sure to run mvn dependency:tree whenever a new dependency is added to watch out for conflicts).

Note that maven's default strategy for omissions might be okay in most cases (I think it is to pick the first declared version of a dependency?).

Yes, I am fixing these manually for now. I may add a test in rebuild.sh that there are no conflicts.

what is "first"?

From: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

Dependency mediation - this determines what version of an artifact will be chosen when multiple
versions are encountered as dependencies. Maven picks the "nearest definition". That is, it uses 
the version of the closest dependency to your project in the tree of dependencies. You can 
always guarantee a version by declaring it explicitly in your project's POM. Note that if two
dependency versions are at the same depth in the dependency tree, the first declaration wins.

"nearest definition" means that the version used will be the closest one to your project in the 
tree of dependencies. For example, if dependencies for A, B, and C are defined as 
A -> B -> C -> D 2.0 and A -> E -> D 1.0, then D 1.0 will be used when building A because 
the path from A to D through E is shorter. You could explicitly add a dependency to D 2.0 in A 
to force the use of D 2.0.