Gradle Build Bible Book Cover - Click to read sample
Trusted by 300+ Java developers

Unleash your Java project with Gradle

Speed up and scale your project with a build system designed for busy developers.

Apply best practices to get faster builds.
Master fundamentals that most developers miss.
Fix unreliable builds and make coding fun again
Tom Gregory
By YouTube's #1 Gradle creator
1,100,654 views and counting

Why Java Projects Slow Down

The build bottleneck

Long, sluggish builds steal time from actually delivering new features.

Gradle promises fast, reliable builds—but only if your project is configured right. Its cryptic build scripts can make that setup feel like guesswork.

I've been there. After years poring over docs and endless trial-and-error, I finally figured it out. Now I can turn slow, clunky projects into finely-tuned build machines—and you can too.

Tom Gregory

Why I won't use another build tool

After applying Gradle across projects big and small, I've seen first-hand how much smoother Java development can be. Now I'm sharing everything I've learned so other developers can spend less time fighting builds and more time coding.

Gradle Build Bible is the guide I wish I had when I started. It distills years of hard-earned lessons into practical steps to master Gradle and supercharge your Java builds.

Five Chapters to Gradle Mastery

1

The Fundamentals

Get to grips with key Gradle concepts (tasks, plugins, build scripts) so you can easily create simple projects from scratch.

2

Interacting With Gradle

Learn to run Gradle like a power user through the command line and IDE. You'll be ready to use Gradle in any situation.

3

Mastering Build Scripts

Unlock the mysteries of the build script so it becomes second nature and you can confidently set up any project.

4

Java Projects

Build, test, and execute Java projects like a pro. Learn the best practices then use them to level up your own project.

5

Structuring Projects for Success

Discover how to organise your build system the right way, so it easily supports a growing codebase.

Ready to Build Faster with Gradle?

Gradle Build Bible is designed for Java developers like you. No fluff—just the knowledge you need with real-world examples.

Each chapter combines clear code samples and step-by-step exercises. This systematic approach is the fastest way to go from novice to Gradle pro.

Read Gradle Build Bible now

Jump in and start learning

Understanding the Gradle fundamentals

1. Understanding the Gradle fundamentals

1.1. Introduction

This chapter gives you a clear overview of Gradle and how it works before diving into details later.

We’ll cover four key Gradle concepts:

  1. Project: the container for your entire build.

  2. Build script: defines what your build does.

  3. Tasks: individual units of work added to your build script.

  4. Plugins: pre-packaged components that add useful build features.

These concepts are all you need to understand before creating simple Gradle projects.

It’s so straightforward to get started with Gradle that you can create a project in just 30 seconds. This chapter walks through every step of that process, and by the end you’ll be able to create this project yourself from scratch.

1.2. The Gradle project

The highest-level concept in Gradle is the project, which represents the entire application you’re building.

One well-known example of a Gradle project is Spring Boot. Gradle builds Spring Boot into libraries that we can use to create our own applications.

image

Before we get into a demo of a Gradle project, here’s a quick overview. There’s no limit to the size of a Gradle project. It could represent the smallest microservice you can imagine which accomplishes a specific task, or a huge monolithic application.

As you go through this book you’ll encounter several Gradle projects, starting off very simple, then growing slightly in size and complexity.

Maybe you’re wondering practically speaking, what does a project look like? In its simplest form it consists of a project directory, and within that a single file named settings.gradle.kts. Inside that file we specify the name of the Gradle project.

Once a Gradle project has been created, you can interact with it on the command line using the gradle command, which we’ll cover in detail in later lessons.

For the 30-second project we’ll work on in this chapter, we have a project directory named 30-second-project.

30-second-project
`-- settings.gradle.kts

In there is the settings.gradle.kts file which contains the name of the project specified in quotes.

Listing 1. Setting a project name in settings.gradle.kts
rootProject.name = "<the project name>"

With this file in place we now have a Gradle project we can interact with.

If I run the gradle tasks command inside the project directory, we get a message Tasks runnable from root project `30-second-project' and a list of tasks available in this project.

