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 theexcludekeyword in the dependency declaration. For example:implementation('org.springframework:spring-webmvc:5.3.27') { exclude group: 'commons-logging', module: 'commons-logging' }