Explain Codes LogoExplain Codes Logo

How do I exclude all instances of a transitive dependency when using Gradle?

java
gradle
dependency-management
build-tools
Nikita BarsukovbyNikita Barsukov·Dec 10, 2024
TLDR

Wield the project-wide exclude command in configurations.all to remove every occurrence of a transitive dependency across your entire Gradle build. Update your build.gradle like this:

configurations.all { exclude group: 'com.unwanted', module: 'dependency' // Bye-bye, unwanted dependency! }

There you have it. You just pruned the dependency from com.unwanted from all corners of your build without having to exclude it in each dependency declaration.

Decoding transitive dependencies

Transitive dependencies are those dependencies that your project needs indirectly, because they're necessary for the direct dependencies your modules rely on. These can be both beneficial, filling gaps your project may have, or burdensome, creating potential conflicts or imposing security risks.

In Gradle, a module corresponds to what Maven refers to as an artifactId. To correctly identify the dependencies you're dealing with, you need to remember this translation: Maven's groupId:artifactId:version equates to Gradle's group:name:version.

Exclude dependencies like a pro

When you need to exclude a specific artifact from all dependencies in the project, you can add an exclude line to configurations.all in your build.gradle. This is a powerful tool for handling pesky problematic dependencies efficiently and confidently:

configurations.all { exclude group: 'com.problematic', module: 'troublesome-dependency' // Off to the dungeon of darkness you go! }

Thanks to this code, troublesome-dependency from com.problematic will be excised from every corner of your project without affecting other same-group artifacts.

Avoiding traps: mind your syntax

Pay attention to the syntax in the exclude block. A sloppy syntax can cause unintended broad-spectrum exclusions, potentially leaving out useful dependencies. Verify that the group and module names perfectly match what you aim to exclude.

If you think that an exclusion is working too efficiently and eliminating more than needed, consider creating a reproducible test case and raising a potential bug report.

Level up: Advanced exclusion and replacement tactics

Some projects come with multiple configurations like runtime and compileClasspath. In such cases, use exclusions within configurations.all to ensure consistent handling of dependencies across the entire project.

Sometimes, you may want to replace a specific module version rather than excluding it. Swing the Resolution Strategy to map to the desired version:

configurations.all { resolutionStrategy { eachDependency { DependencyResolveDetails details -> if (details.requested.group == 'com.unwanted' && details.requested.module == 'dependency') { details.useVersion 'desired.version' // Oh, I ordered a different version, waiter! } } } }

Keep in mind that these techniques are equally useful when dealing with older Gradle versions, specifically starting from 1.10.