Over a million developers have joined DZone.

Gradle Goodness: Lazy Task Properties

DZone's Guide to

Gradle Goodness: Lazy Task Properties

Sometimes it is necessary to support lazy evaluation of task properties in Gradle. In this post, we have a look at an example that implements exactly this type of support.

· DevOps Zone ·
Free Resource

Best practices for getting to continuous deployment faster and with dramatic results in reduced outage minutes, development costs, and QA testing cycles. Brought to you by Rainforest QA.

When we create our own custom tasks we might need to support lazy evaluation of task properties. A Gradle build has three phases: initialisation, configuration and execution. Task properties can be set during the configuration phase, for example when a task is configured in a build file. But our task can also evaluate the value for a task property at execution time. To support evaluation during execution time we must write a lazy getter method for the property. Also we must define the task property with def or type Object. Because of the Object type we can use different types to set a value. For example a Groovy Closure or Callable interface implementation can be used to execute later than during the configuration phase of our Gradle build. Inside the getter method we invoke the Closure or Callable to get the real value of the task property.

Let's see this with a example task. We create a simple class with two task properties: user and outputFile. The user property must return aString object and the outputFile property a File object. For the outputFile property we write a getOutputFile method. We delegate to the Project.file method, which already accepts different argument types for lazy evaluation. We also write an implementation for getUsermethod where we run a Closure or Callable object if that is used to set the property value.

// File: buildSrc/src/main/groovy/com/mrhaki/gradle/Hello.groovy
package com.mrhaki.gradle

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import java.util.concurrent.Callable

class Hello extends DefaultTask {

    // Setter method will accept Object type.
    def outputFile

    File getOutputFile() {
        // The Project.file method already
        // accepts several argument types:
        // - CharSequence
        // - File
        // - URI or URL
        // - Closure
        // - Callable
        project.file outputFile

    // Setter method will accept Object type.
    def user

    String getUser() {
        // If the value is set with a Closure
        // or Callable then we calculate
        // the value. Closure implements Callable.
        if (user instanceof Callable) {
        // For other types we return the
        // result of the toString method.
        } else {

    void sayHello() {
        getOutputFile().text = "Hello ${getUser()}"

Written with Gradle 2.11.

Discover how to optimize your DevOps workflows with our on-demand QA solution, brought to you in partnership with Rainforest QA.

gradle ,properties ,task

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}