Chapter 05Lesson 03~95 minutes

Maven POM Structure, Coordinates, Packaging, Build Lifecycle, Phases, and Goals: Configuration, Design Choices, and Tradeoffs

Choose deliberately among lifecycle phases and direct goals, default and explicit plugin bindings, packaging models, and local versus centrally managed POM conventions.

Design ChoicesPackagingPlugin BindingsParent POMCI

Learning objectives

  • Choose lifecycle-phase invocation or direct goal invocation based on the desired contract and side effects.
  • Decide when to rely on packaging defaults and when to make plugin versions/configuration explicit.
  • Select jar, pom, or war packaging from the artifact/ownership model rather than habit.
  • Separate a minimal leaf POM from centrally managed parent conventions and understand the upgrade blast radius.
  • Justify build choices with observable maintainability, security, reproducibility, and CI behavior.
Current baseline — checked 2026-08-23. Required labs use Maven 3.9.16 through Maven Wrapper 3.3.4, JDK 21 to run Maven, and Java 17 as the compilation release target. For Maven 3.9.16 jar packaging, core default bindings currently include Resources 3.4.0, Compiler 3.15.0, Surefire 3.5.4, JAR 3.5.0, Install 3.1.4, and Deploy 3.1.4. The lab uses a disposable project-local repository path; no remote publication, paid repository manager, or hosted CI is required.

1. Design from the build contract, not from command familiarity

A team that knows only “run mvn clean install” has not designed its build. The command may do too much, hide model assumptions, and create unnecessary local-repository side effects in CI. Start by naming the required outcome: compiled classes, tests, distributable artifact, verification, local consumption, or remote publication. Then select the smallest lifecycle boundary that guarantees that outcome.

2. Lifecycle phase versus direct plugin goal

Choice Prefer it when… Tradeoff / evidence
Lifecycle phase You want the project’s declared build contract and all prerequisite phases. More complete and portable. Evidence is the ordered set of bound goals through that phase.
Direct goal You intentionally need one plugin capability for inspection or a narrowly scoped operation. Does not imply lifecycle prerequisites. Pin the plugin version for repeatability and verify side effects.

Examples: use verify for a CI verification stage; use a pinned help:effective-pom goal for read-only model inspection. Avoid replacing package with direct jar:jar just because both can touch a JAR—only the lifecycle phase guarantees the preceding lifecycle contract.

3. Default lifecycle bindings versus explicit plugin configuration

Maven’s conventions reduce boilerplate, but the default plugin versions belong to the Maven runtime. With the wrapper pinned to Maven 3.9.16, the current core JAR mapping is stable for that runtime. A runtime upgrade can change those defaults without a POM diff.

Approach Advantages Risks / operational cost
Rely on wrapper-pinned core defaults Very small POM; excellent for learning and simple projects; runtime and bindings move together. A Maven runtime upgrade may also upgrade default plugin versions; model review must include core binding diff.
Explicit plugin versions/configuration in project Plugin behavior visible in source; upgrades can be reviewed independently. More POM surface and maintenance; duplicated configuration across many projects without central management.
Parent/pluginManagement convention Centralizes versions/default configuration while leaf POMs stay small. Inheritance becomes a major trust/upgrade boundary; parent changes can affect many builds.
<build>
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.15.0</version>
        <configuration>
          <release>17</release>
        </configuration>
      </plugin>
    </plugins>
  </pluginManagement>
</build>

pluginManagement centralizes defaults for plugin executions that are actually used; it is not the same thing as forcing every listed goal to execute. Plugin structure is covered deeply in Chapter 07.

4. Packaging is an execution-model decision

Need Packaging Why
Produce a normal Java archive jar Default JAR lifecycle mapping compiles/tests/packages Java classes/resources.
Parent or metadata/aggregation project with no normal binary artifact pom No default package artifact goal; POM itself is installable/deployable metadata.
Produce a servlet web application archive war WAR packaging selects the WAR lifecycle mapping and war:war at package.
Do not use packaging to “make the filename look right.” Packaging is part of the project model and selects default lifecycle behavior. If the deployment platform expects an executable JAR but the POM says war, resolve the architecture mismatch rather than renaming output bytes.

