# How to forward reference tasks for configuration?

**URL:** <https://discuss.gradle.org/t/how-to-forward-reference-tasks-for-configuration/35445>\
**Category:** Help/Discuss\
**Created:** [March 28, 2020, 12:37pm UTC](https://discuss.gradle.org/t/how-to-forward-reference-tasks-for-configuration/35445 "2020-03-28T12:37:18Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![TWiStErRob](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/twisterrob/32/7261_2.png) [@TWiStErRob](https://discuss.gradle.org/u/TWiStErRob)\
**Post date:** [March 28, 2020, 12:37pm UTC](https://discuss.gradle.org/t/how-to-forward-reference-tasks-for-configuration/35445/1 "2020-03-28T12:37:19Z")

</div>

Let’s say I have a project where I know eventually there will be a task with name “foo”. How do I attach a configuration block to it? For example:

```gradle
println("configuring build")

println("re-configuring foo")
// What do I write here to do tasks.named("foo").configure {}?
// Note: reordering afterEvaluate of foo creation and this is not an option.

afterEvaluate {
	println("registering foo")
	tasks.register("foo") {
		println("configuring foo")
	}
}

```

* * *

I tried

```gradle
println(tasks.findByName("foo"))
println(tasks.named("foo"))

```

and

```gradle
afterEvaluate {
	println(tasks.findByName("foo"))
	println(tasks.named("foo"))
}

```

but I keep getting `null` from `findByName` and from `named` I get:

```gradle
* What went wrong:
A problem occurred configuring root project 'taskRef'.
> Task with name 'foo' not found in root project 'taskRef'.

```

---

<div class="post-metadata">

**Author:** ![jjustinic](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/jjustinic/32/9005_2.png) [@jjustinic](https://discuss.gradle.org/u/jjustinic)\
**Post date:** [March 29, 2020, 7:24am UTC](https://discuss.gradle.org/t/how-to-forward-reference-tasks-for-configuration/35445/2 "2020-03-29T07:24:05Z")

</div>

You can’t attach anything to a task by name if it has not yet been declared (deferred configuration doesn’t change anything here, it still has to be declared first, even if not yet realized).

To get close to this, you will need to hook into the task container lifecycle so that your code executes after the task is actually added (code before the `afterEvaluate` block executes after the `task.register('foo')` executes). Without doing this, the order of code in the file still matters (both using `afterEvaluate`, for example).

```groovy
tasks.whenTaskAdded {
    if (it.name == 'foo') {
        // configure it here
    }
}

```

```groovy
tasks.withType(DefaultTask) { // Nearly identical to above, but might be preferred if you can be more specific about task type
    if (it.name == 'foo') {
        // configure it here
    }
}

```

The only potential concern is that this code will run _before_ the configuration added when the task is registered (i.e. `println("configuring foo")`).

---

<div class="post-metadata">

**Author:** ![TWiStErRob](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/twisterrob/32/7261_2.png) [@TWiStErRob](https://discuss.gradle.org/u/TWiStErRob)\
**Post date:** [March 29, 2020, 1:11pm UTC](https://discuss.gradle.org/t/how-to-forward-reference-tasks-for-configuration/35445/3 "2020-03-29T13:11:10Z")

</div>

Thank you for the help!

> The only potential concern is that this code will run _before_ the configuration added when the task is registered

I guess it depends what one wants to configure. I was only looking to add `dependsOn` and `mustRunAfter`s so `whenTaskAdded`/`withType` would work, but I’ve had problems in the past when I needed to alter task configuration state **after** the initial configuration has been done.

* * *

Otherwise it became convoluted quick, but it works now mostly after about 10 iterations of tries:

```gradle
println("configuring build")

println("registering bar")
tasks.register("bar") {
	println("configuring bar")
}

configureTaskForSureAfterInitialConfiguration(project, "bar", DefaultTask) {
	println("configuring bar after register")
}
configureTaskForSureAfterInitialConfiguration(project, "foo", DefaultTask) {
	println("configuring foo before register")
}
afterEvaluate {
	configureTaskForSureAfterInitialConfiguration(project, "foo", DefaultTask) {
		println("configuring foo in afterEvaluate before register")
	}
	configureTaskForSureAfterInitialConfiguration(project, "bar", DefaultTask) {
		println("configuring bar in afterEvaluate after register")
	}
}
afterEvaluate {
	println("registering foo")
	tasks.register("foo") {
		println("configuring foo")
	}
}
afterEvaluate {
	configureTaskForSureAfterInitialConfiguration(project, "foo", DefaultTask) {
		println("configuring foo in afterEvaluate after register")
	}
}

static void configureTaskForSureAfterInitialConfiguration(
	Project project, String name, Class taskType, Action<? super Project> configure
) {
	project.tasks.withType(taskType) {
		if (it.name == name) {
			project.afterEvaluate {
				project.tasks.named(name).configure(configure)
			}
		}
	}
}
tasks.register("dummy")

```

```gradle
> Configure project :
configuring build
registering bar
configuring bar
configuring bar after register
registering foo
configuring foo
configuring bar in afterEvaluate after register
configuring foo before register
configuring foo in afterEvaluate before register
configuring foo in afterEvaluate after register

```

This works everywhere by running after the initial configuration. Even if it is called after `register` which doesn’t work with `whenTaskAdded`/`withType` (this part wasn’t in OP). `configureTaskForSureAfterInitialConfiguration` seems to be a good way of making sure the task is configured correctly, even if the implementation detail of when the task created is changed inside the plugin declaring `foo`.

* * *

Now, there’s only one interesting issue, `foo` and `bar` get configured even when I’m not executing them: `gradle dummy` ☹ I thought that using `register`/`named` would result in lazy configuration.
