Monday, 13 July 2015

Software Library Dependency Iceberg

A while ago I wrote some Java code as a plugin for the Go Continuous Delivery server software.  It works quite nicely and won a contest - but that's not the topic for today.

Out of curiosity I have considered changing the way that dependencies have been managed.  So far the application just has three direct runtime dependencies and relies on Gradle to pull in any transitive dependencies.  I want to explicitly declare the dependencies and let Gradle only take care of downloading them, compilation, and assembling the jar.

A quick look at the tree of transitive dependencies shows common libraries but different versions.

+--- cd.go.plugin:go-plugin-api:14.4.0
+--- com.google.code.gson:gson:2.3.1
\--- org.cloudfoundry:cloudfoundry-client-lib:1.1.3
     +--- org.springframework:spring-webmvc:4.0.5.RELEASE -> 4.0.8.RELEASE
     |    +--- org.springframework:spring-beans:4.0.8.RELEASE
     |    |    \--- org.springframework:spring-core:4.0.8.RELEASE
     |    |         \--- commons-logging:commons-logging:1.1.3
     |    +--- org.springframework:spring-context:4.0.8.RELEASE
     |    |    +--- org.springframework:spring-aop:4.0.8.RELEASE
     |    |    |    +--- aopalliance:aopalliance:1.0
     |    |    |    +--- org.springframework:spring-beans:4.0.8.RELEASE (*)
     |    |    |    \--- org.springframework:spring-core:4.0.8.RELEASE (*)
     |    |    +--- org.springframework:spring-beans:4.0.8.RELEASE (*)
     |    |    +--- org.springframework:spring-core:4.0.8.RELEASE (*)
     |    |    \--- org.springframework:spring-expression:4.0.8.RELEASE
     |    |         \--- org.springframework:spring-core:4.0.8.RELEASE (*)
     |    +--- org.springframework:spring-core:4.0.8.RELEASE (*)
     |    +--- org.springframework:spring-expression:4.0.8.RELEASE (*)
     |    \--- org.springframework:spring-web:4.0.8.RELEASE
     |         +--- org.springframework:spring-aop:4.0.8.RELEASE (*)
     |         +--- org.springframework:spring-beans:4.0.8.RELEASE (*)
     |         +--- org.springframework:spring-context:4.0.8.RELEASE (*)
     |         \--- org.springframework:spring-core:4.0.8.RELEASE (*)
     +--- org.springframework.security.oauth:spring-security-oauth2:2.0.4.RELEASE
     |    +--- org.springframework:spring-beans:4.0.8.RELEASE (*)
     |    +--- org.springframework:spring-core:4.0.8.RELEASE (*)
     |    +--- org.springframework:spring-context:4.0.8.RELEASE (*)
     |    +--- org.springframework:spring-webmvc:4.0.8.RELEASE (*)
     |    +--- org.springframework.security:spring-security-core:3.2.5.RELEASE
     |    |    +--- aopalliance:aopalliance:1.0
     |    |    +--- org.springframework:spring-aop:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                               (*)
     |    |    +--- org.springframework:spring-beans:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                             (*)
     |    |    +--- org.springframework:spring-context:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                           (*)
     |    |    +--- org.springframework:spring-core:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                              (*)
     |    |    \--- org.springframework:spring-expression:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                        (*)
     |    +--- org.springframework.security:spring-security-config:3.2.5.RELEASE
     |    |    +--- aopalliance:aopalliance:1.0
     |    |    +--- org.springframework.security:spring-security-core:3.2.5.RELEASE                                                                             (*)
     |    |    +--- org.springframework:spring-aop:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                               (*)
     |    |    +--- org.springframework:spring-beans:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                             (*)
     |    |    +--- org.springframework:spring-context:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                           (*)
     |    |    \--- org.springframework:spring-core:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                              (*)
     |    +--- org.springframework.security:spring-security-web:3.2.5.RELEASE
     |    |    +--- aopalliance:aopalliance:1.0
     |    |    +--- org.springframework.security:spring-security-core:3.2.5.RELEASE                                                                             (*)
     |    |    +--- org.springframework:spring-beans:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                             (*)
     |    |    +--- org.springframework:spring-context:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                           (*)
     |    |    +--- org.springframework:spring-core:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                              (*)
     |    |    +--- org.springframework:spring-expression:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                        (*)
     |    |    \--- org.springframework:spring-web:3.2.8.RELEASE -> 4.0.8.RELEASE                                                                               (*)
     |    +--- commons-codec:commons-codec:1.6
     |    \--- org.codehaus.jackson:jackson-mapper-asl:1.9.13
     |         \--- org.codehaus.jackson:jackson-core-asl:1.9.13
     +--- org.apache.httpcomponents:httpclient:4.3.6
     |    +--- org.apache.httpcomponents:httpcore:4.3.3
     |    +--- commons-logging:commons-logging:1.1.3
     |    \--- commons-codec:commons-codec:1.6
     +--- commons-io:commons-io:2.1
     +--- com.esotericsoftware.yamlbeans:yamlbeans:1.06
     +--- com.fasterxml.jackson.core:jackson-core:2.3.3
     +--- com.fasterxml.jackson.core:jackson-databind:2.3.3
     |    +--- com.fasterxml.jackson.core:jackson-annotations:2.3.0
     |    \--- com.fasterxml.jackson.core:jackson-core:2.3.3
     +--- org.apache.tomcat.embed:tomcat-embed-websocket:8.0.15
     |    \--- org.apache.tomcat.embed:tomcat-embed-core:8.0.15
     +--- org.apache.tomcat:tomcat-juli:8.0.15
     \--- com.google.protobuf:protobuf-java:2.6.1

Just look at the number of times a Spring library version 3.2.8 is specified, but overridden to 4.0.8 - that's a jump in major version number, which may have introduced incompatible code changes, such as removing a method from the API.

I wonder if there are any tools out there that could analyse the caller / callee relationships to offer developers some reassurance or warnings when jars get replaced by different versions in a situation like this.

No comments:

Post a Comment