Engineering Full Stack Apps with Java and JavaScript
Gradle tasks are actually objects and a task object has properties and methods just like any other object. By default, each new task receives a type of DefaultTask in Gradle (similar to how all classes are children of the Object class in Java). DefaultTask only contain the functionality required for them to interface with the Gradle project model and do not do any additional actions such as compiling or executing code.
dependsOn(task)
Adds task dependency.
All dependencies will be run before the current task.
You can add dependency in many different ways. Most common form is as:
task current {
dependsOn before
}
Or the shortcut form for the same as:
task current (dependsOn: before)
Other alternate forms for using dependsOn are:
dependsOn << before
dependsOn ‘before’
current.dependsOn before
You can also have multiple dependencies as:
dependsOn << before1
dependsOn << before2
or
dependsOn before1, before2
or
current.dependsOn before1, before2
or
task current (dependsOn: [before1, before2])
doFirst(closure)
Adds a block of code to the beginning of a task’s action.
You can even use this to add code before an action defined by a build file or a plug-in that you don’t control.
You can invoke the doFirst method directly on the task object, passing a closure to the method.
If you have more than one doFirst method, last one defined will be called first, then second last abd so on (similar to a Stack).
task helloTask << {
println 'Hello World'
}
helloTask.doFirst {
println 'Do First 1'
}
helloTask.doFirst {
println 'Do First 2'
}
When executed as ‘gradle -q helloTask’, you will get the output as:
Do First 2
Do First 1
Hello World
You can also call doFirst method from within the configuration block.
Configuration blocks will be executed first, followed by all doFirst actions in reverse order, followed by actual task actions.
Example:
task helloTask << {
println 'Hello World'
}
helloTask {
println 'Inside config block 1'
helloTask.doFirst {
println 'Do First 1'
}
helloTask.doFirst {
println 'Do First 2'
}
println 'Inside config block 1 after doFirst call'
}
helloTask {
println 'Inside config block 2'
helloTask.doFirst {
println 'Do First 3'
}
helloTask.doFirst {
println 'Do First 4'
}
}
When executed as ‘gradle –q helloTask’, you will get the output as:
Inside config block 1
Inside config block 1 after doFirst call
Inside config block 2
Do First 4
Do First 3
Do First 2
Do First 1
Hello World
Wrapping inside configuration block is also a good way to group similar doFirst calls.
doLast(closure)
doLast is similar to doFist and execute the block of code after the task than before.
If you change all doFirst to doLast in the previous example (including println statements) and execute ‘gradle -q helloTask’, you will get the below output:
Inside config block 1
Inside config block 1 after doLast call
Inside config block 2
Hello World
Do Last 1
Do Last 2
Do Last 3
Do Last 4
All the DoLast calls are executed in order (FIFO) and all DoFirst calls are executed in order LIFO.
Any doFirst or doLast calls done from within a task action (execution phase) are not considered; doFirst or doLast calls should be outside all blocks or within configuration blocks.
onlyIf(closure)
We can execute a task conditionally.
task helloTask << {
println 'Hello World'
}
helloTask.onlyIf {
System.properties['sys.prop'] == 'abcd'
}
helloTask is executed only if we have a system property 'sys.prop' with value abcd.
When executed as ‘gradle -q helloTask’, we get a blank output.
When executed as ‘gradle -Dsys.prop=abcd -q helloTask’, we get output as:
Hello World
Question 1: Predict output
task helloTask << {
println 'Hello World'
}
helloTask {
println 'Inside config block 1'
helloTask.doLast {
println 'Do Last 1'
}
println 'Inside config block 1 after doLast call'
}
helloTask << {
println 'Inside block 2'
helloTask.doLast {
println 'Do Last 2'
}
}
Answer 1:
Output differed when using Gradle 1.11 and 2.1 versions.
Common output part for Gradle 1.11 and 2.1 versions:
Inside config block 1
Inside config block 1 after doLast call
Hello World
Do Last 1
Inside block 2
doFirst or doLast calls done from within a task action (execution phase) are not considered; either doFirst or doLast calls should be outside all blocks or within configuration blocks.
If you replace all doLast with doFirst and Last with First, you will get below output:
Inside config block 1
Inside config block 1 after doLast call
Do First 1
Hello World
Inside block 2
The doFIrst is executed before execution (Hello World). And doFirst within the execution block is ignored.
While executing using Gradle 2.1, below error was also thrown after above output:
FAILURE: Build failed with an exception.
* Where:
Build file '<path-omitted>\build.gradle' line: 20* What went wrong:
Execution failed for task ':helloTask'.
> Cannot call Task.doLast(Closure) on task ':helloTask' after task has started execution. Check the configuration of task ':helloTask' as you may have misused '<<' at task declaration.* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
Similar exception was thrown while using doFirst also, after printing the statements similar to previous case.
Book: Building and Testing with Gradle by Tim Berglund and Matthew McCullough.
Examples in this note has been tested against Gradle versions 1.11 and 2.1.