skip to content

Gradle Module Metadata

The .module Gradle Module Metadata file published beside a POM, the variants and constraints it carries, and how metadataSources decides what is read. Interviewers ask because GMM is what makes Gradle's richer dependency features possible.

on this pageshow

questions

5

What is Gradle Module Metadata (the .module file), and how does it differ from a Maven POM?

level: middleimportance: must knowfreq 55%

answer

  1. .module JSON file
  2. sits next to POM/Ivy
  3. describes variants + attributes
  4. lossless / rich versions
  5. Gradle prefers it when present

basics

~20 s

Gradle 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 s

Gradle 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
json
{
  "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

for a junior

Know that .module is a JSON metadata file Gradle publishes next to the POM and that it can describe more than a POM.

for a middle

Explain variants/attributes and why GMM is preferred over the POM when both exist.

for a senior

Discuss losslessness (rich versions, constraints, capabilities) and how GMM enables variant-aware resolution end to end.

for a principal

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.

context

open as a page

How is the .module file produced and published, and how do you enable or disable Gradle Module Metadata publication?

level: juniorimportance: should knowfreq 30%

basics

~20 s

The maven-publish (or ivy-publish) plugin generates the .module file automatically and publishes it with your POM and jars. GMM publication is on by default; you can toggle it via tasks.withType<GenerateModuleMetadata>().configureEach { enabled = ... }.

open as a page

How does the `metadataSources { }` block on a repository control which metadata Gradle reads, and when would you change it?

level: middleimportance: should knowfreq 40%

basics

~10 s

Inside a repository's metadataSources { } block you list which descriptors Gradle should look for — gradleMetadata(), mavenPom(), ignoreGradleMetadataRedirection(), or artifact(). Gradle tries them in the order declared.

open as a page

What does a variant inside Gradle Module Metadata carry, and how do dependencies vs. dependencyConstraints differ within it?

level: seniorimportance: should knowfreq 35%

basics

~10 s

A variant carries attributes, capabilities, files, and two dependency lists: dependencies (modules this variant actually needs) and dependencyConstraints (version recommendations/limits applied only if that module is pulled in by someone else).

open as a page

A consumer build picks an unexpected variant or fails with 'no variants match' for a dependency. How does Gradle Module Metadata factor into diagnosing this?

level: seniorimportance: nice to knowfreq 25%

basics

~20 s

GMM exposes the published variants and their attributes. When resolution fails, you compare the consumer's requested attributes against each variant's attributes — usually with dependencyInsight or by reading the .module file — and reconcile the mismatch via attributes, capabilities, or a component metadata rule.

open as a page