$ gradle tasks

> Task :tasks

------------------------------------------------------------
Tasks runnable from root project '30-second-project'
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project '30-second-project'.
dependencies - Displays all dependencies declared in root project '30-second-project'.
dependencyInsight - Displays the insight into a specific dependency in root project '30-second-project'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
outgoingVariants - Displays the outgoing variants of root project '30-second-project'.
projects - Displays the sub-projects of root project '30-second-project'.
properties - Displays the properties of root project '30-second-project'.
resolvableConfigurations - Displays the configurations that can be resolved in root project '30-second-project'.
tasks - Displays the tasks runnable from root project '30-second-project'.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

This shows us that our project is properly setup and Gradle understands it. More details on all of this, including understanding what tasks are, is coming up in later lessons.

Project naming

You can name your project anything you like, it doesn’t have to match the name of the project directory. Be imaginative!

Strictly speaking, you don’t have to specify a project name in settings.gradle.kts, but it’s a good idea because it means even if someone clones your repository into a differently named directory, the project name remains the same.

Terminology: if you hear me or others talking about Gradle builds, then it’s just another way of talking about Gradle projects. They’re the same thing.

In the rest of this chapter, we’ll build on top of the simple project we just created to explore more Gradle fundamentals.

1.3. The Gradle build script

As you just saw, a settings.gradle.kts file in a project directory is all we need to create a Gradle project. At this point though, our simple project isn’t much fun as it doesn’t actually do anything.

When you want to start doing stuff with your project, like actually building your application, that’s when you need to add a Gradle build script. It contains the definition of how your application will get built.

image

When it comes to writing your build script, you have a choice of language, Groovy or Kotlin. Kotlin is the best choice for modern Gradle projects since it provides a better editing experience in the IDE. It’s also the option that Gradle recommend.

Since you define your build script as code, it’s very flexible because you can write any code logic you want to do pretty much anything. You’ll learn all the details of the build script in later lessons. For now though, let’s extend our 30-second project to illustrate a simple build script example.

In our project, we’ll create a file named build.gradle.kts, which will contain our build script written in the Kotlin programming language.

