I have a few tasks which inherit from AbstractExecTask
, and determine most of the parameters from a domain object maintained externally (let’s call it “instance”). All these tasks inherit from a base class like this:
abstract class PgExec<T extends PgExec> extends AbstractExecTask<T> {
PgSqlInstance instance
String executableName = 'pg_ctl'
PgExec(Class<T> taskType, String description) {
super(taskType)
this.group = 'pgSql'
this.description = description
project.afterEvaluate {
configureExec()
configureInstance(instance)
}
}
abstract void configureInstance(PgSqlInstance instance);
...
}
I added a few rules to auto-create these tasks based on the domain object collection (i.e. for each instance I want to add a set of tasks). What I found is that all of a sudden the project.afterEvaluate { ... }
stopped firing.
After a more careful look I realized that the tasks are created after the project has been evaluated, because for some reason that’s when rules were called. This forced me to rewrite the code above as:
abstract class PgExec<T extends PgExec> extends AbstractExecTask<T> {
PgSqlInstance instance
String executableName = 'pg_ctl'
PgExec(Class<T> taskType, String description) {
super(taskType)
this.group = 'pgSql'
this.description = description
project.afterEvaluate {
configureExec()
}
}
void setInstance(PgSqlInstance instance) {
this.instance = instance
if (project.state.executed) {
configureExec()
}
}
...
}
I find that quite ugly, and inconvenient. Typically I can rely on the declarative nature of Gradle (i.e. if I do instances.all { ... }
I am guaranteed that all instances, current and future will be configured in this way).
Is there an idiomatic way to achieve what I am after (i.e. to use the latest and greatest values from instance
)?
Does it make sense to change project.afterEvaluate { ... }
to run the closure immediately if the project has finished evaluation? If not, how about outputting a warning, or an error that the action was ignored?