Posted on by & filed under Content - Highlights and Reviews, Programming & Development.

A guest post by Andrew Oberstar, a community contributor to Gradle and plugin author. You can find him at or

Gradle is a build automation tool, making use of Groovy to provide a powerful Domain Specific Language (DSL) to describe and instruct the behavior of your build.

Part of Gradle’s core is reflecting the actions of a build in tasks that become part of a Directed Acyclic Graph (DAG) expressing the relationships between those tasks.

Up until recently, the only option was to use task dependencies to affect the DAG. This post will discuss task dependencies and how they compare to two new task ordering features: must run after and finalizer tasks.


Gradle users will be pretty familiar with traditional task dependencies, but I’ll illustrate the key points to serve as a comparison to the other options.

Gradle can implicitly determine the dependencies of many tasks, but you can also declare them explicitly:

Now, if I call myTask2, Gradle knows it should run myTask1 first.

Even if I try to run them in the wrong order, Gradle will correct me.

The key behavior is that asking for myTask2 requires myTask1 to run sometime before it.

Must Run After

Must run after was introduced in Gradle 1.6 as an alternative to the stricter dependsOn. This is a way to enforce that tasks run in the order you desire, without forcing both tasks to be run.

If I call both tasks, myTask2 will run after myTask1.

However, if I only call myTask2, myTask1 won’t even run.

Must run after means that if, and only if, myTask1 and myTask2 are both requested to be run (either directly or via other dependencies), myTask2 will always run after myTask1.

My favorite use cases for this are:

  • Ensuring that my integration tests run after my unit tests
  • Making sure that clean runs before any of the real tasks

NOTE: There is talk of an eventual should run after feature that would be more of a suggestion.

Finalized By

In the 1.7 version there is new support for “finalizer” tasks. These are tasks that need to run as a follow up to another task, whether it was requested or not.

If I ask for myTask1, it will run myTask2 afterwards:

Even if myTask1 fails:

Finalizer tasks are essentially reverse dependencies. Asking for myTask1 requires that myTask2 be run sometime after, even if it fails.

One of the canonical use cases for this is stopping an application server after a task that has used it.


Gradle’s task relationship features have evolved a lot over the last couple of releases, providing far more flexibility into how tasks are ordered at runtime. This post has shown three ways to express those relationships to inform Gradle of how the build should behave.

See below for some Gradle resources from Safari Books Online.

Safari Books Online has the content you need

Gradle Beyond the Basics is an advanced guide that provides the recipes, techniques, and syntax to help you master this build automation tool. With clear, concise explanations and lots of ready-to-use code examples, you’ll explore four discrete areas of Gradle functionality: file operations, custom Gradle plugins, build lifecycle hooks, and dependency management.
Building and Testing with Gradle shows you to us Gradle for building and testing software written in Java and other JVM languages. It covers transitioning to Gradle from Maven, integration with IDEs such as Eclipse, and more.
Gradle Effective Implementation Guide is a great introduction and reference for using Gradle. The Gradle build language is explained with hands on code and practical applications. You learn how to apply Gradle in your Java, Scala or Groovy projects, integrate with your favorite IDE and how to integrate with well-known continuous integration servers.

About the author

andrew Andrew Oberstar, a community contributor to Gradle and plugin author. You can find him at or

Tags: Finalzer Tasks, gradle, Must Run After, Task Ordering,

Comments are closed.