Discussion:
Running a task after execution of another task
Glen Stampoultzis
2011-05-18 03:34:08 UTC
Permalink
Hi,

I have a little problem with getting a task to run after execution of
another task. In this case I have a task called integrationTest. What I
want to do is use the Jetty plugin to execute the jettyRun task before
running the integrationTest task and to run jettyStop task after it has
finished.

integrationTest.dependsOn(jettyRun) lets me easily start the jetty server
but there doesn't seem to be a good way of hooking in jettyStop at the end.

Using integrationTest.doLast { jettyRun.execute() } lets me hook in an
action at the end of the execution chain but this suffers from a couple of
problems. Firstly if integrationTest is up-to-date then the actions aren't
run so the server doesn't stop. Secondly executing a task this way seems
to be non-standard (execute is a private API).

I found a solution to the first problem with the following code:

gradle.taskGraph.afterTask { Task task, TaskState state ->
if (task.name == 'integrationTest') {
jettyStop.execute();
}
}

but this still suffers from the second issue. Is there a clean way do this?
Ken Sipe
2011-05-18 03:43:46 UTC
Permalink
I haven't tried this... but here's an idea :)

integrationTest.doFirst {
tasks.jettyRun.execute()
}

integrationTest.doLast {
tasks.jettyStop.execute()
}

you can probably shorten it... and as you can see... jetty will only run if the integrationTest runs... so if it skips or is up-to-date, you're good.
Hi,
I have a little problem with getting a task to run after execution of another task. In this case I have a task called integrationTest. What I want to do is use the Jetty plugin to execute the jettyRun task before running the integrationTest task and to run jettyStop task after it has finished.
integrationTest.dependsOn(jettyRun) lets me easily start the jetty server but there doesn't seem to be a good way of hooking in jettyStop at the end.
Using integrationTest.doLast { jettyRun.execute() } lets me hook in an action at the end of the execution chain but this suffers from a couple of problems. Firstly if integrationTest is up-to-date then the actions aren't run so the server doesn't stop. Secondly executing a task this way seems to be non-standard (execute is a private API).
gradle.taskGraph.afterTask { Task task, TaskState state ->
if (task.name == 'integrationTest') {
jettyStop.execute();
}
}
but this still suffers from the second issue. Is there a clean way do this?
Glen Stampoultzis
2011-05-18 04:13:36 UTC
Permalink
Thanks, that seems to work fairly well. I had thought doFirst just adds the
action to the start of the action queue rather than executing before the
task itself but obviously that was an incorrect assumption.

It still leaves me with the smaller issue of using a non-public API to
execute the tasks but I guess I can live with that.
Post by Ken Sipe
I haven't tried this... but here's an idea :)
integrationTest.doFirst {
tasks.jettyRun.execute()
}
integrationTest.doLast {
tasks.jettyStop.execute()
}
you can probably shorten it... and as you can see... jetty will only run if
the integrationTest runs... so if it skips or is up-to-date, you're good.
Hi,
I have a little problem with getting a task to run after execution of
another task. In this case I have a task called integrationTest. What I
want to do is use the Jetty plugin to execute the jettyRun task before
running the integrationTest task and to run jettyStop task after it has
finished.
integrationTest.dependsOn(jettyRun) lets me easily start the jetty server
but there doesn't seem to be a good way of hooking in jettyStop at the end.
Using integrationTest.doLast { jettyRun.execute() } lets me hook in an
action at the end of the execution chain but this suffers from a couple of
problems. Firstly if integrationTest is up-to-date then the actions aren't
run so the server doesn't stop. Secondly executing a task this way seems
to be non-standard (execute is a private API).
gradle.taskGraph.afterTask { Task task, TaskState state ->
if (task.name == 'integrationTest') {
jettyStop.execute();
}
}
but this still suffers from the second issue. Is there a clean way do this?
Adam Murdoch
2011-05-18 19:11:24 UTC
Permalink
Thanks, that seems to work fairly well. I had thought doFirst just adds the action to the start of the action queue rather than executing before the task itself but obviously that was an incorrect assumption.
It still leaves me with the smaller issue of using a non-public API to execute the tasks but I guess I can live with that.
There are a couple of other downsides to this approach.

