Gradle Goodness: Lazy Task Properties
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.
Join the DZone community and get the full member experience.
Join For FreeWhen 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 getUser
method 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) {
user.call()
// For other types we return the
// result of the toString method.
} else {
user.toString()
}
}
@TaskAction
void sayHello() {
getOutputFile().text = "Hello ${getUser()}"
}
}
Written with Gradle 2.11.
Published at DZone with permission of Hubert Klein Ikkink , DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
{{ parent.title || parent.header.title}}
{{ parent.tldr }}
{{ parent.linkDescription }}
{{ parent.urlSource.name }}