skip to content

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%

answer

  1. apply java-gradle-plugin
  2. gradlePlugin { plugins { create … } }
  3. id + implementationClass
  4. generates META-INF/gradle-plugins/<id>.properties
  5. Plugin<Project>.apply called on apply

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.

solid answer

~40 s

You apply the `java-gradle-plugin` plugin to your build-logic project. It exposes the `gradlePlugin` extension where you register named plugin entries: ```kotlin gradlePlugin { plugins { create("greeting") { id = "com.acme.greeting" implementationClass = "com.acme.GreetingPlugin" } } } ``` `id` is the public identifier consumers use in `plugins { id("com.acme.greeting") }`. `implementationClass` is the fully-qualified name of the class implementing `Plugin<Project>` (or `Plugin<Settings>`). When a build applies the id, Gradle reads the descriptor, finds this class and calls its `apply` method. The `java-gradle-plugin` plugin also auto-generates the plugin descriptor file and a plugin marker artifact so the id can be resolved from a repository.

code

kotlin · 12 lines
kotlin
plugins {
  `java-gradle-plugin`
}

gradlePlugin {
  plugins {
    create("greeting") {
      id = "com.acme.greeting"
      implementationClass = "com.acme.GreetingPlugin"
    }
  }
}

go deeper

for a junior

Recall that you apply java-gradle-plugin and set id + implementationClass in gradlePlugin { plugins { … } }.

for a middle

Explain the generated descriptor file and that the entry name differs from the id; show the Kotlin DSL.

for a senior

Discuss why id and class are decoupled, reverse-DNS naming, and what the descriptor contract means at apply time.

for a principal

Frame id conventions as an org-wide contract (namespacing, stability across renames) and how that affects internal plugin catalogs.

## What a plugin id is A Gradle plugin needs a stable, public **id** so build scripts can apply it with `plugins { id("...") }`. The id is decoupled from the implementation class name on purpose: the class can move or be renamed without breaking consumers, and one published module can expose several ids. ## The `java-gradle-plugin` plugin Applying `java-gradle-plugin` to a JVM project does three things: 1. Adds the `gradleApi()` dependency to `implementation` so you can compile against Gradle types. 2. Adds the `gradlePlugin` extension (a `GradlePluginDevelopmentExtension`) for declaring plugins. 3. Wires tasks that generate the **plugin descriptor** and **plugin marker** artifacts. ## Declaring a plugin ```kotlin gradlePlugin { plugins { create("greeting") { // the NamedDomainObjectContainer entry name (arbitrary) id = "com.acme.greeting" // public id consumers apply implementationClass = "com.acme.GreetingPlugin" } } } ``` - The container entry name (`"greeting"`) is internal bookkeeping; it is **not** the id. - `id` must be a valid plugin id: lowercase, dot-separated namespaces, typically reverse-DNS to avoid collisions. - `implementationClass` is the fully-qualified class name implementing `Plugin<Project>`. ## The descriptor file From each entry, the `java-gradle-plugin` generates `META-INF/gradle-plugins/<id>.properties` on the classpath containing one line: ``` implementation-class=com.acme.GreetingPlugin ``` This is the actual runtime contract: when a build applies `com.acme.greeting`, Gradle looks up `com/acme/greeting` → wait, it looks up `META-INF/gradle-plugins/com.acme.greeting.properties`, reads `implementation-class`, loads that class and instantiates it. ## Why use the DSL instead of hand-writing the descriptor Before `java-gradle-plugin` you hand-authored the `.properties` file. The DSL is preferred because it also generates **plugin marker artifacts** (needed for `plugins {}` resolution from a repository) and feeds the metadata into validation and publishing tasks.

  • What file does java-gradle-plugin generate from a plugin declaration, and what does it contain?
    A descriptor at META-INF/gradle-plugins/<id>.properties containing a single line implementation-class=<fully-qualified class>. Gradle reads it at apply time to find and instantiate the plugin class.
  • Is the name passed to create("greeting") the same as the plugin id?
    No. That name is just the container entry key for build-logic bookkeeping. The public id is the separate id property you assign inside the block.

saying these in an interview costs you the question

  • Confusing the container entry name with the public plugin id.
  • Hand-writing the META-INF descriptor when java-gradle-plugin already generates it.
  • Claiming implementationClass is the id rather than the FQN of the Plugin<Project> class.

context