skip to content

What is a 'plugin marker' artifact, and why does the Plugin Portal publish one alongside your implementation JAR?

level: seniorimportance: should knowfreq 35%

answer

  1. id -> Maven coordinates bridge
  2. <id>:<id>.gradle.plugin:<version>
  3. POM with single dependency on impl JAR
  4. java-gradle-plugin generates markers
  5. needed for plugins{} resolution

basics

~10 s

A marker is a tiny artifact at <pluginId>:<pluginId>.gradle.plugin whose POM just depends on your real implementation JAR. It lets the plugins { id … } block map a plugin ID to Maven coordinates.

solid answer

~40 s

The `plugins { id("x") version "1.0" }` DSL references plugins by **ID**, but artifact repositories resolve by **Maven coordinates** (`group:artifact:version`). The **plugin marker** bridges that gap: for each plugin ID, Gradle publishes a separate artifact at coordinates **`<id>:<id>.gradle.plugin:<version>`** whose POM contains a single `dependencies` entry pointing at your actual implementation artifact (your `group:artifact`). When a consumer requests a plugin by ID from a `pluginManagement` repository, Gradle looks up `<id>:<id>.gradle.plugin`, reads its POM, and transitively pulls the real plugin code. The `com.gradle.plugin-publish` plugin (and `java-gradle-plugin` for custom repos) generates these markers automatically — you don't hand-write them. This is why publishing to a custom Maven repo for plugin-ID resolution also requires markers, not just the JAR.

code

groovy · 12 lines
groovy
// Consumer side — resolves via the marker artifact automatically
pluginManagement {
    repositories {
        gradlePluginPortal()      // default; serves markers + impl JARs
        maven { url = uri('https://my.repo/releases') }
    }
}

// settings or build:
plugins {
    id 'com.example.greeting' version '1.0.0'
}

go deeper

for a junior

Awareness only: there's a small extra artifact that makes plugin-ID resolution work.

for a middle

Know the <id>:<id>.gradle.plugin naming and that it points to the real JAR.

for a senior

Explain the full ID→coordinates resolution flow and which plugin generates markers for Portal vs custom repos.

for a principal

Reason about marker implications when designing an internal plugin repository and migration off the Portal.

## The ID-vs-coordinates problem Gradle's `plugins {}` block is intentionally decoupled from Maven coordinates — you write `id("com.example.greeting")`, not `com.example:greeting`. But a Maven/Ivy repository can only be queried by **coordinates**. Something has to translate an ID into coordinates. ## The marker as a redirect That translation is the **plugin marker artifact**. By convention, plugin ID `com.example.greeting` maps to the marker coordinates: ``` com.example.greeting:com.example.greeting.gradle.plugin:<version> ``` The marker has **no code** — its POM declares exactly one dependency on the real implementation artifact: ```xml <dependencies> <dependency> <groupId>com.example</groupId> <artifactId>greeting</artifactId> <version>1.0.0</version> </dependency> </dependencies> ``` ## Resolution flow 1. Consumer writes `plugins { id("com.example.greeting") version "1.0.0" }`. 2. Gradle derives the marker coordinates `com.example.greeting:com.example.greeting.gradle.plugin:1.0.0`. 3. It resolves the marker POM from a configured `pluginManagement` repository (the Portal is included by default). 4. The marker's single dependency drags in the real `com.example:greeting:1.0.0` JAR, which is added to the build's classpath. ## Who generates markers - **`com.gradle.plugin-publish`** generates and uploads markers when publishing to the **Portal**. - **`java-gradle-plugin`** generates the `…PluginMarkerMaven` publications when you use `maven-publish` to push plugins to your **own** Maven repository. ## Practical implications - If you publish a plugin JAR to a custom repo but **forget the marker**, consumers using `plugins { id … }` can't resolve it (they'd have to fall back to `buildscript { dependencies … }`). - Plugin `group`/`version` for the marker default to the project's `group`/`version`, so keep those consistent.

  • If you publish a plugin to a private Maven repo without markers, can consumers still use the `plugins {}` block?
    No. Without the marker artifact, `plugins { id … }` resolution fails; they'd have to fall back to the legacy `buildscript { dependencies { classpath … } }` plus `apply plugin:`.
  • What plugin generates the marker publication for a custom Maven repository?
    `java-gradle-plugin` — it creates `<name>PluginMarkerMaven` publications that `maven-publish` then uploads.

saying these in an interview costs you the question

  • Saying the marker contains the plugin code — it only contains a POM with one dependency.
  • Believing you must hand-author marker artifacts.
  • Claiming `plugins {}` resolves by Maven coordinates directly.

context