30-second-project
|-- build.gradle.kts
`-- settings.gradle.kts

Inside this file we can write any code we want. Don’t worry if you’re not familiar with Kotlin as you’ll learn more about it later, but for now we’ll just use the println function which prints the string you pass it.

Listing 2. Adding simple code to build.gradle.kts
println("This is the 30 second project")

If I run the gradle command from within the project directory let’s see what happens. It says This is the 30 second project. Cool!

$ gradle

> Configure project :
This is the 30 second project

> Task :help

Welcome to Gradle 8.2.1.

To run a build, run gradle <task> ...

To see a list of available tasks, run gradle tasks

To see more detail about a task, run gradle help --task <task>

To see a list of command-line options, run gradle --help

For more detail on using Gradle, see https://docs.gradle.org/8.2.1/userguide/command_line_interface.html

For troubleshooting, visit https://help.gradle.org

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

Likewise, in the build script I could define variables a and b, and print their sum like this.

Listing 3. Doing some calculations in build.gradle.kts
val a = 2
val b = 3

println(a + b)

Now when I run the gradle command we get the output 5, which is 2 plus 3.

$ gradle

> Configure project :
5

> Task :help

Welcome to Gradle 8.2.1.

To run a build, run gradle <task> ...

To see a list of available tasks, run gradle tasks

To see more detail about a task, run gradle help --task <task>

To see a list of command-line options, run gradle --help

For more detail on using Gradle, see https://docs.gradle.org/8.2.1/userguide/command_line_interface.html

For troubleshooting, visit https://help.gradle.org

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

That’s very nice, you might be thinking, but I don’t really want to have to write my entire build in code like this. No problem, because actually defining Gradle builds requires very little real coding.

In Gradle, you reuse predefined tasks, plugins, and other elements, which you configure together in the build script to seamlessly build small or large projects. By the end of this book you’ll be very familiar with all of these elements, and you’ll have the confidence to apply them in your own projects.

For now, just remember that the Gradle build script is where your build logic lives. In the rest of this chapter, you’ll be introduced briefly to two of the most important elements of the build script, tasks and plugins, as we finish creating this sample project.

Finally, if you’ve used the Maven build tool before, you’re right, the build.gradle.kts file is the equivalent of Maven’s pom.xml. As you’ll find out soon though, Gradle’s build script is a lot more flexible.

1.4. The Gradle task

You just learnt how you can define a Gradle build script in a build.gradle.kts file, and in that file write any code you want. To start creating useful Gradle projects though, we need to use one of the components Gradle makes available to us called the task.

image

It represents a unit of work to get done in your build, whether that be copying files, compiling code, running tests, or anything else. Every task that’s part of your Gradle build script can be executed from the command line. Your Gradle project could consist of many tasks, and it’s up to you which ones you choose to run at any particular time.

And as you may have guessed, Gradle comes with many pre-packaged tasks which we can use directly in a build script to achieve specific outcomes. With the pre-packaged tasks, all the code logic to do whatever the task does has been written for us. We just have to define an instance of the task, and configure it how we need it. If we need to do something that isn’t supported by one of the pre-packaged tasks, we can always create our own custom tasks.

So how do we use a task in our build script? To show you how, in our build.gradle.kts file I’m going to define a task to copy a file from one location to another. We’ll use one of the pre-packaged Gradle tasks, unsurprisingly called Copy. To define an instance of this task, we’ll need only 4 pieces of information:

  1. the task name

  2. the type of task, which is Copy

  3. the source file location

  4. the destination file location

Once the task is defined, we’ll run it from the command line to copy the file.

Let’s go back to our project as we left it in the last lesson, and create a new file to be copied, called important-message.txt.

Within there we’ll write this extremely important message.

Listing 4. important-message.txt
Watch out! This is the 30 second project

Now back in our build.gradle.kts file we’re going to define our task.

Listing 5. Defining a copy task
tasks.register<Copy>("copyMessage") {
   from("important-message.txt")
   into(layout.buildDirectory)
}

Task definition syntax: if you’re wondering why we’re using tasks.register here to define our task rather than other available syntaxes, we’ll cover the advantages of this in Chapter 3.

This creates a task called copyMessage of type Copy. We’re using from to set the source file and into to set the destination directory of the task. This task syntax will be explained in full in later lessons.

We can run this task from a command prompt within the 30-second-project with gradle copyMessage.

$ gradle copyMessage

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

In the project directory we now have a build directory containing the copied important-message.txt.

30-second-project
|-- build
|   `-- important-message.txt
|-- build.gradle.kts
|-- important-message.txt
`-- settings.gradle.kts

In summary, that was a very simple use of the Copy task. It’s very flexible though, and can be scaled up to copy whole directories and even do token replacement within files.

Don’t worry about remembering the syntax of defining tasks right now, as we’ll cover it again many times. Later on, you’ll also learn about the other types of Gradle tasks, including the Java related tasks, as well as creating your own custom tasks.

For now, all you need to take away from this tasks introduction is that tasks do some work within your project, can be pre-packaged tasks or custom tasks, and can be executed from the command line.

1.5. The Gradle plugin

You just saw how to define a task in your build script and then execute it from the command line. The last fundamental Gradle concept to introduce you to in this chapter is the Gradle plugin. Plugins allow us to automatically add helpful tasks into our Gradle project using pre-packaged code that either us, Gradle, or some 3rd party has written.

image

And if you’re thinking at this point that this diagram is starting to look a bit like a face, trust me, it was totally unintended!

Before we get into a practical example, here are some key points to understand about plugins.

  • plugins automatically register tasks into our Gradle project, so we don’t need to do that ourselves in the build script

  • you just have to apply a plugin, and then you’re able to execute any of the tasks it exposes

  • the tasks that plugins expose may be pre-packaged Gradle tasks, like the Copy task you saw in the previous lesson, or custom tasks written by the plugin author

  • plugins allow us to add rich functionality to our Gradle project, including multiple tasks which work together

Applying a plugin

To illustrate how to use plugins we’ll make some more changes to our build.gradle.kts file. You’ll see that the syntax for applying plugins is simple, involving just a one line change.

The plugin we’ll apply is one of the most basic plugins, called the base plugin. This plugin adds some tasks to our project which are common to many Gradle projects, hence its name.

We’ll be able to list these tasks using the gradle tasks command. Then, we’ll execute one of them.

Apply the plugin to 30-second-project by adding this snippet at the top of build.gradle.kts.

Listing 6. Applying the base plugin
plugins {
    base
}

With this plugin applied, if we run gradle tasks we can now see 3 additional tasks listed under Build tasks.

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
clean - Deletes the build directory.

Running the clean task

Right now we’ll focus only on the clean task. You’ll learn about the others later on.

In the previous lesson, our copyMessage task created a build directory. The clean task made available by the base plugin allows us to delete the build directory automatically from the command line.

Let’s run the clean task with gradle clean.

$ gradle clean

BUILD SUCCESSFUL in 972ms
1 actionable task: 1 executed

In our project directory we see that the build directory has now been deleted.

30-second-project
|-- build.gradle.kts
|-- important-message.txt
`-- settings.gradle.kts

