# Part 3: Dependency Management

version 8.9

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 the Version Catalog

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

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

libs.versions.toml

    [versions]
    guava = "32.1.2-jre"
    junit-jupiter = "5.10.0"

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

To reference the libraries defined in the version catalog:

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

    dependencies {
        implementation libs.guava
        testImplementation libs.junit.jupiter
    }

In this example, `libs.guava` and `libs.junit.jupiter` refer to the corresponding libraries defined in your version catalog.

| The `versions.junit.jupiter` syntax is used because the key contains a hyphen which is a special characters.

A version catalog provides a number of advantages over declaring 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.

## Step 2. Understanding Project Dependencies

Gradle provides excellent support for dependency management and automation.

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

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

    dependencies {
        // Use JUnit Jupiter for testing.
        testImplementation(libs.junit.jupiter)

        testRuntimeOnly("org.junit.platform:junit-platform-launcher")

        // This dependency is used by the application.
        implementation(libs.guava)
    }

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

    dependencies {
        // Use JUnit Jupiter for testing.
        testImplementation libs.junit.jupiter

        testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

        // This dependency is used by the application.
        implementation libs.guava
    }

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 → `libs.junit.jupiter` and `libs.guava`

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

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

## Step 3. 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 4. 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:guava-parent:32.1.2-jre
         |    +--- com.google.code.findbugs:jsr305:3.0.2 (c)
         |    +--- org.checkerframework:checker-qual:3.33.0 (c)
         |    +--- com.google.errorprone:error_prone_annotations:2.18.0 (c)
         |    \--- com.google.j2objc:j2objc-annotations:2.8 (c)
         +--- 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.33.0
         +--- com.google.errorprone:error_prone_annotations -> 2.18.0
         \--- com.google.j2objc:j2objc-annotations -> 2.8

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 5. 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 6. 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 in the version catalog to:

gradle/libs.version.toml

    [versions]
    guava = "30.0-jre"
    junit-jupiter = "5.10.0"

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

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 7. Run the Java app

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!

Next Step: Applying Plugins >>