skip to content

How does a build extension contribute a custom packaging type and lifecycle mapping?

level: seniorimportance: should knowfreq 35%

answer

  1. packaging -> lifecycle mapping table
  2. ArtifactHandler + LifecycleMapping
  3. <extensions>true</extensions> to register
  4. components.xml / Sisu metadata
  5. bundle, maven-plugin, eclipse-plugin examples

basics

~10 s

An extension ships component metadata that registers a new <packaging> value and maps which plugin goals run in each lifecycle phase. You then set extensions=true on the plugin and use that packaging.

solid answer

~40 s

A packaging type (jar, war, pom, etc.) maps to a set of default goal bindings per lifecycle phase. An extension contributes a new one by providing two Sisu/Plexus components: an ArtifactHandler (file extension, type, classifier, whether it's added to the classpath) and a LifecycleMapping (phase -> goals). Plugins that bring such mappings are activated with <extensions>true</extensions> in their <plugin> declaration; once active, declaring <packaging>my-type</packaging> makes Maven run that custom lifecycle. Real examples: the maven-plugin-plugin enables packaging maven-plugin, the takari-lifecycle and tycho's eclipse-plugin/eclipse-feature packagings, or the bundle packaging from the maven-bundle-plugin (OSGi). The extension thus defines both the artifact's shape and the sequence of goals that produce it.

code

xml · 12 lines
xml
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.felix</groupId>
      <artifactId>maven-bundle-plugin</artifactId>
      <version>5.1.9</version>
      <extensions>true</extensions>
    </plugin>
  </plugins>
</build>
<!-- module: -->
<packaging>bundle</packaging>

go deeper

for a junior

Knows packaging like jar/war changes the build output.

for a middle

Knows custom packaging exists and needs a plugin with extensions=true.

for a senior

Can explain ArtifactHandler + LifecycleMapping registration and the activation mechanics and failure mode.

for a principal

Designs or evaluates custom lifecycles for org-wide build types, weighing tooling lock-in and IDE support.

## Background: packaging drives the default build Every Maven project has a `<packaging>` (default `jar`). Packaging is not just a file extension — it selects a **default lifecycle mapping**: a table of `phase -> goal(s)`. For `jar`, `package` runs `jar:jar`; for `war`, `package` runs `war:war`; for `pom`, most phases are empty. So changing packaging changes which goals run automatically. ## How an extension adds a new packaging A build extension (often shipped as a plugin marked `<extensions>true</extensions>`) registers two component types in the Maven runtime: 1. **ArtifactHandler** — defines the produced artifact's `extension` (e.g. `nbm`), its `type`, default `classifier`, language, and whether it's `addedToClasspath`. 2. **LifecycleMapping** — declares, for a given packaging, the goals bound to each phase of the default lifecycle. These are wired via component metadata (modern Maven uses Sisu/JSR-330 annotations or `components.xml`; older plugins used `META-INF/plexus/components.xml`). ## Activating it ```xml <build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>5.1.9</version> <extensions>true</extensions> <!-- registers the 'bundle' packaging + lifecycle --> </plugin> </plugins> </build> ``` Then the module declares the new packaging: ```xml <packaging>bundle</packaging> ``` Now `mvn package` runs the bundle lifecycle (manifest generation + jar) instead of the plain jar lifecycle. ## Real examples - `maven-plugin-plugin` -> packaging `maven-plugin` (binds `plugin:descriptor`). - `maven-bundle-plugin` -> packaging `bundle` (OSGi). - Eclipse Tycho -> `eclipse-plugin`, `eclipse-feature`, `eclipse-repository`. - `nbm-maven-plugin` -> NetBeans module packaging `nbm`. ## Why `<extensions>true</extensions>` is required Without it, the plugin's goals are available but its ArtifactHandler/LifecycleMapping components are **not** registered, so the new packaging value is unknown and the build fails with 'Unknown packaging'.

  • What error do you get if you set a custom packaging but forget <extensions>true</extensions>?
    Maven fails with an 'Unknown packaging' error because the LifecycleMapping/ArtifactHandler for that packaging was never registered.
  • Which two component types must the extension register?
    An ArtifactHandler (artifact shape/extension/classpath) and a LifecycleMapping (phase-to-goal bindings) for the new packaging.

saying these in an interview costs you the question

  • Claiming packaging is only a file extension with no effect on goals.
  • Saying you can use a custom packaging without setting <extensions>true</extensions>.
  • Confusing this with a profile or executions block.

context