What metadata must a POM contain to pass Maven Central validation, and how do you express each field in a Gradle MavenPublication?
answer
- name + description + url
- at least one license (name + url)
- at least one developer
- scm connection/developerConnection/url
- signing + sources/javadoc jars (non-POM)
basics
~10 sCentral needs name, description, url, at least one license (name + url), at least one developer, and scm connection/developerConnection/url. You set each via the pom { } block on the MavenPublication.
solid answer
~40 sMaven Central (Sonatype/Central Portal) validates each `pom.xml`. The required descriptive metadata beyond GAV is: a project **name** and **description**, a project **url**, at least one **license** with a `name` and `url`, at least one **developer** (typically `name`/`email` or `id`), and an **scm** section with `connection`, `developerConnection`, and `url`. In Gradle you express these inside `pom { }` on a `MavenPublication` using nested closures — `licenses { license { } }`, `developers { developer { } }`, `scm { }`. There are also non-POM requirements (signed artifacts, sources & javadoc jars) but those live outside the POM. The fields are `Property`/`MapProperty`-backed, so use `.set(...)` (Kotlin) or `=` (Groovy). Missing any required field causes the deployment to be rejected during validation, not at build time.
code
kotlin · 14 linespom {
licenses { license {
name.set("The Apache License, Version 2.0")
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
}}
developers { developer {
id.set("jdoe"); name.set("Jane Doe"); email.set("[email protected]")
}}
scm {
connection.set("scm:git:git://github.com/acme/toolkit.git")
developerConnection.set("scm:git:ssh://github.com/acme/toolkit.git")
url.set("https://github.com/acme/toolkit")
}
}go deeper
List the required descriptive fields.
Map each field to its DSL and note the non-POM requirements (signing, sources/javadoc).
Show how to verify the generated POM early and reason about deferred validation.
Define a shared convention plugin so every module ships a Central-compliant POM by default.
## The Central metadata checklist When you deploy to Maven Central, Sonatype runs validation on each component's POM. The **POM-level** requirements are: | Requirement | POM element | Gradle DSL | |---|---|---| | Coordinates | groupId/artifactId/version | `project.group`, publication name, `project.version` | | Project name | `<name>` | `pom.name` | | Description | `<description>` | `pom.description` | | Project URL | `<url>` | `pom.url` | | License | `<licenses><license>` | `pom.licenses { license { name; url } }` | | Developer | `<developers><developer>` | `pom.developers { developer { id; name; email } }` | | SCM | `<scm>` | `pom.scm { connection; developerConnection; url }` | ## Full example ```kotlin publishing { publications { create<MavenPublication>("maven") { from(components["java"]) pom { name.set("Acme Toolkit") description.set("Utilities for Acme services") url.set("https://github.com/acme/toolkit") licenses { license { name.set("The Apache License, Version 2.0") url.set("https://www.apache.org/licenses/LICENSE-2.0.txt") } } developers { developer { id.set("jdoe") name.set("Jane Doe") email.set("[email protected]") } } scm { connection.set("scm:git:git://github.com/acme/toolkit.git") developerConnection.set("scm:git:ssh://github.com/acme/toolkit.git") url.set("https://github.com/acme/toolkit") } } } } } ``` ## Things that are NOT POM fields but still required by Central - **GPG/PGP-signed artifacts** — apply the `signing` plugin and call `signing { sign(publishing.publications["maven"]) }`. - **`-sources.jar` and `-javadoc.jar`** — for a Java library, `java { withSourcesJar(); withJavadocJar() }` adds them to the component. These complement the POM but are validated separately. Keeping them in mind avoids the common surprise where the POM is complete yet the deployment still fails. ## Why validation is deferred The POM is generated and validated at **publish/deploy** time, not at `build`. A green `./gradlew build` tells you nothing about Central readiness — run `./gradlew generatePomFileForMavenPublication` and inspect `build/publications/maven/pom-default.xml`, or publish to a staging repo, to verify completeness early.
- Central rejected your deploy even though the POM has name/description/url/license/developer/scm. What else could be missing?Likely non-POM requirements: GPG-signed artifacts (signing plugin) and the -sources.jar / -javadoc.jar. They're validated separately from the POM.
- How can you inspect the generated POM before publishing?Run generatePomFileForMavenPublication and read build/publications/<name>/pom-default.xml.
- Can a license appear more than once?Yes — licenses { } can contain multiple license { } blocks for dual/multi-licensed projects.
saying these in an interview costs you the question
- Saying signing or sources/javadoc jars live in the pom { } block — they don't.
- Assuming a successful build means Central readiness.