skip to content

What does Provider.orElse do, and how does it differ from convention() and from getOrElse()?

level: middleimportance: should knowfreq 40%

answer

  1. orElse = lazy fallback provider
  2. getOrElse = eager terminal read
  3. convention = Property default, overridden by set()
  4. convention makes property present
  5. orElse overload takes value or provider

basics

~20 s

orElse returns a new provider that uses a fallback value or provider when the source is absent, staying lazy. convention sets a default on a Property that an explicit set() overrides. getOrElse eagerly returns a plain value or a default now.

solid answer

~40 s

`Provider<T>.orElse(value)` and `orElse(provider)` produce a **new lazy provider** that yields the source's value if present, otherwise the fallback. It composes in a chain and never forces evaluation. `getOrElse(default)` is the **eager** sibling: it immediately resolves the provider, returning the value or the default — use it only at the last moment (in a task action). `convention(...)` is different in kind: it sets a **default on a `Property`** that is used unless someone explicitly `set()`s the property; once set, the convention is ignored even if you later "unset" via a new value. The key distinctions: `orElse` builds a derived provider and reacts to *absence at query time*; `convention` is a property-level default overridden by *any* explicit assignment; `getOrElse` is a terminal, eager read. Prefer `orElse`/`convention` to keep chains lazy; reserve `getOrElse` for execution-time reads.

code

kotlin · 5 lines
kotlin
val fromGradleProp = providers.gradleProperty("region")
val region: Provider<String> = fromGradleProp
    .orElse(providers.environmentVariable("REGION"))
    .orElse("us-east-1") // final literal fallback, still lazy
// region.get() only resolves now, walking the chain top-down

go deeper

for a junior

Know orElse supplies a fallback when a provider is absent.

for a middle

Distinguish orElse (lazy) from getOrElse (eager) and from convention (property default overridden by set).

for a senior

Explain the convention-makes-present gotcha and how to design clean fallback chains.

for a principal

Define defaulting conventions across plugins so users get predictable override semantics.

## Three ways to supply a default ### orElse — lazy fallback in a chain ``` Provider<T>.orElse(fallback: T): Provider<T> Provider<T>.orElse(fallback: Provider<T>): Provider<T> ``` Returns a provider that, when queried, yields the source value if present, else the fallback (or the fallback provider's value). It stays lazy and is itself a `Provider`, so you keep chaining `map`/`flatMap`/`zip` after it. The provider-taking overload lets the fallback also be deferred (e.g. fall back to an env var provider). ### convention — a Property default `convention(value | provider)` applies **only to `Property`/collection properties**. It is the value the property reports *until an explicit `set()`/assignment happens*. After any explicit set, the convention no longer applies. It models "sensible default that the user can override." ### getOrElse — eager terminal read `getOrElse(default): T` is not lazy — it resolves the provider right now and returns a plain `T`, substituting `default` if absent. Calling it during configuration forces evaluation and should be avoided; it's appropriate inside a `doLast`/task action where you genuinely need the concrete value. ## How they interact ```kotlin val port = objects.property(Int::class.java).convention(8080) // default 8080 val effective: Provider<Int> = port.orElse(providers.environmentVariable("PORT").map { it.toInt() }) // because convention makes port always present (8080), orElse fallback never triggers here — // a subtle gotcha: a property with a convention is NOT absent, so orElse won't kick in. ``` That last point is a frequent interview trap: **a `Property` carrying a convention is present**, so `orElse` on it never reaches the fallback unless the convention is removed or the source is a plain absent provider. Choose `convention` for property defaults and `orElse` for composing fallback chains over genuinely-absent providers.

  • Why might orElse on a Property never use its fallback?
    If the property has a convention, it is always present, so orElse never sees absence. Conventions make a property non-absent.
  • When is getOrElse the right choice over orElse?
    Inside a task action where you need a concrete value immediately and want a default if absent — getOrElse is the eager terminal read.
  • Can the orElse fallback itself be lazy?
    Yes — the orElse(Provider<T>) overload takes a provider, so the fallback is also evaluated lazily and can carry its own dependencies.

saying these in an interview costs you the question

  • Saying orElse and getOrElse are the same — one is lazy, one is eager.
  • Claiming convention is overridden by orElse rather than by an explicit set().
  • Forgetting that a convention makes a property present, so orElse won't fire.

context