简体   繁体   中英

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.

If you're trying to exclude

org.apache.logging.log4j:log4j-slf4j-impl:2.4.1

Try

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

I usually fallback to this when i want to make sure that a dependency never added to a project.

configurations {
    all*.exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl', version '2.4.1'
}

But are you sure you need to exclude the dependency. It should not be part of the build jar/war. You can check all dependencies using "gradlew dependencies".

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 v 2.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

Somehow the issue was that I declared log4j as runtime dependency:

  ext {
       log4jVersion="2.5"
  }
  runtime (
            "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion",
            "org.apache.logging.log4j:log4j-api:$log4jVersion",
            "org.apache.logging.log4j:log4j-core:$log4jVersion"
        )

Which lead to the case that version 2.4.1 was fetched by some editor magic as compile dependency.

Therfore I had then 2.4.1 and 2.5 on the classpath.

As soon as I declared log4j as compile dependency 2.4.1 is gone...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM