# Dependency Management for Java Projects

This chapter explains how to apply basic dependency management concepts to Java-based projects. For a detailed introduction to dependency management, see Introduction to Dependency Management.

## Dissecting a typical build script

Let’s have a look at a very simple build script for a Java-based project. It applies the Java Library plugin which automatically introduces a standard project layout, provides tasks for performing typical work and adequate support for dependency management.

Example 1. Dependency declarations for a Java-based project
build.gradle

    plugins {
        id 'java-library'
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        implementation 'org.hibernate:hibernate-core:3.6.7.Final'
        api 'com.google.guava:guava:23.0'
        testImplementation 'junit:junit:4.+'
    }

build.gradle.kts

    plugins {
        `java-library`
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        implementation("org.hibernate:hibernate-core:3.6.7.Final")
        api("com.google.guava:guava:23.0")
        testImplementation("junit:junit:4.+")
    }

The Project.dependencies{} code block declares that Hibernate core 3.6.7.Final is required to compile the project’s production source code. It also states that junit >= 4.0 is required to compile the project’s tests. All dependencies are supposed to be looked up in the Maven Central repository as defined by Project.repositories{}. The following sections explain each aspect in more detail.

## Declaring module dependencies

There are various types of dependencies that you can declare. One such type is a module dependency. A module dependency represents a dependency on a module with a specific version built outside the current build. Modules are usually stored in a repository, such as Maven Central, a corporate Maven or Ivy repository, or a directory in the local file system.

To define an module dependency, you add it to a dependency configuration:

Example 2. Definition of a module dependency
build.gradle

    dependencies {
        implementation 'org.hibernate:hibernate-core:3.6.7.Final'
    }

build.gradle.kts

    dependencies {
        implementation("org.hibernate:hibernate-core:3.6.7.Final")
    }

To find out more about defining dependencies, have a look at Declaring Dependencies.

## Using dependency configurations

A Configuration is a named set of dependencies and artifacts. There are three main purposes for a configuration:

Declaring dependencies

  A plugin uses configurations to make it easy for build authors to declare what other subprojects or external artifacts are needed for various purposes during the execution of tasks defined by the plugin. For example a plugin may need the Spring web framework dependency to compile the source code.

Resolving dependencies

  A plugin uses configurations to find (and possibly download) inputs to the tasks it defines. For example Gradle needs to download Spring web framework JAR files from Maven Central.

Exposing artifacts for consumption

  A plugin uses configurations to define what artifacts it generates for other projects to consume. For example the project would like to publish its compiled source code packaged in the JAR file to an in-house Artifactory repository.

With those three purposes in mind, let’s take a look at a few of the standard configurations defined by the Java Library Plugin.

implementation

  The dependencies required to compile the production source of the project which are not part of the API exposed by the project. For example the project uses Hibernate for its internal persistence layer implementation.

api

  The dependencies required to compile the production source of the project which are part of the API exposed by the project. For example the project uses Guava and exposes public interfaces with Guava classes in their method signatures.

testImplementation

  The dependencies required to compile and run the test source of the project. For example the project decided to write test code with the test framework JUnit.

Various plugins add further standard configurations. You can also define your own custom configurations in your build via Project.configurations{}. See Managing Dependency Configurations for the details of defining and customizing dependency configurations.

## Declaring common Java repositories

How does Gradle know where to find the files for external dependencies? Gradle looks for them in a repository. A repository is a collection of modules, organized by `group`, `name` and `version`. Gradle understands different repository types, such as Maven and Ivy, and supports various ways of accessing the repository via HTTP or other protocols.

By default, Gradle does not define any repositories. You need to define at least one with the help of Project.repositories{} before you can use module dependencies. One option is use the Maven Central repository:

Example 3. Usage of Maven central repository
build.gradle

    repositories {
        mavenCentral()
    }

build.gradle.kts

    repositories {
        mavenCentral()
    }

You can also have repositories on the local file system. This works for both Maven and Ivy repositories.

Example 4. Usage of a local Ivy directory
build.gradle

    repositories {
        ivy {
            // URL can refer to a local directory
            url "../local-repo"
        }
    }

build.gradle.kts

    repositories {
        ivy {
            // URL can refer to a local directory
            url = uri("../local-repo")
        }
    }

A project can have multiple repositories. Gradle will look for a dependency in each repository in the order they are specified, stopping at the first repository that contains the requested module.

To find out more about defining repositories, have a look at Declaring Repositories.

## Publishing artifacts

Dependency configurations are also used to publish files. Gradle calls these files publication artifacts, or usually just artifacts. As a user you will need to tell Gradle where to publish the artifacts. You do this by declaring repositories for the `uploadArchives` task. Here’s an example of publishing to a Maven repository:

Example 5. Publishing to a Maven repository
build.gradle

    plugins {
        id 'maven'
    }

    uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: "file://localhost/tmp/myRepo/")
            }
        }
    }

build.gradle.kts

    plugins {
        maven
    }

    tasks.named<Upload>("uploadArchives") {
        repositories.withGroovyBuilder {
            "mavenDeployer" {
                "repository"("url" to "file://localhost/tmp/myRepo/")
            }
        }
    }

Now, when you run `gradle uploadArchives`, Gradle will build the JAR file, generate a `.pom` file and upload the artifacts.

To learn more about publishing artifacts, have a look at Legacy Publishing.