skip to content

From a build script or another plugin, how do you access and configure an extension that some other plugin registered? Contrast the<>() and configure<>{}.

level: middleimportance: must knowfreq 55%

answer

  1. the<T>() = getByType read
  2. configure<T>{} = typed block
  3. getByName returns Any
  4. findByType/findByName = nullable
  5. throws UnknownDomainObjectException

basics

~10 s

Use the Kotlin DSL helpers: the<MyExtension>() returns the extension instance to read, and configure<MyExtension> { ... } runs a configuration block against it. Both look it up by type in the ExtensionContainer.

solid answer

~50 s

When a plugin registers an extension, consumers can reach it without knowing its registered name by looking it up **by type**. In the Kotlin DSL, `the<MyExtension>()` returns the instance (a typed getter you read from), and `configure<MyExtension> { ... }` applies a configuration `Action` to it. Under the hood both call `project.extensions.getByType(MyExtension::class.java)` / `configure(...)`. You use `the<>()` when you just need to read or tweak one property; `configure<>{}` when you want a whole block, equivalent to writing the named DSL block but resolved by type — handy inside another plugin that can't assume the user's script name is in scope. If you do know the name, `extensions.getByName("greeting")` works but is untyped (returns `Any`). Type-based access is preferred because it's checked and refactor-safe. There is also `findByType`/`findByName` for nullable lookups when the extension may be absent.

code

kotlin · 7 lines
kotlin
// react to another plugin and configure its extension by type
pluginManager.withPlugin("com.example.greeting") {
    configure<GreetingExtension> {
        message.set("set by my plugin")
    }
    val current = the<GreetingExtension>().message.orNull
}

go deeper

for a junior

Know the named block greeting { } configures the extension; awareness that the<>()/configure<>{} exist is enough.

for a middle

Explain that the<>() reads and configure<>{} configures, both by type, and contrast with getByName (untyped) and findByType (nullable).

for a senior

Use configure<T>{} inside pluginManager.withPlugin for cross-plugin integration and justify type-based lookups for robustness.

for a principal

Set conventions for how teams reach across plugin boundaries safely and avoid brittle name-coupling in shared build logic.

## The problem these helpers solve Inside a build script, the named block `greeting { ... }` works because Gradle dynamically exposes that name. But sometimes you need to touch an extension *programmatically* — e.g. from another plugin, or from a precompiled script plugin where the name isn't dynamically in scope, or when you want compile-time type safety. That's what the type-based accessors are for. ## the<>() — typed read access `the<MyExtension>()` is a Kotlin DSL extension function on `ExtensionAware` that delegates to `extensions.getByType(MyExtension::class.java)`. It returns the live instance, so you can read or set its properties: ```kotlin val msg = the<GreetingExtension>().message.get() the<GreetingExtension>().message.set("updated") ``` It throws `UnknownDomainObjectException` if no extension of that type is registered. ## configure<>{} — typed block access `configure<MyExtension> { ... }` looks the extension up by type and runs the block against it (receiver = the extension). It's the programmatic equivalent of the named DSL block: ```kotlin configure<GreetingExtension> { message.set("hi") } ``` This is the idiom you reach for inside a plugin reacting to another plugin: `pluginManager.withPlugin("...") { configure<TheirExtension> { ... } }`. ## Name-based vs type-based | Accessor | Lookup | Type-safe? | Returns null if missing? | |---|---|---|---| | `the<T>()` / `extensions.getByType(T)` | by type | yes | no (throws) | | `configure<T> {}` / `extensions.configure(T) {}` | by type | yes | no (throws) | | `extensions.getByName("x")` | by name | no (Any) | no (throws) | | `extensions.findByType(T)` / `findByName("x")` | by type/name | type: yes | yes (returns null) | Prefer type-based lookups: they survive renames of the registered string and give IDE help. Use `findByType` when the extension's presence is conditional. ## Groovy equivalent In the Groovy DSL the dynamic name usually suffices (`greeting { ... }`), but the same `project.extensions.getByType(...)`/`configure(...)` calls exist for programmatic access.

  • What happens if you call the<MyExtension>() but no such extension is registered?
    It throws UnknownDomainObjectException. Use findByType<MyExtension>() (returns null) when the extension may be absent.
  • Why prefer configure<T>{} over getByName("name"){}?
    Type-based access is compile-checked and refactor-safe; getByName returns Any (untyped) and breaks silently if the registered name changes.

saying these in an interview costs you the question

  • Claiming the<>() and configure<>{} look up by name — they look up by type.
  • Assuming type-based accessors return null when missing (they throw; find* returns null).
  • Saying getByName is type-safe.

context