skip to content

How does the <packaging> element change the default goal-to-phase bindings? Contrast jar, war, pom, and maven-plugin.

level: middleimportance: should knowfreq 55%

answer

  1. packaging = lifecycle mapping
  2. jar -> jar:jar
  3. war -> war:war
  4. pom -> only install/deploy
  5. maven-plugin -> plugin:descriptor

basics

~10 s

The <packaging> value selects which plugin goals are bound by default. jar binds jar:jar at package; war binds war:war; pom binds almost nothing (only install/deploy); maven-plugin adds plugin descriptor goals.

solid answer

~40 s

`<packaging>` is more than a file extension — it maps to a named lifecycle-mapping that defines the default goal-to-phase bindings for the `default` lifecycle. For `jar`: package binds `jar:jar`, plus compiler/surefire/resources earlier. For `war`: package binds `war:war` (which assembles the web archive). For `pom`: there is essentially no compile/test/package work — only `install:install` and `deploy:deploy` are bound, which suits aggregator/parent POMs. For `maven-plugin`: it behaves like jar but additionally binds `plugin:descriptor` (generate-resources) and `plugin:addPluginArtifactMetadata` so the plugin metadata is built. Because the binding set is driven by packaging, changing packaging silently changes what `mvn package` produces, which is a common source of 'why is there no artifact?' confusion (usually a `pom` packaging where someone expected a jar).

code

xml · 6 lines
xml
<!-- Parent / aggregator POM: pom packaging means no compile/jar binding -->
<packaging>pom</packaging>
<modules>
  <module>core</module>
  <module>web</module>
</modules>

go deeper

for a junior

Know jar is the default and produces a jar; war produces a war.

for a middle

Map each packaging to its distinctive package-phase goal and know pom skips compile/test.

for a senior

Diagnose 'no artifact produced' issues from wrong packaging and choose pom for aggregators deliberately.

for a principal

Govern packaging conventions across a large reactor and understand custom lifecycle mappings via extensions/components.xml.

## Packaging selects a lifecycle mapping The `<packaging>` element (default `jar`) names a **lifecycle mapping** — a built-in table of which goals bind to which phases of the `default` lifecycle. Each packaging ships its own table. ## jar (the default) ``` process-resources -> resources:resources compile -> compiler:compile process-test-resources -> resources:testResources test-compile -> compiler:testCompile test -> surefire:test package -> jar:jar install -> install:install deploy -> deploy:deploy ``` ## war Identical to jar except `package` binds **`war:war`** instead of `jar:jar`. The war goal assembles `src/main/webapp`, classes, and dependency JARs into a `.war`. ## pom A POM-packaged module produces no compiled artifact. Only: ``` package -> site:attach-descriptor (in newer Maven) install -> install:install deploy -> deploy:deploy ``` There is **no compile, test, or jar binding**. This is correct for parent POMs and aggregator (multi-module) POMs that only declare `<modules>`. A frequent mistake: leaving `<packaging>pom</packaging>` on a module that has real `src/main/java` and wondering why no jar appears. ## maven-plugin Like jar, but adds plugin-specific goals: ``` generate-resources -> plugin:descriptor (writes META-INF/maven/plugin.xml) package -> jar:jar + plugin:addPluginArtifactMetadata ``` This ensures the Mojo descriptor that Maven needs to invoke the plugin is generated. ## Why it matters ```xml <project> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>web-app</artifactId> <version>1.0.0</version> <packaging>war</packaging> <!-- swap to jar and package binds jar:jar instead --> </project> ``` Changing one word reroutes the entire `package` step. Always confirm packaging matches the intended artifact, and use `pom` only for parents/aggregators.

  • Why does a `pom`-packaged module skip compile and test?
    Its lifecycle mapping binds no compiler or surefire goals; pom modules are meant to aggregate or be inherited, not to produce a code artifact.
  • What extra goal does `maven-plugin` packaging bind compared to `jar`?
    plugin:descriptor (and plugin:addPluginArtifactMetadata) to generate the plugin.xml Mojo descriptor.

saying these in an interview costs you the question

  • Believing packaging only sets the output file extension
  • Expecting a jar from a `pom`-packaged module
  • Thinking war packaging still binds jar:jar at package

context