skip to content

What artifacts must a Maven Central release bundle contain beyond the main JAR, and why does Central reject a publication that is missing them?

level: juniorimportance: must knowfreq 62%

answer

  1. main + sources + javadoc + POM
  2. .asc signature per file
  3. withSourcesJar / withJavadocJar
  4. POM needs license/scm/developers
  5. validation is server-side

basics

~10 s

Each release must include the main JAR plus a sources JAR, a javadoc JAR, a POM, and PGP/GPG signatures (.asc) for every file. Central validation rejects bundles missing any of these.

solid answer

~40 s

Maven Central enforces a minimum bundle for every released coordinate: the primary artifact (usually the JAR), a `-sources.jar`, a `-javadoc.jar`, a complete POM (with name, description, URL, license, developers, SCM), and a detached PGP signature (`.asc`) for **each** of those files plus the POM. The sources/javadoc requirement exists so consumers can read code and docs in their IDE; signatures let anyone verify provenance against the publisher's public key. In Gradle you produce the extra JARs with `java { withSourcesJar(); withJavadocJar() }` and sign everything with the `signing` plugin applied to the `maven-publish` publication. Central's validation (Portal or legacy OSSRH) runs these checks server-side and fails the staging deployment if anything is absent or a signature does not verify.

code

kotlin · 8 lines
kotlin
java {
    withSourcesJar()
    withJavadocJar()
}

signing {
    sign(publishing.publications["maven"])
}

go deeper

for a junior

List the four artifact kinds plus signatures and note Central rejects incomplete bundles.

for a middle

Show the exact Gradle wiring (withSourcesJar/withJavadocJar + signing) and name the POM fields validated.

for a senior

Explain why immutability drives the contract and how Kotlin projects satisfy javadoc via Dokka.

for a principal

Frame it as a supply-chain/provenance guarantee and discuss enforcing the bundle contract across many modules via convention plugins.

## Why Maven Central has a bundle contract Maven Central is the default public repository for the JVM ecosystem. Because anything published there is **immutable and globally consumable forever**, Sonatype enforces a strict quality and provenance contract before a coordinate (`group:artifact:version`) goes live. A 'bundle' is the complete set of files uploaded for one version. ## The required files For a typical Java/Kotlin library version Central requires: - **Main artifact** — the `.jar` (or `.aar`, `.war`, etc.). - **Sources JAR** — `artifact-version-sources.jar`, so consumers can step into your code. - **Javadoc JAR** — `artifact-version-javadoc.jar`. (For Kotlin you can publish a stub/Dokka-generated jar; an empty javadoc jar with a placeholder is also commonly accepted, but a real one is better.) - **POM** — must carry `name`, `description`, `url`, at least one `license`, `developers`, and `scm` blocks. Central validates these fields. - **PGP signatures** — a detached ASCII-armored `.asc` for **every** file above, including the POM and the checksums. The public key must be discoverable on a public keyserver. ## Producing them in Gradle With `maven-publish`, `signing`, and the `java` plugin: ```kotlin plugins { `java-library` `maven-publish` signing } java { withSourcesJar() withJavadocJar() } publishing { publications { create<MavenPublication>("maven") { from(components["java"]) pom { name.set("my-lib") description.set("A useful library") url.set("https://github.com/me/my-lib") licenses { license { name.set("Apache-2.0") } } developers { developer { id.set("me"); name.set("Me") } } scm { url.set("https://github.com/me/my-lib") } } } } } signing { sign(publishing.publications["maven"]) } ``` `withSourcesJar()`/`withJavadocJar()` register `sourcesJar`/`javadocJar` tasks and wire them into the `java` component, so `from(components["java"])` automatically attaches them to the publication. `sign(...)` produces the `.asc` files at publish time. ## What validation checks When the bundle reaches Central (via the Central Portal upload or the legacy OSSRH staging repository), server-side validation verifies: presence of sources + javadoc, POM completeness, a valid signature on each file, and that the signing public key resolves on a keyserver. Any failure leaves the deployment in a failed/dropped state and it never goes public.

  • Kotlin libraries have no real Javadoc — how do people satisfy the javadoc-JAR requirement?
    Generate one with the Dokka plugin's javadoc-format task and attach it as the javadoc jar, or attach a minimal placeholder javadoc jar. Central requires the artifact to exist; it doesn't deeply inspect its contents.
  • Which POM fields does Central specifically validate?
    name, description, url, at least one license, developers, and scm. Missing any of these fails validation.

saying these in an interview costs you the question

  • Saying only the main JAR is needed for Central.
  • Claiming signatures are optional for public releases.
  • Confusing the javadoc/sources requirement with snapshot publishing (snapshots are more lenient — but that's a sibling topic).

context