What is Gradle Module Metadata (the .module file), and how does it differ from a Maven POM?
answer
- .module JSON file
- sits next to POM/Ivy
- describes variants + attributes
- lossless / rich versions
- Gradle prefers it when present
basics
~20 sGradle Module Metadata is a JSON file (the .module file) published next to the POM/Ivy file. Unlike a POM, it can describe multiple variants of a component, each with its own dependencies, attributes, and artifacts.
solid answer
~40 sGradle Module Metadata (GMM) is a JSON descriptor — `module-version.module` — published in a repository alongside the legacy `.pom` or `.ivy.xml` file. A POM has a single flat dependency list and cannot express that a library ships, say, separate API/runtime classpaths, a `-sources` jar, or platform-specific artifacts. GMM solves this by describing a component as a set of **variants**, each carrying attributes (e.g. `org.gradle.usage=java-api`), its own dependencies/constraints, and its own files. This is what powers Gradle's variant-aware resolution. When both files exist, Gradle prefers GMM because it is richer and lossless. POM/Ivy remain the interoperability format for Maven and other tools; GMM is an additive companion, not a replacement.
code
json · 11 lines{
"formatVersion": "1.1",
"component": { "group": "com.acme", "module": "lib", "version": "1.0" },
"variants": [
{
"name": "runtimeElements",
"attributes": { "org.gradle.usage": "java-runtime" },
"files": [ { "name": "lib-1.0.jar", "url": "lib-1.0.jar" } ]
}
]
}go deeper
Know that .module is a JSON metadata file Gradle publishes next to the POM and that it can describe more than a POM.
Explain variants/attributes and why GMM is preferred over the POM when both exist.
Discuss losslessness (rich versions, constraints, capabilities) and how GMM enables variant-aware resolution end to end.
Frame GMM as the interop boundary for an org's publishing strategy: when to keep POM-only for legacy consumers vs. enable GMM for variant fidelity.
## What it is Gradle Module Metadata (GMM) is a JSON file with the `.module` extension, published in a repository next to the traditional `.pom` (Maven) or `ivy.xml` (Ivy) file for the same coordinates. Its filename follows `{module}-{version}.module`. A Maven POM was designed for a single-classpath world: one list of `<dependencies>`, each with a `scope` (compile/runtime/...). It cannot natively say "these dependencies apply to the API classpath but those only to the runtime", nor "this component also has a variant compiled for JDK 8 vs JDK 11". ## Variants GMM models a component as a collection of **variants**. Each variant has: - **attributes** — typed key/value tags such as `org.gradle.usage` (`java-api` / `java-runtime`), `org.gradle.category` (`library` / `platform`), `org.gradle.libraryelements` (`jar` / `classes`), `org.gradle.jvm.version`. These drive variant-aware resolution. - **dependencies** and **dependencyConstraints** — scoped to that variant only. - **files** — the actual artifacts (jar names, sizes, checksums). A typical Java library publishes at least an `apiElements` variant and a `runtimeElements` variant; Gradle maps them to consumer attributes when resolving a configuration. ## Why prefer it over POM GMM is **lossless and richer**: it preserves rich versions (strictly/require/prefer/reject), dependency constraints, capabilities, and variant structure that a POM flattens or drops. When both `.module` and `.pom` are present, Gradle uses the `.module` file. The POM still exists so Maven and non-Gradle consumers can resolve the same artifact. ## Where it comes from The `maven-publish` / `ivy-publish` plugins generate the `.module` file automatically for Gradle projects. It is published by default; you rarely write it by hand. ```json { "formatVersion": "1.1", "component": { "group": "com.acme", "module": "lib", "version": "1.0" }, "variants": [ { "name": "apiElements", "attributes": { "org.gradle.usage": "java-api" }, "dependencies": [ { "group": "com.google.guava", "module": "guava", "version": { "requires": "32.1.3-jre" } } ], "files": [ { "name": "lib-1.0.jar", "url": "lib-1.0.jar" } ] } ] } ```
- If both a .module and a .pom exist for a component, which one does Gradle use?Gradle uses the `.module` file because it is richer and lossless; the POM is kept for Maven/non-Gradle interoperability.
- Who generates the .module file in a normal Gradle project?The `maven-publish` (or `ivy-publish`) plugin generates and publishes it automatically; you almost never hand-author it.
saying these in an interview costs you the question
- Calling GMM a replacement for the POM — it is an additive companion published alongside it.
- Claiming a POM can express multiple variants/classpaths natively.