# Part 3: Dependency Management

version 8.4

Learn the basics of project dependencies and Gradle’s dependency management.

In this section you will:

- Understand project dependencies

- Inspect project dependencies

- Use a Build Scan to analyze dependencies

- Update project dependencies

- Understand transitive dependencies

- Adding a version catalog

## Step 0. Before you Begin

1. You initialized your Java app in part 1.

2. You ran several tasks in part 2.

## Step 1. Understanding Project Dependencies

Gradle provides excellent support for dependency management and automation.

Let’s take another look at our build script (the `gradle.build.kts` file), specifically the following section:

    repositories {
        // Use Maven Central for resolving dependencies.
        mavenCentral()
    }

    dependencies {
        // Use JUnit test framework.
        testImplementation("junit:junit:4.13.2")

        // This dependency is used by the application.
        implementation("com.google.guava:guava:32.1.2-jre")
    }

Some key concepts in Gradle dependency management include:

Repositories - The source of dependencies → `mavenCentral()`

Maven Central is a collection of jar files, plugins, and libraries provided by the Maven community and backed by Sonatype. It is the de-facto public artifact store for Java and is used by many build systems.

Dependencies - Dependencies declared via configuration types → `junit` and `guava`

Gradle needs specific information to find a dependency. Let’s look at `com.google.guava:guava:32.1.2-jre` and `junit:junit:4.13.2`; they are broken down as follows:

| Description | com.google.guava:guava:32.1.2-jre | junit:junit:4.13.2
--- | --- | --- | ---
Group | identifier of an organization | `com.google.guava` | `junit`
Name | dependency identifier | `guava` | `junit`
Version | version # to import | `32.1.2-jre` | `4.13.2`

## Step 2. Understanding Transitive Dependencies

A transitive dependency is a dependency of a dependency.

For our `guava` dependency to work, it requires a library called `failureaccess`. Therefore `failureaccess` is a transitive dependency of the project.

## Step 3. Viewing Project Dependencies

You can view your dependency tree in the terminal using the `./gradlew :app:dependencies` command:

    $ ./gradlew :app:dependencies

    > Task :app:dependencies

    ------------------------------------------------------------
    Project ':app'
    ------------------------------------------------------------

    ...

    compileClasspath - Compile classpath for source set 'main'.
    \--- com.google.guava:guava:32.1.2-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:3.12.0
         +--- com.google.errorprone:error_prone_annotations:2.11.0
         \--- com.google.j2objc:j2objc-annotations:1.3

    ...

The output clearly depicts that `com.google.guava:guava:32.1.2-jre` has a dependency on `com.google.guava:failureaccess:1.0.1`.

## Step 4. Viewing Dependencies in a Build Scan®

To view dependencies using a Build Scan, run the build task with an optional `--scan` flag.

In the `tutorial` directory, enter the command below and follow the prompt to accept the terms:

    $ ./gradlew build --scan

    BUILD SUCCESSFUL in 423ms
    7 actionable tasks: 7 up-to-date

    Publishing a build scan to scans.gradle.com requires accepting the Gradle Terms of Service defined at https://gradle.com/terms-of-service. Do you accept these terms? [yes, no] yes

    Gradle Terms of Service accepted.

    Publishing build scan...
    https://gradle.com/s/link

A Build Scan is a shareable and centralized record of a build and is available as a free service from Gradle.

Click the link provided in the prompt: `https://gradle.com/s/link`.

| You will have to accept the terms of service to use Build Scans.

You will need to activate the Build Scan by using your email:

You will receive the final link to the scan in your inbox which should look as follows:

Open the Dependencies tab in the menu and expand `compileClasspath`, `runtimeClasspath`, `testCompileClasspath`, and `testRuntimeClasspath`:

As expected, we can see the declared dependencies `junit` and `guava` are used by Gradle to compile, run, and test the app.

Expand `com.google.guava:guava:32.1.2-jre` and `org.junit.jupiter:junit-jupiter:5.9.1` in the window:

There are several transitive dependencies under `junit` and `guava`. For example, the `com.google.code.findbugs:jsr305:3.0.2` transitive dependency comes from the `com.google.guava:guava:32.1.2-jre` dependency.

## Step 5. Updating Project Dependencies

Adding and changing dependencies is done in the build file.

Let’s change the `guava` version and look at how this affects the dependency tree.

Change the `guava` dependency to the `gradle.build.kts` file to:

    implementation("com.google.guava:guava:30.0-jre")

If you change the file using IntelliJ, don’t forget to click the `sync` Gradle button:

Run `./gradlew build --scan` and view the Build Scan results:

Run `./gradlew :app:dependencies` in the terminal to check the changes in the dependency tree:

    compileClasspath - Compile classpath for source set 'main'.
    \--- com.google.guava:guava:30.0-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:3.5.0
         +--- com.google.errorprone:error_prone_annotations:2.3.4
         \--- com.google.j2objc:j2objc-annotations:1.3

    ...

It is clear the `guava` dependency has been updated to version `30.0` and the transitive dependencies have changed as well.

## Step 6. Adding a Version Catalog

A version catalog is used to declare all direct dependencies of a project in a central location.

It is created in `gradle/libs.versions.toml` and referenced in subproject build files.

First, create the `libs.versions.toml` file in the `gradle` directory.

Then, add the following lines to this new file:

    [versions]
    junitVer = "5.9.1"
    guavaVer = "32.1.2-jre"

    [libraries]
    junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junitVer" }
    guava = { module = "com.google.guava:guava", version.ref = "guavaVer" }

In your `app/build.gradle.kts` file, update the dependency block accordingly:

    dependencies {
        testImplementation(libs.junit)
        implementation(libs.guava)
    }

Finally, make sure everything is working using the `run` task, either in your terminal or IDE:

    ./gradlew run

    > Task :app:compileJava UP-TO-DATE
    > Task :app:processResources NO-SOURCE
    > Task :app:classes UP-TO-DATE

    > Task :app:run
    Hello World!

A version catalog provides a number of advantages over declaring the dependencies directly in build scripts:

- Gradle generates type-safe accessors from the catalog so that you can easily add dependencies with autocompletion in the IDE.

- It is a central place to declare a version of a dependency so that any changes apply to every subproject.

Next Step: Applying Plugins >>