Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove transitive classpath dependency in gradle

we're running a spring-boot app with gradle.

In order to include the spring-boot plugin we add it as dependency:

buildscript {
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.2.RELEASE") 
    }
}

Unfortunately this plugin ships with a dependency to org.apache.logging.log4j:log4j-slf4j-impl:2.4.1

Which I'd like to exclude.

Already tried that by adding:

  dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.2.RELEASE") {
            exclude group: 'org.apache.logging.log4j'
        }
    }

Which doesn't work.

Also adding:

configurations {
    classpath.exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl'
}

Doesn't have any effect.

Any hint is welcome.

like image 988
questionaire Avatar asked Jan 27 '16 12:01

questionaire


1 Answers

Two steps, chase down the transitive dependency then exclude it from the library responsible.

gradle dependencies gives you the full list including the transitive. If your project is small that can be helpful but for large enterprise builds... its too much info. Feel free to search through it but we get more to the point information from dependencyInsight.

gradle dependencyInsight --dependency someDependency finds all the places the dependency could come into the build. If you have multiple versions this will help make it apparent where the versions originate.

In my usecase logging is explicitly declared as a compile time dependency so it shows as below. If log4j was anywhere else you would see the offending library as well as the compile time declaration for v2.5.

I had to run this explicitly on each sub module.

$ gradle util:dependencyInsight --dependency org.apache.logging.log4j
Configuration on demand is an incubating feature.
:util:dependencyInsight
org.apache.logging.log4j:log4j-api:2.5
+--- compile
\--- org.apache.logging.log4j:log4j-core:2.5
     \--- compile

org.apache.logging.log4j:log4j-core:2.5
\--- compile

(*) - dependencies omitted (listed previously)

BUILD SUCCESSFUL

Total time: 0.933 secs

Now once you know where to exclude the dependency from just do like before to remove it. You can confirm by running the dependencyInsights again

dependencies {
    // found through `gradle dependencyInsight --dependency org.apache.logging.log4j`
    classpath("someOtherGroup:someOtherArtifactId:1.0") {
        exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl'
    }
}

Another solution could be overriding the dependency resolver and force the version to 2.5

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.group == "org.apache.logging.log4j") {
            println "Updating version for: $details.requested.group:$details.requested.name:$details.requested.version --> 2.5"
            details.useVersion '2.5'
        }
    }
}

My opinion, I probably don't want to keep adding checks in the resolutionStrategy all the time so probably better to just track it down in the dependencyInsights. Also this means updating the version in two places and if another developer isn't aware of how gradle's resolutionStrategy works then they will have "weird" behavior... eg. I updated log4j to 2.7 but it still builds with 2.5?!?!

But both are valid approaches

like image 180
JBirdVegas Avatar answered Oct 21 '22 01:10

JBirdVegas