Java > Java Build Tools > Gradle > Dependency Management in Gradle
Gradle Dependency Management: Basic Example
This snippet demonstrates a basic build.gradle
file showcasing dependency management in Gradle. It includes adding dependencies from Maven Central, a common repository. It provides a fundamental understanding of how to declare dependencies using the dependencies
block and different dependency configurations like implementation
, testImplementation
and api
.
build.gradle file
implementation
configuration means that this dependency is required for compiling the project and is also exposed to modules that depend on this project. Changes to implementation dependencies require recompilation of dependent modules.testImplementation
indicates that this dependency is only used for compiling tests.api
configuration means that this dependency is not only required for compilation but also exposed as part of the project's API. Changes to api dependencies require recompilation of any modules that depend on this project. This is less common than implementation
and should be used when other modules need to use the classes from the dependency directly.
plugins {
id 'java'
}
group 'com.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.apache.commons:commons-lang3:3.12.0'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
api 'com.google.guava:guava:31.1-jre'
}
test {
useJUnitPlatform()
}
Concepts Behind the Snippet
This snippet illustrates the core concepts of dependency management: specifying external libraries that your project relies on. Gradle uses a declarative approach, where you define the dependencies in the build.gradle
file, and Gradle automatically downloads and manages those dependencies. The implementation
configuration is the most common and generally preferred for most dependencies because it hides internal dependencies from consumers of your library, improving modularity and reducing the risk of version conflicts. Use api
judiciously when you need to expose dependencies as part of your public API.
Real-Life Use Case
Imagine you're building a web application and need to use a JSON processing library like Jackson. You would add Jackson as a dependency in your build.gradle
file, and Gradle would handle downloading Jackson and all of its transitive dependencies, making them available for use in your project. This eliminates the need to manually download and manage JAR files.
Best Practices
implementation
by default: Unless you specifically need to expose a dependency as part of your API, use the implementation
configuration.
When to Use api
vs. implementation
Use api
only when your project's public API exposes types from the dependency. If the dependency is only used internally within your project's implementation, use implementation
. Incorrectly using api
can increase compile times and create unnecessary dependencies.
Alternatives
Alternatives to mavenCentral()
are jcenter()
(deprecated), or a company-hosted Maven repository. You could also use a local file based repository, though this is uncommon and should be avoided if possible.
Pros
The pros of using Gradle for dependency management include:
Cons
The cons of using Gradle for dependency management include:
build.gradle
files.
FAQ
-
What happens if I don't specify a version for a dependency?
Gradle will attempt to resolve the dependency with a version that satisfies other dependencies in your project, which can lead to unpredictable results. It's best practice to always specify a version. -
How can I exclude a transitive dependency?
You can exclude a transitive dependency using theexclude
keyword in the dependency declaration. For example:implementation('org.springframework:spring-webmvc:5.3.27') { exclude group: 'commons-logging', module: 'commons-logging' }