Gradle Dependencies
Project Dependencies
Ever wonder why your gradle build is failing because unresolved or not compatible dependencies. Where to get started?
To have a visual graph and information about all dependencies in front of your eyes is essential. Here dependencies
command should be your answer.
Gradle provides sufficient tooling to navigate large dependency graphs and mitigate situations that can lead to dependency hell.
List all dependencies
By default, dependencies gets listed for all the configurations. This can output a lot of unnecessary information.
For this you can list all of the configurations first.
./gradlew --console plain dependencies | fgrep ' - '
Then you list all the dependencies for this particular configuration
./gradlew dependencies --configuration compileClasspath
In the following result we can clearly see the graph of dependencies that will be used for compiling java project
> Task :dependencies
------------------------------------------------------------
Root project
------------------------------------------------------------
compileClasspath - Compile classpath for source set 'main'.
+--- com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20191001.1
| \--- com.google.guava:guava:27.1-jre
| +--- com.google.guava:failureaccess:1.0.1
| +--- com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
| +--- com.google.code.findbugs:jsr305:3.0.2
| +--- org.checkerframework:checker-qual:2.5.2
| +--- com.google.errorprone:error_prone_annotations:2.2.0
| +--- com.google.j2objc:j2objc-annotations:1.1
| \--- org.codehaus.mojo:animal-sniffer-annotations:1.17
+--- org.apache.commons:commons-lang3:3.10
+--- org.springframework.boot:spring-boot-starter-thymeleaf -> 2.2.6.RELEASE
| +--- org.springframework.boot:spring-boot-starter:2.2.6.RELEASE
| | +--- org.springframework.boot:spring-boot:2.2.6.RELEASE
| | | +--- org.springframework:spring-core:5.2.5.RELEASE
...
List specific dependency
You can also resolve a graph for one specific dependency.
./gradlew -q dependencyInsight --dependency aws-java-sdk-sqs --configuration compileClasspath
Force update dependencies
Once dependency in your Gradle build was fetched from a remote repository it will be cached. Now it can happen that:
- this dependency was updated,
- you changed some settings for the maven repository want to test if dependencies are still being resolved
- dependencies were partially downloaded and you need to redoenload them
In above cases you can use flag for refreshing dependencies:
gradlew build --refresh-dependencies
Refreshing dependencies (Gradle Userguide)
CLI Execution options (Gradle Userguide)
How can I force Gradle to redownload dependencies? (Cloudhadoop)
How can I force gradle to redownload dependencies? (StackOverflow)
Transitive dependency exclusion
Exclude specific transitive dependency from a dependencies
org.springframework.boot:spring-boot-starter-web dependency includes a list of transitive dependencies. Note that Tomcat server is transitive dependency.
+--- org.springframework.boot:spring-boot-starter-web:2.6.2
| ...
| | \--- com.fasterxml.jackson:jackson-bom:2.13.1 (*)
| +--- org.springframework.boot:spring-boot-starter-tomcat:2.6.2
| | +--- jakarta.annotation:jakarta.annotation-api:1.3.5
| | +--- org.apache.tomcat.embed:tomcat-embed-core:9.0.56
| | +--- org.apache.tomcat.embed:tomcat-embed-el:9.0.56
| | \--- org.apache.tomcat.embed:tomcat-embed-websocket:9.0.56
| | \--- org.apache.tomcat.embed:tomcat-embed-core:9.0.56
| +--- org.springframework:spring-web:5.3.14 (*)
...
If you want to replace Tomcat embedded server with Jetty, then you have to exclude Tomcat server first.
Exclude block has two properties group and module. For those of you coming from maven background, group is same as groupId and module is same as artifactId. You don’t need to specify version though.
implementation("org.springframework.boot:spring-boot-starter-web:2.6.2") {
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
}
Now spring-boot-starter-tomcat and all its transitive dependencies won’t be included through spring-boot-starter-web and won’t be a part of your application on classpath.
Example of exclusion in real life project on GitHub: https://github.com/FBI-Waring/test_mvparms/blob/03619cd595ade7ee1d301fbe37b7430d1b1e99aa/arms/build.gradle#L30
Question asked on StackOverflow https://stackoverflow.com/questions/21764128/how-do-i-exclude-all-instances-of-a-transitive-dependency-when-using-gradle
Buildscript Dependencies
Sometimes you even need to debug your buildscript configuration itself. Your build script can be broken before the project is even being evaluated. You want to see which plugins are included, what versions of those plugins are defined and which additional dependencies they will bring in.
There is buildEnvironment
command that will output dependency tree of buildscript instead of your project.
Example output of buildEnvironment
command for a simple SpringBoot project:
rivancic:app rivancic$ ./gradlew buildEnvironment
> Task :buildEnvironment
------------------------------------------------------------
Root project 'app'
------------------------------------------------------------
classpath
+--- org.springframework.boot:org.springframework.boot.gradle.plugin:2.6.7
| \--- org.springframework.boot:spring-boot-gradle-plugin:2.6.7
| +--- org.springframework.boot:spring-boot-buildpack-platform:2.6.7
| | +--- com.fasterxml.jackson.core:jackson-databind:2.13.2.1
| | | +--- com.fasterxml.jackson.core:jackson-annotations:2.13.2
| | | | \--- com.fasterxml.jackson:jackson-bom:2.13.2 -> 2.13.2.1
| | | | +--- com.fasterxml.jackson.core:jackson-annotations:2.13.2 (c)
| | | | +--- com.fasterxml.jackson.core:jackson-core:2.13.2 (c)
| | | | +--- com.fasterxml.jackson.core:jackson-databind:2.13.2.1 (c)
| | | | \--- com.fasterxml.jackson.module:jackson-module-parameter-names:2.13.2 (c)
| | | +--- com.fasterxml.jackson.core:jackson-core:2.13.2
| | | | \--- com.fasterxml.jackson:jackson-bom:2.13.2 -> 2.13.2.1 (*)
| | | \--- com.fasterxml.jackson:jackson-bom:2.13.2.1 (*)
...
| | +--- org.apache.commons:commons-compress:1.21
| | \--- org.springframework:spring-core:5.3.19 (*)
| +--- io.spring.gradle:dependency-management-plugin:1.0.11.RELEASE
| +--- org.apache.commons:commons-compress:1.21
| \--- org.springframework:spring-core:5.3.19 (*)
+--- io.spring.dependency-management:io.spring.dependency-management.gradle.plugin:1.0.11.RELEASE
| \--- io.spring.gradle:dependency-management-plugin:1.0.11.RELEASE
\--- name.remal.sonarlint:name.remal.sonarlint.gradle.plugin:1.5.0
\--- name.remal:gradle-plugins:1.5.0
+--- name.remal:gradle-plugins-kotlin-dsl:1.5.0
| +--- name.remal:gradle-plugins-api:1.5.0
| +--- name.remal.tools:common:1.26.147
| +--- org.jdom:jdom2:2.0.6
...
+--- org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:5.12.0.202106070339-r
| +--- org.eclipse.jgit:org.eclipse.jgit:5.12.0.202106070339-r
| | \--- com.googlecode.javaewah:JavaEWAH:1.1.7
| +--- com.jcraft:jsch:0.1.55
| \--- com.jcraft:jzlib:1.1.1
+--- org.eclipse.jgit:org.eclipse.jgit:5.12.0.202106070339-r (*)
\--- name.remal.gradle-plugins.test-source-sets:test-source-sets:2.2.0
(c) - dependency constraint
(*) - dependencies omitted (listed previously)
Sources
Viewing and debugging dependencies - Gradle Userguide
Gradle Configurations - Stack Overflow