Later in this book you’ll learn about other plugins, such as the Java plugin, which add rich functionality to projects. For now, all you need to remember from this introductory lesson is that you can easily apply plugins to a build script and plugins automatically add helpful tasks to your project.

1.6. Practical: creating a simple Gradle project

Now it’s time for you to bring together the Gradle concepts from the last four lessons, the project, the build script, the task, and the plugin, and create your first project.

This is a practical lesson, which means you should do the below steps yourself to properly learn these concepts.

A new assignment

The situation is that we’ve been asked by a company that manages many theme parks (also known as amusement parks) to help them with their software builds. As you go through this book you’ll encounter several situations where we’ll create Gradle builds on this topic.

For this lesson, the requirement is very simple. We have several files which contain descriptions for theme park rides. Since we may be running this build for different theme parks we need to substitute in the correct theme park name in the description.

Here’s an example of the rollercoaster.txt file and what the generated file should look like, including the substituted theme park name.

image

And of course, we’re going to accomplish this important assignment with Gradle!

Installing Gradle

Before we get into the implementation, you need to get Gradle installed on your machine. Depending on whether you’re working in a Windows, Mac, or Linux environment the procedure will be different.

Windows
  • open the Windows command prompt (open the Start menu, type cmd, then hit enter)

  • validate that Java is installed

    java -version

You will see details of your current Java installation. You need Java version 8 or above to use Gradle.

  • go to https://gradle.org/releases

  • scroll down and choose the most recent Gradle release

  • choose the binary-only option. Click the link to download the Gradle zip file to your computer.

  • create a Gradle directory on your hard drive, and extract the zip file into that directory:

    • open file explorer (open the Start menu, type file, then hit enter).

    • navigate to your hard drive root directory then right click, go to New > Folder, then enter the name Gradle

    • navigate to where you downloaded the Gradle zip file, copy the zip file, then paste it in the new Gradle directory

    • right-click the zip file and select Extract all to extract the zip file

  • you should now have an additional directory. Go into that directory, go into the bin directory, and copy the path from the address bar at the top of the File explorer and keep it safe for later on

  • now you need to configure your PATH variable so that you can run Gradle commands from wherever you are in the command prompt:

    • go to the Start menu, type environment, then hit Enter when Edit the system environment variables appears.

    • on the dialog that appears, click Environment Variables, then under System variables double-click the Path variable

    • click New, then paste in the location of the Gradle bin directory which you copied earlier

    • hit enter, select OK, then OK again, then OK again

  • close the Windows command prompt, and open a new one (Start menu, type cmd, hit enter)

  • now we’re going to validate our Gradle installation:

    gradle --version
  • you should see some output showing that a specific version of Gradle is installed

