How do you make a Gradle Java library publish a sources jar and a javadoc jar alongside the main artifact?
answer
- java { withSourcesJar(); withJavadocJar() }
- registers sourcesJar / javadocJar Jar tasks
- attached as secondary variants on java component
- from(components["java"]) picks them up
- classifiers sources / javadoc
basics
~10 sInside the java { } block call withSourcesJar() and withJavadocJar(). Gradle registers sourcesJar and javadocJar tasks and attaches them to the java component, so they publish automatically.
solid answer
~30 sThe `java` plugin extension exposes two opt-in methods: `withSourcesJar()` and `withJavadocJar()`. Calling them in the `java { }` block does three things: registers a `sourcesJar` task (a `Jar` packaging `main` sources, classifier `sources`), registers a `javadocJar` task (packaging the output of the `javadoc` task, classifier `javadoc`), and attaches each as a *secondary variant* on the `java` SoftwareComponent. Because they are part of the component, a `maven-publish` `from(components["java"])` publication picks them up with no extra wiring, and they are also described in Gradle Module Metadata. You no longer hand-create `Jar` tasks or call `artifacts { archives ... }` for the common case.
code
kotlin · 12 linesjava {
withSourcesJar()
withJavadocJar()
}
publishing {
publications {
create<MavenPublication>("maven") {
from(components["java"])
}
}
}go deeper
Know the two method names and that they go inside the java { } block to publish sources and javadoc.
Explain that they register named Jar tasks and attach them to the java component so publishing picks them up automatically.
Discuss secondary variants and module metadata, and contrast with the legacy hand-rolled Jar + archives approach.
Frame as a publishing-policy default across many library modules (convention plugin) and the consumer-resolution implications via attributes.
## The problem Maven Central (and most repos) require a library to publish three things: the main `.jar`, a `-sources.jar`, and a `-javadoc.jar`. Historically you wrote these `Jar` tasks by hand and registered them with the `archives` configuration. Modern Gradle gives you two one-liners. ## The two methods The `java-library`/`java` plugin adds a `JavaPluginExtension` reachable via the `java { }` block. Two methods on it are relevant: - `withSourcesJar()` — registers a task named `sourcesJar` of type `Jar`. It bundles the `main` source set's sources (`.java`, resources) and uses the archive classifier `sources`. - `withJavadocJar()` — registers a task named `javadocJar` of type `Jar`. It depends on and packages the output of the built-in `javadoc` task, with classifier `javadoc`. Both are *opt-in* and idempotent: calling them more than once is safe, and not calling them means the tasks don't exist. ## Secondary variants The important part is what happens after registration. Each jar is attached to the `java` component as a **secondary variant** — a variant carrying attributes like `DocsType=sources` or `DocsType=javadoc` and category `documentation`. Because the variant lives on the component: - `from(components["java"])` in a `maven-publish` publication publishes all three jars and emits correct Gradle Module Metadata describing the variants. - A consumer can selectively resolve, say, the sources variant via attribute-based dependency resolution. ## Why prefer it over hand-rolled Jar tasks Manually creating `Jar` tasks still works, but you'd then have to attach them to the component (or the publication) yourself and they wouldn't automatically appear as proper documentation variants in module metadata. The `withXxxJar()` methods wire all of that correctly. ```kotlin plugins { `java-library`; `maven-publish` } java { withSourcesJar() withJavadocJar() } publishing { publications { create<MavenPublication>("lib") { from(components["java"]) // includes main + sources + javadoc } } } ```
- What classifiers do the generated jars use?`sources` for the sources jar and `javadoc` for the javadoc jar — matching Maven conventions for `-sources.jar` and `-javadoc.jar`.
- Do you need to add these jars to the publication manually?No. Because they are attached to the `java` component, `from(components["java"])` includes them automatically along with correct module metadata.
saying these in an interview costs you the question
- Saying you must hand-create `Jar` tasks and use `artifacts { archives }` for sources/javadoc — that's the legacy approach the methods replace.
- Claiming these are enabled by default — they are opt-in.