In my previous post I presented how to display and filter dependencies in multi-module Gradle build. This time I will show how to quickly discover why become a Dependency of our project.
Problem
Real life use case. Multi-project Gradle build. In the runtime SLF4J reports problem with two discovered implementations: slf4j-logback
and slf4j-simple
. Logback is used in the project, but where slf4j-simple
came from? Of course it is not listed in our build.gradle
, but it is packaged into the WAR file and makes a conflict.
Long and bumpy way
With the knowledge from the previous post one of the possible solutions is to write allDeps
task, dump dependencies to file and find a rogue dependency.
It is not pretty visible on the first sight even for that small project with only 4 direct dependencies. But luckily there is a better way.
Quick solution
In addition to dependency
task (implemented in DependencyReportTask), Gradle has one more similar task – dependencyInsight
(implemented in DependencyInsightReportTask. It allows to limit a dependencies tree only to selected dependency (also transitive).
The command takes 2 mandatory parameters:--configuration
– Gradle configuration to search in – e.g. runtime
or testRuntime
(in a dependency
task a configuration was optional to specify)--dependency
– dependency to look for – e.g. org.slf4j:slf4j-simple
In the mentioned project it could be:
gradle sub2:dependencyInsight --configuration testRuntime --dependency slf4j-simple
The result is self explanatory. slf4j-simple
is (unnecessary) included by Moco library (moco-core). With that knowledge it is easy to exclude that transitive dependency:
compile('com.github.dreamhead:moco-core:0.9.2') { exclude group: 'org.slf4j', module: 'slf4j-simple' }
or when appropriate, do it globally for all configurations:
configurations { all*.exclude group: 'org.slf4j', module: 'slf4j-simple' }
Further tuning
The nice thing is the ability to loosely define expected dependency features. All of the following are valid:
--dependency org.slf4j:slf4j-simple:1.7.7
– only exactly version of that dependency--dependency org.slf4j:slf4j-simple
– all versions of that dependency--dependency org.slf4j
– all dependencies in given group--dependency slf4j-simple
– all dependencies with given name regardless of the group (useful when a package was relocated)
Multiple subprojects
dependencyInsight
the same as dependency
task do not work with multiple subproject. Fortunately it is simple to create that task:
subprojects { task allDepInsight(type: DependencyInsightReportTask) << {} }
It accepts all parameters supported by a base dependencyInsight
task and:
gradle allDepInsight --configuration testRuntime --dependency org.slf4j:slf4j-simple
would do its job in all subprojects.
Summary
dependencyInsight
task can be very useful when tracking down suspicious and not expected transitive dependencies in the project. An ability to make it multi-project build friendly makes it even more powerful.
Tested with Gradle 2.2.
This post first appeared on Solid Soft | Working Code Is Not Enough, please read the originial post: here