0Pricing
Groovy & Gradle: JVM Automation and Build Engineering · Lesson

Declaring Project Dependencies

Learn various ways to declare dependencies in `build.gradle` for different scopes and types.

Declaring Project Dependencies is a free Groovy & Gradle: JVM Automation and Build Engineering lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Groovy & Gradle: JVM Automation and Build Engineering learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Project Needs & Dependencies

Modern software projects rarely work in isolation. They often rely on external code, known as dependencies, to perform various tasks.

Think of dependencies as pre-built tools or libraries that save you from writing common functionalities from scratch, like logging, parsing JSON, or connecting to a database.

  • Libraries: Collections of code (e.g., Apache Commons).
  • Frameworks: Structured foundations for applications (e.g., Spring Boot).
  • Modules: Components of a larger system.

Gradle's `dependencies` Block

In Gradle, you declare all your project's dependencies within a dedicated dependencies { ... } block in your build.gradle file.

This block is central to managing what your project needs to compile, test, and run.

/* build.gradle */

plugins {
  id 'java'
}

repositories {
  mavenCentral()
}

dependencies {
  // Your dependencies go here!
}

Where Gradle Finds Dependencies

Before Gradle can fetch dependencies, it needs to know where to look. This is defined in the repositories { ... } block.

The most common repository is Maven Central, a vast public repository for Java libraries. By declaring mavenCentral(), you tell Gradle to search there.

/* build.gradle */

repositories {
  // Tells Gradle to look for dependencies in Maven Central
  mavenCentral()
}

`implementation`: The Standard

The implementation configuration is your go-to for most production dependencies. It adds the dependency to the compilation classpath and also to the runtime classpath.

Crucially, implementation dependencies are not exposed to other modules that consume your project, which helps with faster compilation and better encapsulation.

/* build.gradle */

dependencies {
  // Adds SLF4J API for logging, used during compile and runtime
  implementation 'org.slf4j:slf4j-api:1.7.30'
}

Example: Using `implementation`

Let's see a simple Java class that uses a library added with implementation. We'll add the Apache Commons Lang library for string utilities.

/* build.gradle */

plugins {
  id 'java'
}

repositories {
  mavenCentral()
}

dependencies {
  implementation 'org.apache.commons:commons-lang3:3.12.0'
}

/* src/main/java/App.java */

import org.apache.commons.lang3.StringUtils;

public class App {
  public static void main(String[] args) {
    String text = "  Hello CoddyKit  ";
    System.out.println(StringUtils.trim(text));
  }
}

`testImplementation`: For Testing Only

Dependencies needed only for running tests (like JUnit 5 or Mockito) should be declared with testImplementation.

These dependencies are added to the test compilation and runtime classpaths but are not included in your final application artifact or exposed to production code.

/* build.gradle */

dependencies {
  // Adds JUnit 5 for unit testing
  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
  testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

`runtimeOnly`: Just for Running

Sometimes, a dependency is only needed when your application actually runs, not during compilation. This is where runtimeOnly comes in.

A common use case is a JDBC driver. Your code compiles against the JDBC API (which is often part of Java or a compileOnly dependency), but the specific driver (e.g., HSQLDB, PostgreSQL) is only needed at runtime.

/* build.gradle */

dependencies {
  // JDBC driver for HSQLDB, only needed when the app runs
  runtimeOnly 'org.hsqldb:hsqldb:2.5.1'
}

`compileOnly`: Compile-Time Helpers

Use compileOnly for dependencies that are required during compilation but should not be packaged with your final application or available at runtime.

Examples include annotation processors like Lombok, or API specifications (e.g., Servlet API) when your application will run in an environment that already provides them.

/* build.gradle */

dependencies {
  // Lombok for reducing boilerplate code, not needed at runtime
  compileOnly 'org.projectlombok:lombok:1.18.20'
  annotationProcessor 'org.projectlombok:lombok:1.18.20'
}

Local Files as Dependencies

While generally discouraged, you might sometimes need to include a local JAR file that isn't available in any public repository (e.g., a proprietary library).

You can declare these using the files() method within the dependencies block. Make sure the path is correct relative to your project root.

/* build.gradle */

dependencies {
  // Includes a JAR file located in the 'libs' folder
  implementation files('libs/my-custom-lib.jar')
}

Dependency Configuration Quiz

You are building a web application and need to include:

  • A logging library for all code.
  • JUnit 5 for unit tests.
  • The Servlet API, which your application server already provides.

Which Gradle dependency configurations would you use for these three items?

Recap: Declaring Dependencies

Great job! You've learned the essentials of declaring dependencies in Gradle:

  • The dependencies { ... } block is where you list all external libraries.
  • repositories { ... } tells Gradle where to find these libraries (e.g., mavenCentral()).
  • implementation for most production code.
  • testImplementation for test-specific libraries.
  • runtimeOnly for dependencies only needed at runtime.
  • compileOnly for compile-time only dependencies not packaged.
  • You can also include local JARs using files().

Understanding these configurations helps you build efficient and well-structured projects!

Frequently asked questions

Is the “Declaring Project Dependencies” lesson free?

Yes — the full text of “Declaring Project Dependencies” is free to read here on the web, and the Groovy & Gradle: JVM Automation and Build Engineering course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Groovy & Gradle: JVM Automation and Build Engineering course, upgrade to CoddyKit PRO.

What will I learn in “Declaring Project Dependencies”?

Learn various ways to declare dependencies in `build.gradle` for different scopes and types. You practise Groovy & Gradle: JVM Automation and Build Engineering with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Groovy & Gradle: JVM Automation and Build Engineering?

No prior experience is required. Groovy & Gradle: JVM Automation and Build Engineering on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Declaring Project Dependencies” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Groovy & Gradle: JVM Automation and Build Engineering lesson?

Yes. Every Groovy & Gradle: JVM Automation and Build Engineering lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Declaring Project Dependencies
  2. Dependency Resolution & Caching
  3. Custom Repositories & BOMs
  4. Resolving Version Conflicts & Dependency Constraints
← Back to Groovy & Gradle: JVM Automation and Build Engineering