What is the Gradle Module Metadata (the `.module` file), and what does it describe that a traditional Maven POM cannot?
answer
- JSON `.module` sidecar next to .pom
- variants + attributes + dependencies + capabilities
- POM = flat list; GMM = variant-aware
- GenerateModuleMetadata task
- POM marker points to .module
basics
~20 sIt's a JSON file (module.module) Gradle publishes alongside the POM. It describes a module's variants, their dependencies, and attributes — richer info than a flat POM can express, so Gradle can pick the right variant when resolving.
solid answer
~40 sGradle Module Metadata (GMM) is a JSON sidecar file, named `<artifact>-<version>.module`, published next to the `.pom` (and `.jar`). Where a Maven POM lists a single flat dependency set, GMM models the module as a set of **variants** — e.g. `apiElements`, `runtimeElements`, sources, javadoc — each carrying **attributes** (like `org.gradle.usage=java-api`), its own **dependencies**, **dependency constraints**, **capabilities**, and the **files** it provides. At resolution time Gradle reads GMM and uses variant-aware matching to pick exactly the variant whose attributes satisfy the consumer's request. A POM cannot express usage/api-vs-runtime separation, rich constraints, or capabilities, so GMM unlocks features like feature variants and platform alignment while staying interoperable: a Gradle consumer prefers `.module`, a Maven consumer falls back to the POM.
code
kotlin · 13 linesplugins {
`java-library`
`maven-publish`
}
publishing {
publications {
create<MavenPublication>("maven") {
from(components["java"]) // GenerateModuleMetadata writes the .module file
}
}
repositories { mavenLocal() }
}go deeper
Know it's a JSON .module file published next to the POM that describes variants so Gradle resolves more precisely than a POM.
Explain the variant model (attributes, dependencies, capabilities) and that GMM is generated from the published component's outgoing configurations while remaining POM-compatible.
Discuss variant-aware matching at resolution time, what GMM unlocks (constraints, capabilities, feature variants, alignment) and the POM-as-fallback interop strategy.
Frame GMM as the contract that lets an org standardize cross-project variant attributes and capabilities; weigh ecosystem implications of publishing it for downstream Maven-only consumers.
## What it is Gradle Module Metadata (GMM) is a **JSON metadata file** Gradle publishes for a component, named `<module>-<version>.module`. It sits in the repository right beside the classic Maven `.pom` and the binary artifacts. Its purpose is to describe a published component with far more fidelity than a Maven POM allows. ## Why a POM isn't enough A Maven POM describes a module as essentially **one flat list of dependencies** with coarse `scope` (`compile`, `runtime`, `provided`). It has no first-class notion of: - separate **API vs runtime** dependency sets, - **attributes** that describe *what kind* of artifact a variant is, - **dependency constraints** (recommend-a-version-without-requiring-it), - **capabilities** (two modules providing the same thing), - multiple alternative artifacts (sources, javadoc, platform-specific jars) chosen by context. ## The variant model GMM models a component as a set of **variants**. Each variant has: - a **name** (e.g. `apiElements`, `runtimeElements`, `javadocElements`), - **attributes** — key/value pairs like `org.gradle.usage=java-api`, `org.gradle.category=library`, `org.gradle.libraryelements=jar`, - its own **dependencies** and **dependencyConstraints**, - **capabilities**, - the **files** (artifacts) it carries. During resolution Gradle performs **variant-aware matching**: the consumer asks for a set of attributes (e.g. "I need the API of this library") and Gradle selects the single variant whose attributes are compatible, then pulls that variant's dependencies and files. This is what makes things like API/implementation separation and per-platform artifacts work across module boundaries. ## Interoperability GMM never replaces the POM — it's published *in addition* to it. A Gradle consumer detects the `.module` file (the POM carries a marker comment pointing to it) and prefers it; a Maven/older consumer just reads the POM. So you get richer resolution for Gradle users without breaking Maven users. ## Where it comes from When you apply `maven-publish` and publish a `SoftwareComponent` (typically `components["java"]`), the `GenerateModuleMetadata` task produces the `.module` file from the component's outgoing variants (the `*Elements` configurations). It is enabled by default for component-based publications. ```kotlin publishing { publications { create<MavenPublication>("maven") { from(components["java"]) // drives variants written into the .module file } } } ```
- Does publishing GMM stop Maven users from consuming your library?No. The `.module` file is published alongside the POM, not instead of it. Maven and older tools read the POM; Gradle prefers the `.module`.
- Which task generates the file?`GenerateModuleMetadata`, wired automatically when a component (e.g. `components["java"]`) is added to a publication with `maven-publish` or `ivy-publish`.
A POM is a single-page résumé; GMM is a structured profile with separate sections (API, runtime, docs, native binaries) so the reader picks exactly the section relevant to them.
saying these in an interview costs you the question
- Claiming GMM replaces or is incompatible with the Maven POM.
- Saying it's an XML file (it is JSON).