skip to content

Authoring Plugins, Tasks and Extensions

Writing build logic as real software: custom task types, plugins, DSL extensions, the lazy property API, worker concurrency, and structured diagnostics. Interviewers use this area to separate people who configure Gradle from people who extend it.

on this pageshow

explore

questions

186 · 6 sections

What does the @CacheableTask annotation do, and what is the difference between marking a task cacheable and the build cache simply being enabled?

level: juniorimportance: must knowfreq 62%
basics
~10 s

@CacheableTask on a task type opts that type into the build cache, so its outputs can be stored and reused. Enabling the build cache alone does nothing unless task types are marked cacheable.

open as a page

What is a CommandLineArgumentProvider in Gradle, and why would you use one instead of just adding strings to a task's args?

level: juniorimportance: must knowfreq 45%
basics
~10 s

It's a small object that supplies command-line arguments lazily via asArguments(). You register it on a task (e.g. JavaExec/Test) so the actual arguments are computed at execution time rather than hardcoded as plain strings.

open as a page

What is DefaultTask and how do you create a custom task type by subclassing it?

level: juniorimportance: must knowfreq 70%
basics
~10 s

DefaultTask is Gradle's base class for tasks. You create a custom task type by subclassing it and adding one method annotated with @TaskAction, which holds the work the task runs when executed.

open as a page

What does `dependsOn` do in Gradle, and how is a task dependency different from controlling the mere ordering of two tasks?

level: juniorimportance: must knowfreq 80%
basics
~20 s

dependsOn declares that one task requires another to run first; if you ask for task A, Gradle also runs its dependencies. A pure ordering hook only sequences tasks that are already scheduled — it never adds a task to the build.

open as a page

What is the purpose of annotating task properties with @Input, @InputFile, and @OutputFile in a custom Gradle task?

level: juniorimportance: must knowfreq 70%
basics
~10 s

They tell Gradle which properties are a task's inputs and outputs so Gradle can decide if the task is up-to-date and skip running it when nothing relevant changed.

open as a page

How do you declare a plugin id for a custom Gradle plugin using the java-gradle-plugin plugin, and what is the role of implementationClass?

level: juniorimportance: must knowfreq 70%
basics
~20 s

Apply the java-gradle-plugin plugin, then in the gradlePlugin { plugins { … } } block register a plugin entry with an id and an implementationClass — the fully-qualified name of your Plugin<Project> class that Gradle instantiates when that id is applied.

open as a page

What is a precompiled script convention plugin in Gradle, and what problem does it solve?

level: juniorimportance: must knowfreq 70%
basics
~10 s

It's a *.gradle.kts file placed in a build-logic project's source set that Gradle compiles into a plugin. You apply it by id to share common build configuration across many subprojects instead of copy-pasting it.

open as a page

What is Gradle's ProjectBuilder and what do you use it for when developing a plugin?

level: juniorimportance: must knowfreq 55%
basics
~10 s

ProjectBuilder creates a throwaway Project instance in a JVM unit test (ProjectBuilder.builder().build()), so you can apply your plugin and assert it wired up tasks, extensions or configurations — without running a real build.

open as a page

What is the Plugin<Project> interface in Gradle, and what does the apply method do?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Plugin<Project> is the interface a Gradle plugin implements. Its single apply(project) method runs when the plugin is applied and is where you configure the project: register tasks, add extensions, or apply other plugins.

open as a page

What is a Settings plugin in Gradle, and how does it differ from a Project plugin?

level: juniorimportance: must knowfreq 55%
basics
~10 s

A Settings plugin implements Plugin<Settings> and is applied in settings.gradle(.kts). It configures the build as a whole (which projects exist, repositories, plugin resolution), unlike a Project plugin that configures one project's tasks and dependencies.

open as a page

What does Property.convention(...) do on a Gradle lazy property, and how does it differ from calling set(...)?

level: juniorimportance: must knowfreq 62%
basics
~10 s

convention(...) supplies a default value used only if nobody calls set(...). set(...) is an explicit assignment that overrides any convention. So convention = fallback default, set = the actual chosen value.

open as a page

What is a Gradle DSL extension, and how do you register one from a plugin so users can configure your plugin in their build script?

level: juniorimportance: must knowfreq 70%
basics
~10 s

An extension is an object added to a project that exposes a configuration block (DSL). A plugin registers it with project.extensions.create("myExt", MyExtension::class.java), then users configure it via a myExt { ... } block.

open as a page

What is a NamedDomainObjectContainer in Gradle, and why would a plugin author expose one in their extension?

level: juniorimportance: must knowfreq 55%
basics
~10 s

It's a Gradle collection of objects each identified by a unique name. Plugins expose one so users can declare multiple named instances in a DSL block, like sourceSets or configurations.

open as a page

Your plugin defines an extension with a `Property<String>` called `greeting`. How do you connect that extension value to a task's input property so the task uses whatever the user sets in the build script?

level: juniorimportance: must knowfreq 60%
basics
~10 s

Use task.greeting.set(extension.greeting). This wires the task's Property to the extension's Property lazily, so the value is read later (at execution), not while configuring.

open as a page

Why are modern Gradle extensions written as abstract classes with abstract Property<> / ListProperty<> getters, and who provides the implementations?

level: middleimportance: must knowfreq 60%
basics
~20 s

