skip to content

How do you register a typed task (e.g. a Zip task) lazily in both the Kotlin and Groovy DSL, and what does the 'by registering' syntax do?

level: juniorimportance: should knowfreq 40%

answer

  1. register(name, Type::class) { }
  2. Groovy: register('name', Type) { }
  3. by registering = delegate sugar
  4. property name becomes task name
  5. by creating = eager, avoid

basics

~20 s

Pass the type as a second argument: tasks.register("zipIt", Zip::class) { } in Kotlin, or tasks.register('zipIt', Zip) { } in Groovy. 'by registering' is Kotlin delegate sugar that registers and binds a val to the provider.

solid answer

~40 s

To register a task of a specific type lazily you supply the type alongside the name. **Kotlin DSL:** `tasks.register("zipIt", Zip::class) { archiveFileName.set("app.zip") }`, returning a `TaskProvider<Zip>`. **Groovy DSL:** `tasks.register('zipIt', Zip) { archiveFileName = 'app.zip' }`. Kotlin also offers a delegated-property form: `val zipIt by registering(Zip::class) { ... }` — this is pure syntactic sugar over `register` that (a) registers the task using the property name as the task name and (b) binds the local `val zipIt` to the resulting `TaskProvider<Zip>`. Both forms are fully lazy: the configuration block runs only when the task is realized. The typed overload is what lets you configure type-specific properties (`archiveFileName`, `from`, `destinationDirectory`) with full type safety in the IDE. There's an analogous eager pair (`tasks.create("zipIt", Zip::class)`), but you should prefer the registering/register forms.

code

kotlin · 3 lines
kotlin
// all lazy, all return TaskProvider<Zip>
val a = tasks.register("zipA", Zip::class) { archiveFileName.set("a.zip") }
val b by registering(Zip::class) { archiveFileName.set("b.zip") } // name = "b"

go deeper

for a junior

Know the typed register syntax in both DSLs and that by registering is the lazy Kotlin delegate.

for a middle

Explain that the delegate derives the task name from the property and binds the provider; contrast with by creating.

for a senior

Choose typed register forms in plugins for type-safe configuration and lazy realization across DSLs.

for a principal

Standardize DSL conventions (registering over creating/create) so generated build logic stays lazy and consistent organization-wide.

## Typed registration Many useful tasks are instances of built-in types — `Zip`, `Copy`, `Sync`, `Exec`, `Jar`, `JavaCompile`. Registering them *typed* gives you the type's DSL properties with full static typing. ### Kotlin DSL ```kotlin // explicit register, returns TaskProvider<Zip> val zipIt = tasks.register("zipIt", Zip::class) { from("build/libs") archiveFileName.set("app.zip") destinationDirectory.set(layout.buildDirectory.dir("dist")) } ``` ### Groovy DSL ```groovy tasks.register('zipIt', Zip) { from 'build/libs' archiveFileName = 'app.zip' destinationDirectory = layout.buildDirectory.dir('dist') } ``` ## The `by registering` delegate (Kotlin only) ```kotlin val zipIt by registering(Zip::class) { archiveFileName.set("app.zip") } ``` This is **delegated-property** syntax. Kotlin's `by` hands off the property to the `registering` delegate, which: 1. calls `tasks.register("zipIt", Zip::class) { ... }` using the **property name** as the task name, and 2. binds `zipIt` to the returned `TaskProvider<Zip>`. There's a sibling `by creating` that maps to the eager `create` — avoid it in favor of `registering`. There's also `val existing by existing` / `tasks.named` for referencing already-declared tasks. ## Laziness is preserved None of these realize the task. The block runs only when `zipIt` is realized (requested, depended-on, or `.get()`-ed). The typed form just gives you a better-typed configuration block. ## Eager counterpart (avoid) ```kotlin tasks.create("zipIt", Zip::class) { ... } // eager — configures now ``` Same typing, but pays the configuration cost up front every build. ## Summary Type goes as the second argument to `register`. Kotlin's `by registering(Type::class)` is sugar that registers and binds the provider using the val's name. Prefer it over `create`/`by creating`.

  • What task name does 'val report by registering { }' create?
    "report" — the delegate uses the property name as the task name.
  • Is 'by creating' lazy or eager?
    Eager — it delegates to tasks.create, configuring the task immediately. Prefer 'by registering'.

saying these in an interview costs you the question

  • Thinking 'by registering' is eager (it is lazy).
  • Forgetting the property name becomes the task name with the delegate form.
  • Using by creating when by registering is intended.

context