5. Minimal leaf POM versus centrally managed parent

A small project can start with a minimal self-contained POM. As an organization scales, duplicated compiler/test/plugin policies become expensive and drift-prone. A parent POM can centralize properties and plugin management, but that parent becomes executable governance: changing it can alter effective models in every inheriting child.

Question Minimal/self-contained POM Managed parent convention
Where is policy visible? In each project. In parent + child effective model.
Upgrade scope Per repository. Potentially organization-wide.
Developer discoverability Simple for one project. Requires effective-POM literacy.
Drift risk Higher across many repos. Lower if parent governance is disciplined.
Supply-chain/trust boundary Project plugins/repositories. Adds parent artifact/source and its release process.

Chapter 09 will cover parent POMs and inheritance at multi-module scale. Here the key rule is: if behavior is inherited, production diagnosis must inspect the effective POM, not only the child file.

6. Keep configuration domains separate

Domain Example control Do not confuse with
Maven project model pom.xml, packaging, plugin executions JDK installation or CI runner image.
Maven runtime Wrapper Maven 3.9.16 Java bytecode release target.
JDK/toolchain JDK used to run compiler/build, --release / toolchain policy Maven lifecycle phase.
Repository policy Mirrors/proxies/repository manager Lifecycle install (local) or deploy (remote).
CI platform Job image, cache restore, secrets, workspace cleanup Maven’s own lifecycle ordering.
IDE Import/run configuration Authoritative CLI/wrapper build contract.

7. Worked decision — design a pull-request build

Scenario: a pull request must compile, run unit/integration checks configured by the project, create the candidate artifact, and retain reports. It must not write project coordinates into a shared local repository or publish remotely.

Decision Choice Reason / observable result
Entry point ./mvnw verify Executes the build verification contract without later install/deploy side effects.
Maven version Wrapper-pinned 3.9.16 Same core lifecycle/default bindings on developer and CI machines.
Local repository Job-scoped or safely cached path Dependency/plugin cache is explicit; project install output is not required.
Packaging jar for this service/library Matches required artifact type and default mapping.
Plugin policy Pin important organization-sensitive versions via governed parent/pluginManagement Allows reviewable upgrades while preserving leaf simplicity.
Evidence Maven/JDK version, effective model where needed, test reports, JAR checksum, concise execution log Lets an operator explain the exact build.

8. Upgrade cost is part of the design

When the wrapper Maven runtime changes, compare its core binding reference and Super POM before assuming “only Maven changed.” When a parent POM changes, diff the effective POM of representative children. When explicit plugin versions change, review plugin release notes and run clean-room builds. Treat every layer that can alter the effective model or executed goals as a versioned production dependency.

Knowledge check

A CI job only needs the project’s verification contract. Why is install usually broader than necessary?

Does listing a plugin under pluginManagement automatically execute its goals?

Why is a parent POM a trust boundary?

A team upgrades the Maven wrapper but does not change pom.xml. What lifecycle evidence should still be reviewed?

Summary

Select Maven controls from outcomes. Lifecycle phases express end-to-end build contracts; direct goals express one plugin capability. Packaging selects lifecycle mappings. Runtime defaults reduce POM noise but move with Maven; explicit plugin versions and governed parents make policy more visible but add maintenance and inheritance blast radius. The effective POM is the common evidence layer for all of these choices.

Next lesson

Diagnose lifecycle surprises without destroying evidence

Lesson 4 deliberately introduces phase/goal, duplicate binding, packaging, inheritance, and install mistakes and repairs them with a controlled diagnostic sequence.

Official references and version notes

Version-sensitive statements in this lesson were checked against Apache Maven primary documentation on 2026-08-23. The production teaching baseline is Maven 3.9.16 through Maven Wrapper 3.3.4, running on JDK 21 and compiling the lab project with maven.compiler.release=17. Maven 4 is intentionally outside this chapter’s required path because it remains preview-stage. Default lifecycle plugin versions are properties of the Maven runtime and can change when the Maven runtime changes; re-check the matching core reference after an upgrade.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.