You declare the extension abstract with abstract Property/ListProperty getters and no bodies. Because Gradle instantiates the class via ObjectFactory, it generates a subclass that implements those getters with initialized, lazy property objects — you don't write boilerplate.

open as a page

What are ListProperty, SetProperty and MapProperty in Gradle, and how do you create them on a task or extension?

level: juniorimportance: must knowfreq 60%
basics
~10 s

They are lazy, collection-valued properties: ListProperty<T>, SetProperty<T>, MapProperty<K,V>. You create them via ObjectFactory (objects.listProperty(String::class.java)) and usually expose them as abstract getters on a task or extension.

open as a page

What is a ConfigurableFileCollection in Gradle, and how do you create one in a plugin or task?

level: juniorimportance: must knowfreq 55%
basics
~10 s

A ConfigurableFileCollection is a mutable, lazily-evaluated set of files. You create one with project.objects.fileCollection() and populate it with from(...), so the actual files are resolved later, not at configuration time.

open as a page

What is ProjectLayout in Gradle, and how do you use it to point at a file or directory under the build directory?

level: juniorimportance: must knowfreq 55%
basics
~10 s

ProjectLayout (project.layout) gives lazy access to the project and build directories. You use layout.buildDirectory.file("name") or .dir("name") to point at outputs under build/ without resolving paths eagerly.

open as a page

What does Provider.map do in Gradle, and why is it preferred over reading a provider's value at configuration time?

level: juniorimportance: must knowfreq 62%
basics
~10 s

map transforms a provider's value into a new provider using a function, without computing it now. The transform runs lazily only when the value is finally queried, so it stays deferred until execution time.

open as a page

What is the ObjectFactory service in Gradle, and how do you obtain an instance of it?

level: juniorimportance: must knowfreq 55%
basics
~10 s

ObjectFactory is a Gradle service that creates instances of model objects like Property, FileCollection, and custom managed types. You get it via @Inject in a constructor or through project.objects.

open as a page

What is the Gradle Worker API, and why would a custom task use it instead of just running its work directly in the task action?

level: juniorimportance: must knowfreq 55%
basics
~20 s

The Worker API lets a task hand units of work to Gradle's worker pool so they run in parallel. You inject WorkerExecutor, define a WorkAction, and submit work to a queue. It enables parallelism and isolation that a plain task action can't get.

open as a page

How do you define and register a BuildService with parameters, and how are those parameters supplied?

level: middleimportance: must knowfreq 45%
basics
~10 s

Define a nested Params interface extending BuildServiceParameters with Property fields, then register with registerIfAbsent and set those Property values inside the configuration action.

open as a page

What is a Gradle BuildService, and what problem does it solve?

level: middleimportance: must knowfreq 55%
basics
~10 s

A BuildService is a shared, build-scoped object that holds state or resources (caches, connections) and can be safely shared across tasks, including tasks running in parallel.

open as a page

The Gradle Worker API offers three isolation modes — noIsolation, classLoaderIsolation, and processIsolation. What does each one isolate, and how do they differ?

level: middleimportance: must knowfreq 55%
basics
~10 s

noIsolation runs work in the Gradle JVM with the buildscript classpath. classLoaderIsolation runs it in the same JVM but under a separate classloader from a custom classpath. processIsolation runs it in a forked JVM.

open as a page

What does the @ServiceReference annotation do on a Gradle task, and why is it preferable to manually wiring a build service?

level: middleimportance: must knowfreq 45%
basics
~10 s

@ServiceReference marks an abstract Property<MyService> on a task so Gradle auto-injects a registered shared build service and automatically tracks it as a task dependency, so you don't call usesService() yourself.

open as a page

What is the Gradle Problems Report HTML, where is it written, and when does Gradle generate it?

level: juniorimportance: must knowfreq 45%
basics
~10 s

It is an aggregated HTML file at build/reports/problems/problems-report.html that lists all problems and deprecations Gradle and plugins reported during the build. Gradle generates it automatically when problems exist.

open as a page

What is Gradle's Problems API and why would a plugin author report a structured problem instead of just throwing an exception or logging a warning?

level: juniorimportance: must knowfreq 35%
basics
~20 s

The Problems API lets a plugin report build issues as structured data (an ID, a message, severity, location) instead of plain text. Gradle then surfaces them uniformly in the console, the HTML report, IDEs, and the Tooling API.

open as a page

When reporting a structured problem with Gradle's Problems API, what severity levels can you assign via the ProblemSpec, and what does each one mean for the build?

level: juniorimportance: must knowfreq 35%
basics
~20 s

Severity is set with spec.severity(...) using the Severity enum: WARNING, ERROR, and ADVICE. ERROR signals a real failure, WARNING a concern, and ADVICE a hint/suggestion. It classifies the problem; it does not by itself fail the build.

open as a page

How does the Problems Report group entries, and what role does ProblemId (group + id) play in how problems surface to consumers?

level: middleimportance: must knowfreq 40%
basics
~20 s

Each reported problem carries a ProblemId — a stable id plus a ProblemGroup. The report uses that grouping to cluster problems of the same kind under shared headings, so consumers see a tree instead of a flat list.

open as a page

How do you obtain the Problems service inside a plugin or task, and why can't you just instantiate it?

level: middleimportance: must knowfreq 30%
basics
~10 s

You don't create it — Gradle injects it. Add a constructor parameter of type Problems annotated with @Inject on your Plugin or Task (using an abstract class), and Gradle's service registry supplies the instance.

open as a page