skip to content

What is an artifactView in Gradle, and why would you set lenient = true on it?

level: middleimportance: should knowfreq 45%

answer

  1. incoming.artifactView { }
  2. lenient = true → ignore failures
  3. componentFilter / attributes
  4. ArtifactCollection.failures
  5. lazy FileCollection — task input

basics

~10 s

An artifactView lazily produces a filtered/transformed set of resolved artifacts from a configuration. lenient = true makes it ignore resolution and artifact failures instead of throwing, returning whatever resolved successfully.

solid answer

~40 s

`configuration.incoming.artifactView { ... }` builds a **lazy, filtered view** over a resolved configuration's artifacts. Inside the spec you can set `componentFilter { id -> ... }` to keep only certain components, request `attributes { ... }` to trigger artifact transforms or select a different variant, and set `lenient = true`. Normally, resolving artifacts fails the build if *any* component or artifact can't be resolved. With `lenient = true`, the view swallows those failures and returns only the artifacts that *did* resolve — useful for best-effort tooling (IDE imports, optional analysis tasks) where one bad dependency shouldn't break everything. You read results via `view.artifacts` (an `ArtifactCollection`, exposing `artifactFiles`, per-artifact metadata, and `failures`) or `view.files`. Because it's lazy, you can wire `artifactFiles` into a task input without forcing resolution at configuration time.

code

kotlin · 10 lines
kotlin
val externalJars = configurations.getByName("runtimeClasspath")
    .incoming.artifactView {
        lenient = true
        componentFilter { it is ModuleComponentIdentifier }
    }.artifacts.artifactFiles

tasks.register<Copy>("copyExternal") {
    from(externalJars)
    into(layout.buildDirectory.dir("ext-libs"))
}

go deeper

for a junior

Know that artifactView produces a filtered set of files and lenient=true means 'don't fail if some can't resolve'.

for a middle

Explain componentFilter, attributes, lenient, reading via ArtifactCollection, and that the result is a lazy FileCollection.

for a senior

Discuss how attributes drive artifact transforms/variant selection and how laziness keeps configuration cache and config-time performance intact.

for a principal

Position lenient artifact views as the resilient-collection primitive for org tooling (IDE sync, SBOM) that must not be aborted by a single bad dependency.

## What an artifactView is `ResolvableDependencies.artifactView { ArtifactView.ViewConfiguration }` returns an `ArtifactView` — a **lazy projection** of the artifacts of a resolved configuration. It does not re-declare dependencies; it filters and optionally transforms the artifacts of the *already-modeled* graph. You obtain it from `configuration.incoming.artifactView { ... }` and read it via: - `view.files` — a lazy `FileCollection`. - `view.artifacts` — an `ArtifactCollection`, which additionally gives `artifactFiles` (FileCollection), the resolved `artifacts` (each with a `ComponentArtifactIdentifier` + variant), and `getFailures()`. ## The three knobs ```kotlin val view = configurations.getByName("runtimeClasspath").incoming.artifactView { lenient = true componentFilter { id -> id is ModuleComponentIdentifier && id.group == "com.acme" } attributes { attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, "jar") } } ``` 1. **`lenient`** — when `true`, resolution and artifact-download failures are collected (into `artifacts.failures`) rather than thrown. The view returns the artifacts that succeeded. When `false` (default), the first failure breaks the build on access. 2. **`componentFilter { ComponentIdentifier -> Boolean }`** — keeps only artifacts whose owning component passes the predicate. Common use: include only project (`ProjectComponentIdentifier`) vs external (`ModuleComponentIdentifier`) artifacts. 3. **`attributes { ... }`** — requests artifacts matching a given set of attributes. This is the trigger for **artifact transforms**: if no variant matches directly, Gradle finds a chain of registered transforms (e.g. unzip-jar, extract-classes) to produce the requested attribute set. It can also select a different consumable variant than the one the configuration's own attributes would pick. ## Why lenient matters In best-effort scenarios — IDE dependency sync, an optional license/SBOM scan, a 'collect what you can' diagnostic — you don't want one unpublished or broken dependency to abort the whole operation. `lenient = true` degrades gracefully: you process the resolvable subset and can still inspect `artifacts.failures` to log what was skipped. ## Laziness and wiring into tasks `view.files` / `view.artifacts.artifactFiles` are lazy `FileCollection`s. You can register them as a task input (`from(view.files)`, or a `@InputFiles` property) without forcing resolution during configuration. Resolution happens when the task actually runs — preserving configuration-time performance and configuration cache compatibility. ## artifactView vs ResolutionResult - artifactView → the **files** (filtered/transformed artifacts). - ResolutionResult → the **graph** (selected versions + reasons). They are complementary views over the same resolution.

  • How do you find out which dependencies were skipped when lenient = true?
    Read view.artifacts.getFailures() (the ArtifactCollection's failures) — each entry describes a resolution or artifact failure that was suppressed, so you can log or report it.
  • What does requesting attributes on an artifactView enable beyond filtering?
    It can trigger artifact transforms: if no variant matches the requested attributes directly, Gradle composes a chain of registered transforms to synthesize matching artifacts, or selects a different consumable variant.

saying these in an interview costs you the question

  • Saying lenient skips downloading artifacts — it still downloads; it only suppresses failures.
  • Claiming artifactView re-declares or adds dependencies — it only filters/transforms the existing graph's artifacts.

context