If you’re a Windows user, well done, that’s all you need to do before moving onto the next lesson.

Linux
  • validate that Java is installed:

    java -version

You will see details of your current Java installation. You need Java version 8 or above to use Gradle.

  • go to https://gradle.org/releases

  • note the latest Gradle version

  • download the latest version of Gradle using the curl command:

    curl https://downloads.gradle-dn.com/distributions/gradle-<latest-version>-bin.zip \
    --output ~/gradle.zip
  • unzip the file using the unzip command:

    sudo unzip -d /opt/gradle ~/gradle.zip
  • if you’re prompted for your password, enter it because we’re running this command as the root user

  • look at the contents of the Gradle installation using the ls command:

    ls /opt/gradle/gradle-<latest-version>

You should see some files and directories.

  • setup the PATH environment variable:

    echo 'export PATH="$PATH:/opt/gradle/gradle-<latest-version>/bin"' >> ~/.bashrc
  • close the terminal and open a new one

  • check that Gradle has been successfully installed.

    gradle --version
  • you should see output showing that a specific version of Gradle is installed

If you’re a Linux user, well done, that’s all you need to do before moving onto the next lesson.

Other installation options
Homebrew
brew install gradle
SDKMAN!
sdk install gradle <latest-version>
Verify your installation

Once you’ve followed these steps, you know you’re ready to continue if when you open a terminal, type gradle, and hit enter, you see output like this.

$ gradle

> Task :help

Welcome to Gradle 8.2.1.

Directory 'C:\workspace' does not contain a Gradle build.

To create a new build in this directory, run gradle init

For more detail on the 'init' task, see https://docs.gradle.org/8.2.1/userguide/build_init_plugin.html

For more detail on creating a Gradle build, see https://docs.gradle.org/8.2.1/userguide/tutorial_using_tasks.html

To see a list of command-line options, run gradle --help

For more detail on using Gradle, see https://docs.gradle.org/8.2.1/userguide/command_line_interface.html

For troubleshooting, visit https://help.gradle.org

BUILD SUCCESSFUL in 976ms
1 actionable task: 1 executed

If you get an error trying to run the gradle command, make sure that the Gradle bin directory is in your PATH environment variable.

Creating the project

With Gradle installed, we can start creating the Gradle project. For this lesson I suggest using a simple file explorer and text editor of your choice to fully understand the fundamentals. Later on, you’ll learn how to make the best use of Gradle IDE integration to increase your productivity.

We’re going to create all 4 fundamental Gradle elements already discussed in this chapter, including the project, build script, task, and plugin.

  1. create a new project directory theme-park-rides

  2. in the project directory create a file settings.gradle.kts

  3. edit the file and add a single line

    Listing 7. settings.gradle.kts for theme-park-rides project
    rootProject.name = "theme-park-rides"
  4. in the project directory create a descriptions directory

  5. in the descriptions directory create rollercoaster.txt and add the following contents

    At @THEME_PARK_NAME@ thrill seekers should head straight to the rollercoaster. Hands in the air now!

  6. in the descriptions directory create log-flume.txt and add the following contents

    At @THEME_PARK_NAME@ take a ride on the log flume on a hot sunny day. You’ll certainly find it refreshing!

  7. in the descriptions directory create teacups.txt and add the following contents

    At @THEME_PARK_NAME@ if you want some leisurely fun, head to the teacups. Teatime will never be the same again!

  8. in root of the project directory create a file build.gradle.kts

  9. in build.gradle.kts add the following contents

    Listing 8. build.gradle.kts for theme-park-rides project
    import org.apache.tools.ant.filters.ReplaceTokens
    
    plugins {
        base
    }
    
    tasks.register<Copy>("generateDescriptions") {
        from("descriptions")
        into(layout.buildDirectory.dir("descriptions"))
        filter<ReplaceTokens>("tokens" to mapOf("THEME_PARK_NAME" to "Grelephant's Wonder World"))
    }
  10. on the command line in the root of the project directory run gradle generateDescriptions

  11. observe that description files have been created in build/descriptions with the correctly substituted THEME_PARK_NAME

  12. run gradle clean and see that the build directory is deleted

