Over a million developers have joined DZone.

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

The DevOps zone is brought to you in partnership with Sonatype Nexus. The Nexus suite helps scale your DevOps delivery with continuous component intelligence integrated into development tools, including Eclipse, IntelliJ, Jenkins, Bamboo, SonarQube and more. Schedule a demo today

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.

The DevOps zone is brought to you in partnership with Sonatype Nexus. Use the Nexus Suite to automate your software supply chain and ensure you're using the highest quality open source components at every step of the development lifecycle. Get Nexus today


Published at DZone with permission of Hubert Klein Ikkink, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}