skip to content

Software Components

The SoftwareComponent abstraction, the built-in java and javaPlatform components, and adhoc components that map configurations onto published variants. Asked because from(components['java']) is where most people's understanding stops.

on this pageshow

questions

5

What is a SoftwareComponent in Gradle, and how does it relate to what gets published?

level: juniorimportance: must knowfreq 55%

answer

  1. describes publishable output
  2. from(components.java)
  3. artifacts + variant dependency metadata
  4. drives POM / Ivy / GMM
  5. registered by java plugin

basics

~10 s

A SoftwareComponent describes what a project produces for publication (its artifacts and dependencies). The MavenPublication's from(components.java) reads a component to populate the artifacts and POM/metadata that get published.

solid answer

~40 s

A `SoftwareComponent` is Gradle's abstraction for the *publishable output* of a project — the artifacts plus the dependency information that should accompany them. You don't publish raw files directly; instead you point a publication at a component with `from(components["java"])`. The `java` plugin registers a `components.java` software component whose contents (the main jar, the `apiElements`/`runtimeElements` variants and their dependencies) are derived from the build. When you call `from(components.java)` inside a `MavenPublication` or `IvyPublication`, Gradle reads that component to generate the artifacts, the `pom.xml`, and — for Gradle's own format — Gradle Module Metadata. This indirection means the same component can drive Maven, Ivy, and GMM publishing consistently, with one source of truth for dependencies and variants.

code

kotlin · 12 lines
kotlin
plugins {
  `java-library`
  `maven-publish`
}

publishing {
  publications {
    create<MavenPublication>("lib") {
      from(components["java"]) // reads the java software component
    }
  }
}

go deeper

for a junior

Know that you publish a component, not raw files, via from(components.java).

for a middle

Explain that the component carries both artifacts and per-variant dependency metadata that becomes POM scopes and GMM.

for a senior

Discuss the component as single source of truth across Maven/Ivy/GMM and how variants map to scopes.

for a principal

Frame components as the contract layer enabling consistent multi-format publishing and governance of what leaves a module.

## What a SoftwareComponent is A **SoftwareComponent** is Gradle's model of *the thing a project publishes*. Rather than telling the `maven-publish` plugin "publish this exact jar and write this exact POM by hand," you describe the output once as a component and let Gradle translate it into each publication format. A component bundles two things: - **Artifacts** — the files (jars, etc.) produced. - **Variants with dependency metadata** — for each consumption context (compile vs runtime), which dependencies belong and with what scope. ## Where components come from Components live in the project's `components` container (`SoftwareComponentContainer`). Plugins register them: - The **`java` plugin** registers `components.java` — backed by the `apiElements` and `runtimeElements` outgoing (consumable) configurations and the main jar. - The **`java-platform` plugin** registers `components.javaPlatform` — for BOM/platform publishing (constraints only, no jar). ## How publishing consumes a component ```kotlin publishing { publications { create<MavenPublication>("maven") { from(components["java"]) } } } ``` `from(component)` makes the publication read the component's variants. Gradle then: 1. Attaches the component's artifacts to the publication. 2. Maps the variants' dependencies into POM scopes (`compile`, `runtime`) for `pom.xml`. 3. Emits **Gradle Module Metadata** (`*.module`) capturing the full variant model that the legacy POM/Ivy formats can't express. ## Why the indirection matters Because the component is the single source of truth, the **same** `from(components.java)` works whether you publish to Maven, Ivy, or both — and the richer variant information survives in GMM even though POM flattens it. You generally do **not** hand-author `pom.xml`; you shape the component (or its underlying configurations) and let publishing render the formats.

  • If you never call `from(components.java)`, what gets published?
    Only what you attach manually via `artifact(...)` — no dependency metadata is derived, so the POM would have no dependencies and no GMM variants are produced from a component.
  • Which plugin registers `components.java`?
    The `java` plugin (applied transitively by `java-library`/`application`).

A SoftwareComponent is like a packing manifest: you describe what's in the shipment once, and different shipping forms (Maven POM, Ivy, GMM) are printed from that one manifest.

saying these in an interview costs you the question

  • Saying a SoftwareComponent is just the jar file — it also carries variant/dependency metadata.
  • Claiming you must hand-write the POM dependencies — Gradle derives them from the component.

context

open as a page

What is AdhocComponentWithVariants and why would you use it when publishing?

level: seniorimportance: must knowfreq 45%

basics

~10 s

AdhocComponentWithVariants is a software component you can assemble yourself by mapping outgoing (consumable) configurations to published variants with addVariantsFromConfiguration, controlling exactly which configurations end up in the publication.

open as a page

What is the difference between components.java and components.javaPlatform, and when do you publish each?

level: middleimportance: should knowfreq 40%

basics

~10 s

components.java (from the java plugin) publishes a library: a jar plus its dependencies. components.javaPlatform (from the java-platform plugin) publishes a platform/BOM: only dependency constraints, no jar.

open as a page

How do a component's variants and their dependencies map into the generated Maven POM, and what is lost?

level: middleimportance: should knowfreq 38%

basics

~20 s

Each variant's dependencies are mapped to a Maven scope (compile/runtime) when generating the POM. The POM can only express a flat scope view, so variant attributes and capabilities are lost — Gradle Module Metadata preserves them.

open as a page

How would you build a custom software component in a plugin to publish a non-standard artifact set, and what are the design trade-offs?

level: seniorimportance: should knowfreq 22%

basics

~10 s

Inject SoftwareComponentFactory, call factory.adhoc("name"), add it to project.components, create consumable configurations with attributes and artifacts, then addVariantsFromConfiguration to map them. Publish via from(components["name"]).

open as a page