Note
You can find a sample project in the accompanying GitHub repository.

Summary

Well done! You’ve managed to achieve the desired outcome.

I know this is a simple example, but copying files and doing token substitution is common when building projects with Gradle, especially when handling property files. And you’ve just done this in a new Gradle project, with a Copy task defined in your build script, along with the base plugin for cleanup of the build directory.

If you have any questions about this practical lesson, send me an email at tom@tomgregory.com and I’ll get back to you.

1.7. Quiz

Question 1

You need to create a Gradle project called my-awesome-project. In which file should you set the project name?

  1. build.gradle.kts

  2. settings.gradle.kts

  3. name.gradle.kts

Question 2

You have an existing Gradle project and need it to do a specific custom action when gradle doSomething is run.

What do you need to do to achieve this?

  1. Define a task

  2. Create a new project

  3. Apply a plugin

Question 3

Which of the following tasks does the base plugin make available when applied to a Gradle project?

  1. help

  2. project

  3. clean

See Appendix for answers.

1.8. Gradle "zip" challenge

The last thing to do to finish off this chapter is an extension of the earlier practical lesson. In that lesson we built a simple Gradle project which copies theme park ride descriptions, replacing tokens with the theme park name.

Challenge lesson: in this lesson you’ll attempt to add some new functionality yourself, referring to the Gradle documentation where required. These scenarios are important, as they’re similar to when you’re working with Gradle projects on your own.

An additional requirement

The theme park company we’re working for has requested that to save precious time, we should automatically zip up these ride descriptions for later deployment to their production environment.

To be clear about the end result, I expect to be able to run gradle generateDescriptions to generate the descriptions as we saw in the practical earlier. And then I want to run gradle zipDescriptions which should package all those description files into a zip file located at build/descriptions.zip.

To get you started, here are a few pointers.

  1. you’ll need to create a new Gradle task called zipDescriptions

  2. the task will need to be of type Zip (see the documentation)

  3. you’ll need to set task properties destinationDirectory and archiveFileName using the .set syntax e.g. destinationDirectory.set(layout.buildDirectory) (you’ll learn exactly how this works in later chapters)

  4. you’ll need to call the from method e.g. from("some-source-location")

OK, so now it’s over to you!

If you need more help or want to compare your solution, check out the sample project. Good luck!

2. Interacting with Gradle

2.1. Introduction

In this chapter, you’re going to become proficient at interacting with Gradle through the command line and IDE. Whether you’re a developer, DevOps engineer, or any other role where you have to interact with Gradle, properly understanding that interface will allow you to do what you need to do more effectively.

By the end of this chapter, you’ll have the knowledge and practical skills to:

  • create projects using the Gradle command line wizard

  • interact with existing Gradle projects on the command line effectively

  • understand the Gradle project layout in detail, including what should go into version control

  • know how to work productively with a Gradle project in IntelliJ IDEA

Appendix

Quiz answers

Here are the answers and explanations for the quizzes that appear at the end of the specified chapter.

Chapter 1

  • Question 1 (answer = 2)

settings.gradle.kts is where the project name is specified using the syntax rootProject.name = "my-awesome-project"

  • Question 2 (answer = 1)

A task is used to define a specific action to be executed in your Gradle project. You can use pre-packaged tasks (e.g. Copy) or define your own custom logic.

  • Question 3 (answer = 3)

The base plugin adds the clean task to your Gradle project. The other tasks listed are available by default within any Gradle project.

Copyright Tom Gregory Limited 2024

For any queries or corrections, please contact tom@tomgregory.com.

Continue Your Gradle Journey Today

Don't let slow builds hold you back.
Join 100s of developers who've learned Gradle the fast way.