skip to content

How do you set the groupId, artifactId, and version on a MavenPublication, and how does that relate to project.group and project.version?

level: juniorimportance: must knowfreq 70%

answer

  1. groupId / artifactId / version
  2. defaults: project.group, project.name, project.version
  3. override per-publication
  4. multiple artifacts from one project
  5. override != mutating project.version

basics

~10 s

Inside a MavenPublication you set groupId, artifactId, and version directly. If you omit them, Gradle defaults groupId to project.group, version to project.version, and artifactId to project.name.

solid answer

~30 s

A `MavenPublication` carries three coordinate properties: `groupId`, `artifactId`, and `version`. When you don't set them, Gradle derives defaults — `groupId` from `project.group`, `version` from `project.version`, and `artifactId` from `project.name`. You can override any of them inside the publication block, which is common when one project produces several artifacts (e.g. a `-core` and a `-bom`) or when the published name should differ from the Gradle project name. Overriding here does **not** change `project.group`/`project.version`; it only affects this publication's published coordinates and the generated POM's `<groupId>/<artifactId>/<version>`. Setting `project.group`/`project.version` at the top level is the idiomatic way when all publications share one GAV.

code

kotlin · 10 lines
kotlin
publishing {
    publications {
        create<MavenPublication>("library") {
            from(components["java"])
            groupId = "com.acme"
            artifactId = "payments-core"
            version = "1.4.0"
        }
    }
}

go deeper

for a junior

Name the three coordinates and the three project defaults they fall back to.

for a middle

Explain when to override per-publication (multiple artifacts, BOMs, renamed modules) and that artifactId defaults to project.name.

for a senior

Discuss keeping GAV centralized on the project vs. per-publication, and lazy evaluation gotchas when reading project.version early.

for a principal

Frame GAV as the public API contract of a module and how org conventions (reverse-DNS groups, naming) are governed across many publishing builds.

## What "GAV" means Every artifact in a Maven-style repository is addressed by three coordinates, collectively called **GAV**: - **G**roup id — a namespace, usually reverse-DNS (`com.acme`). - **A**rtifact id — the module name (`payments-core`). - **V**ersion — the release identity (`1.4.0`, `2.0.0-SNAPSHOT`). A consumer declares `com.acme:payments-core:1.4.0`, so these three strings are the public contract of what you publish. ## Where coordinates come from in Gradle The `maven-publish` plugin contributes a `publishing { publications { ... } }` block. Inside a `MavenPublication` you can assign coordinates explicitly: - `groupId`, `artifactId`, `version` are mutable `String` properties on the publication. - If you leave them unset, Gradle fills in **defaults at publish time**: `groupId = project.group.toString()`, `version = project.version.toString()`, `artifactId = project.name`. So for the common case you set nothing on the publication and instead set `group` and `version` once on the project — every publication inherits them. ## When you override on the publication You override directly on the `MavenPublication` when a single Gradle project emits **more than one** set of coordinates, or when the published name must diverge from the project's folder name. Classic cases: - A BOM published as `acme-bom` from a project whose `project.name` is `bom`. - A renamed artifact for backward compatibility. - Multiple publications in one project, each with its own artifactId. Overriding the publication's `version` does **not** mutate `project.version`; the two are independent once you set the publication value explicitly. ## Example ```kotlin publishing { publications { create<MavenPublication>("library") { from(components["java"]) // override only what differs from project defaults: groupId = "com.acme" artifactId = "payments-core" version = "1.4.0" } } } ``` ## Pitfalls - Coordinates are resolved lazily; if you read `project.version` too early in configuration you may capture a stale value. - `artifactId` defaults to `project.name`, which is the **directory name** unless overridden in `settings.gradle(.kts)` — a frequent surprise.

  • If you set project.group and project.version but nothing on the publication, what coordinates get published?
    groupId = project.group, version = project.version, artifactId = project.name (the directory name unless overridden in settings).
  • Why might artifactId differ from what you expect even with no override?
    Because it defaults to project.name, which is the project directory name, not necessarily the human-friendly module name; it must be set in settings.gradle if you want a different one.

saying these in an interview costs you the question

  • Claiming you must always set coordinates explicitly on every publication — defaults from project.group/name/version usually suffice.
  • Thinking overriding the publication's version also changes project.version.

context