skip to content

What is the difference between the classifier and the extension on a ConfigurablePublishArtifact, and what happens if two artifacts collide on both?

level: middleimportance: should knowfreq 40%

answer

  1. filename = name-version-classifier.extension
  2. classifier = tag, extension = format
  3. (classifier, extension) must be unique
  4. duplicate -> publish failure
  5. defaults read from archive task

basics

~20 s

The classifier is the suffix in the filename (e.g. -all), the extension is the file type (e.g. jar, zip). Together with coordinates they uniquely identify a file; two artifacts with the same classifier+extension clash and publishing fails.

solid answer

~40 s

An extra artifact's coordinate is `group:name:version` plus a **classifier** and **extension**. The published filename is `name-version-classifier.extension` (the `-classifier` part is omitted when blank). The classifier names the variant of the file (`sources`, `all`, `linux`), the extension names the format (`jar`, `zip`, `tar.gz`). On a `ConfigurablePublishArtifact` both are mutable, so you can override what a task implies — e.g. a `Zip` task whose archive is `.zip` could be published with `extension = "zip"` and `classifier = "docs"`. The uniqueness key within a publication is (classifier, extension): attach two artifacts both having, say, classifier `all` and extension `jar` and the publish task fails with a duplicate/ambiguous artifact error. So when adding several extra files, give each a distinct classifier (or extension).

code

kotlin · 10 lines
kotlin
publishing {
    publications {
        create<MavenPublication>("maven") {
            from(components["java"])           // main name-version.jar
            artifact(tasks.named("fatJar")) { classifier = "all" }   // name-version-all.jar
            artifact(tasks.named("docsZip")) { classifier = "docs"; extension = "zip" } // name-version-docs.zip
            // adding another artifact with classifier="all", extension="jar" here would FAIL
        }
    }
}

go deeper

for a junior

Know that classifier is the -something suffix and extension is the file type, and they default from the task.

for a middle

Explain the filename pattern, that the (classifier, extension) pair must be unique, and the typical duplicate-artifact failure.

for a senior

Discuss how these map to Maven <classifier>/<type>, conventional classifier names for interoperability, and overriding task defaults.

for a principal

Set org-wide conventions for classifiers so consumers across teams can predict coordinates, and weigh classifier-based files vs metadata-described variants.

## The coordinate model In Maven-style publishing a single set of coordinates (`group:name:version`) can carry many files. Two attributes disambiguate them: - **classifier** — a free-form tag appended to the artifact name: `sources`, `javadoc`, `all`, `linux-x86_64`. Empty/blank for the main artifact. - **extension** (Maven calls it *type/packaging* at the POM level, but the file extension at the storage level) — `jar`, `zip`, `pom`, `tar.gz`. The stored filename is: ``` <name>-<version>[-<classifier>].<extension> ``` So `mylib-1.0-all.jar` is classifier `all`, extension `jar`; `mylib-1.0.jar` is the no-classifier main artifact. ## Setting them on ConfigurablePublishArtifact `artifact(...)` hands you a `ConfigurablePublishArtifact` with mutable `classifier` and `extension`. These default from the source: an `AbstractArchiveTask` exposes `archiveClassifier` and `archiveExtension`, and Gradle reads those. You override them on the publication side when you want a different published identity than the task's own archive name: ```kotlin artifact(tasks.named("docsZip")) { classifier = "docs" extension = "zip" } ``` ## The uniqueness rule Within one publication, the pair **(classifier, extension)** must be unique. If you attach two artifacts that both resolve to the same classifier and extension, Gradle raises an error at configuration/publish time (e.g. *"Multiple artifacts with the identical extension and classifier"*). This commonly bites when: - You add `from(components.java)` (which already contributes the main `jar`) and then also `artifact(jarTask)` with no classifier — two `jar` artifacts with empty classifier collide. - Two custom tasks both default to classifier `all`. The fix is to give each extra file a distinct classifier (or, less commonly, extension). ## Why it matters to consumers Maven consumers request a classified artifact with `<classifier>` in the dependency, and a non-`jar` extension via `<type>`. So the classifier/extension you publish is exactly the handle downstream users must type. Choosing conventional classifiers (`sources`, `javadoc`, `all`, `tests`) keeps you interoperable.

  • You get 'Multiple artifacts with the identical extension and classifier' — what's the usual cause?
    Two attached artifacts resolve to the same (classifier, extension) pair — often the auto-added main jar from `from(components.java)` plus a manually attached jar with no classifier. Give the extra one a distinct classifier.
  • Do classifier and extension always match the producing task's archive name?
    They default from `archiveClassifier`/`archiveExtension`, but you can override either on the ConfigurablePublishArtifact, so the published identity can differ from the task's own file name.

saying these in an interview costs you the question

  • Saying classifier and extension are interchangeable — classifier tags the file, extension names the format.
  • Thinking two same-classifier-and-extension artifacts just overwrite each other silently — publishing fails.
  • Believing the classifier changes the artifact's group/name/version.

context