skip to content

Gradle Module Metadata

The .module metadata file describing variants, capabilities, and constraints published alongside the POM. Interviewers ask what consumers gain from it and what happens when a consumer reads only the POM.

on this pageshow

questions

5

What is the Gradle Module Metadata (the `.module` file), and what does it describe that a traditional Maven POM cannot?

level: juniorimportance: must knowfreq 55%

answer

  1. JSON `.module` sidecar next to .pom
  2. variants + attributes + dependencies + capabilities
  3. POM = flat list; GMM = variant-aware
  4. GenerateModuleMetadata task
  5. POM marker points to .module

basics

~20 s

It'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 s

Gradle 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 lines
kotlin
plugins {
    `java-library`
    `maven-publish`
}

publishing {
    publications {
        create<MavenPublication>("maven") {
            from(components["java"]) // GenerateModuleMetadata writes the .module file
        }
    }
    repositories { mavenLocal() }
}

go deeper

for a junior

Know it's a JSON .module file published next to the POM that describes variants so Gradle resolves more precisely than a POM.

for a middle

Explain the variant model (attributes, dependencies, capabilities) and that GMM is generated from the published component's outgoing configurations while remaining POM-compatible.

for a senior

Discuss variant-aware matching at resolution time, what GMM unlocks (constraints, capabilities, feature variants, alignment) and the POM-as-fallback interop strategy.

for a principal

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).

context

open as a page

Walk through the structure of a `.module` file: what does a 'variant' entry contain, and how does Gradle use it during resolution?

level: middleimportance: must knowfreq 45%

basics

~20 s

Each variant in the .module JSON has a name, a map of attributes, a list of dependencies (and constraints), capabilities, and the files it provides. Gradle matches the consumer's requested attributes against these to pick one variant.

open as a page

How are dependency constraints and rich versions (strictly/prefers/rejects) represented and used through Gradle Module Metadata?

level: middleimportance: should knowfreq 35%

basics

~10 s

GMM stores per-variant dependencyConstraints and rich version info (requires, prefers, strictly, rejects) as structured JSON. Consumers that read GMM honor them during resolution; the POM can only approximate this.

open as a page

When publishing, Gradle sometimes emits Module Metadata warnings. What causes them, and how do `suppressAllPublicationWarnings` / `suppressPomMetadataWarningsFor` work?

level: seniorimportance: should knowfreq 30%

basics

~10 s

Warnings appear when a variant can be represented in GMM but not in the POM (lossy mapping). You can silence them per-variant with suppressPomMetadataWarningsFor("name") or all of them with suppressAllPublicationWarnings() on the publication.

open as a page

How does a consumer enable or disable Gradle Module Metadata resolution, and what are the trade-offs of turning it off on either side?

level: seniorimportance: nice to knowfreq 22%

basics

~10 s

Consuming GMM is on by default. You can opt out per-repository (metadataSources only the POM) or disable producing it via the GenerateModuleMetadata task. Turning it off loses variant-aware resolution and rich-version fidelity.

open as a page