We do want to add some way to solve this problem, as it's a pretty common one. One option we've discussed is to allow you to declare 'initializer' and 'finalizer' tasks for a given task. An initializer is a task which must run before the main task (like a dependency) and which is run only if the main task will be run. So, for example, jettyRun would be skipped if the integration tests are up-to-date. A finalizer is a task which must run after the main task, whether the main task succeeds or fails, and which is automatically added to the dag when the main task is added.
I haven't tried this... but here's an idea :)
integrationTest.doFirst {
tasks.jettyRun.execute()
}
integrationTest.doLast {
tasks.jettyStop.execute()
}
you can probably shorten it... and as you can see... jetty will only run if the integrationTest runs... so if it skips or is up-to-date, you're good.
Hi,
I have a little problem with getting a task to run after execution of another task. In this case I have a task called integrationTest. What I want to do is use the Jetty plugin to execute the jettyRun task before running the integrationTest task and to run jettyStop task after it has finished.
integrationTest.dependsOn(jettyRun) lets me easily start the jetty server but there doesn't seem to be a good way of hooking in jettyStop at the end.
Using integrationTest.doLast { jettyRun.execute() } lets me hook in an action at the end of the execution chain but this suffers from a couple of problems. Firstly if integrationTest is up-to-date then the actions aren't run so the server doesn't stop. Secondly executing a task this way seems to be non-standard (execute is a private API).
gradle.taskGraph.afterTask { Task task, TaskState state ->
if (task.name == 'integrationTest') {
jettyStop.execute();
}
}
but this still suffers from the second issue. Is there a clean way do this?
--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com
Sergey
2013-09-20 12:58:32 UTC
Permalink
Task.finalizedBy is in action now, but seems that Gradle doesn't consider
that configured finalizer task[s] may change (e.g. bytecode instrumentation)
the finalizedTask.outputs.files...
And that eventually directs to a failed up-to-date check for finalized task.
Any comments ?



--
View this message in context: http://gradle.1045684.n5.nabble.com/Running-a-task-after-execution-of-another-task-tp4405504p5711886.html
Sent from the gradle-user mailing list archive at Nabble.com.
Adam Murdoch
2013-09-20 20:59:09 UTC
Permalink
Post by Sergey
Task.finalizedBy is in action now, but seems that Gradle doesn't consider
that configured finalizer task[s] may change (e.g. bytecode instrumentation)
the finalizedTask.outputs.files...
And that eventually directs to a failed up-to-date check for finalized task.
Any comments ?
This is true of any task that changes the output of another task in place, without copying it somewhere else.

It's something we plan to improve at some point. In the meantime, you need to give each task its own output directory, or use a Task.doLast() action instead of a finalizer task.


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com

Join us at the Gradle eXchange 2013, Oct 28th in London, UK: http://skillsmatter.com/event/java-jee/gradle-exchange-2013
Sergey
2013-09-23 07:44:56 UTC
Permalink
On 20/09/2013, at 10:58 PM, Sergey <
Post by Sergey
Task.finalizedBy is in action now, but seems that Gradle doesn't consider
that configured finalizer task[s] may change (e.g. bytecode
instrumentation)
the finalizedTask.outputs.files...
And that eventually directs to a failed up-to-date check for finalized task.
Any comments ?
This is true of any task that changes the output of another task in place,
without copying it somewhere else.
It's something we plan to improve at some point. In the meantime, you need
to give each task its own output directory, or use a Task.doLast() action
instead of a finalizer task.
--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com
http://skillsmatter.com/event/java-jee/gradle-exchange-2013
Maybe that would be interesting to somebody ...
I've an example how to workaround this on compileJava & jibxBind pair
sample.
Note that this approach allows execute jibxBind & compileJava tasks both
separately and in context of overall build process execution with correct
up-to-date check and mutual dependency:





--
View this message in context: http://gradle.1045684.n5.nabble.com/Running-a-task-after-execution-of-another-task-tp4405504p5711892.html
Sent from the gradle-user mailing list archive at Nabble.com.

Continue reading on narkive:
Loading...