Chapter 07Lesson 04~145 minutes

Maven Plugins, Lifecycle Bindings, Plugin Configuration, Executions, and Plugin Management: Diagnostics, Failure Modes, Security, and Performance

Diagnose plugin failures from evidence: inactive managed plugins, wrong-phase executions, surprising inherited configuration, Maven/JDK/plugin incompatibility, and prefix resolution that points at an unexpected plugin source.

DiagnosticsWrong PhasePrefix ResolutionCompatibilitySupply Chain

Learning objectives

  • Apply a consistent evidence-first sequence to Maven plugin failures.
  • Diagnose a managed-but-inactive custom plugin without adding duplicate executions.
  • Diagnose a correct goal bound to the wrong lifecycle phase by inspecting artifact timing.
  • Trace surprising inherited plugin configuration through the effective POM and execution ids.
  • Separate plugin compatibility, prefix resolution, repository/cache state, security, and performance causes.
Current baseline — verified 2026-08-23. Required labs use Maven 3.9.16 via Maven Wrapper 3.3.4, JDK 21 to run Maven, Java 17 as the compiler release target, Compiler Plugin 3.15.0, Surefire 3.5.4, JAR Plugin 3.5.1, Resources Plugin 3.5.0, Help Plugin 3.5.2, and AntRun Plugin 3.2.0. Every lab uses a disposable project directory and -Dmaven.repo.local=<lab>/.lab-m2/repository. Normal user caches/settings are not deleted or rewritten.
Cross-platform note: POSIX examples use ./mvnw, grep, find, and sha256sum. On Windows use mvnw.cmd and PowerShell equivalents such as Select-String, Get-ChildItem, and Get-FileHash. The POM model, plugin execution identity, and lifecycle ordering are platform-independent; shell syntax is not.

1. The diagnostic sequence

Plugin incidents are easy to “fix” by moving phases, adding another plugin declaration, changing repositories, or deleting caches. Those actions can hide the original cause. Use the same disciplined sequence every time:

1. Preserve concise failure/log/artifact evidence.
2. Confirm wrapper, Maven, and JDK identity.
3. Inspect declared POM + parent/profile inputs.
4. Inspect effective POM and active plugin/execution ids.
5. Identify lifecycle/default-binding versus explicit/direct activation.
6. Inspect plugin coordinate/version/source and local repository state.
7. Read the plugin/goal compatibility and parameter documentation.
8. Apply the smallest model correction.
9. Rebuild in a controlled clean/disposable state.
10. Verify both execution evidence and artifact/report outcome.

2. Failure mode — “the plugin is configured” but its goal never runs

Symptom: the parent contains an AntRun execution, yet clean verify has no AntRun log line and no marker. Before adding a second execution, ask where the plugin is declared.

mkdir -p evidence
./mvnw org.apache.maven.plugins:maven-help-plugin:3.5.2:effective-pom   -pl app -Doutput=evidence/effective.xml

grep -n -A24 -B4 'maven-antrun-plugin' evidence/effective.xml
# Compare <pluginManagement> with active <build><plugins>.

Cause: custom plugin policy exists under pluginManagement, but the plugin has no active reference. Repair: add one plugin reference under the appropriate module's build/plugins; inherit the managed version/execution rather than copying it.

3. Intentionally broken example — correct plugin, wrong phase

Now create a different failure: change the managed write-build-marker phase from prepare-package to verify, while still expecting the marker inside the JAR.

<execution>
  <id>write-build-marker</id>
  <phase>verify</phase>
  <goals><goal>run</goal></goals>
  <configuration>
    <target>
      <echo file="${project.build.outputDirectory}/build-marker.txt">phase=verify</echo>
    </target>
  </configuration>
</execution>
REPO="$PWD/.lab-m2/repository"
mkdir -p evidence
set -o pipefail
./mvnw -Dmaven.repo.local="$REPO" clean verify | tee evidence/wrong-phase.log

grep 'maven-antrun-plugin:3.2.0:run' evidence/wrong-phase.log
ls -l app/target/classes/build-marker.txt
jar tf app/target/app-1.0.0.jar | grep 'build-marker.txt' || echo 'marker absent from JAR' 

Interpretation: the plugin did run, but it ran after package. The marker exists in target/classes only after the JAR was already assembled. This is not a cache failure or plugin-resolution failure. The repair is to restore prepare-package, then run clean verify so stale output cannot mask ordering.

4. Failure mode — inherited configuration changes a child unexpectedly

Symptom: only one child emits unexpected manifest entries, generated files, test flags, or executions after a parent update. Capture both the parent diff and child effective POM. Search by plugin coordinate and execution id.

mkdir -p evidence
./mvnw org.apache.maven.plugins:maven-help-plugin:3.5.2:effective-pom   -pl app -Doutput=evidence/effective.xml

grep -n -A40 -B8 'maven-jar-plugin' evidence/effective.xml
grep -n -A40 -B8 'write-build-marker' evidence/effective.xml

Then decide whether the inherited behavior is genuinely global. If not, move activation/configuration closer to the module, override the specific managed value/execution id deliberately, or use inherited=false on a parent plugin that must remain parent-only. Do not duplicate the plugin in the same plugins section as a workaround.

5. Failure mode — plugin/JDK/Maven compatibility mismatch

A plugin can have minimum Maven/JDK requirements independent of your application's Java release target. Preserve the plugin error and tool identities, then read the exact plugin version's system requirements/release notes. Do not “fix” the incident by randomly switching JAVA_HOME or downgrading Maven until something passes.

./mvnw --version
java -version

./mvnw org.apache.maven.plugins:maven-antrun-plugin:3.2.0:help   -Ddetail=true -Dgoal=run

For this lab AntRun 3.2.0 documents Maven 3.6.3+ and JDK 8+ requirements, so Maven 3.9.16/JDK 21 is within its supported floor. The application still targets Java 17 through Compiler Plugin; those are separate compatibility axes.

6. Failure mode — a short prefix resolves unexpectedly

Prefix resolution can consult configured plugin groups and repository metadata. An organization-specific pluginGroup can even claim the same prefix as an official plugin group, making prefix order security-relevant.

# First make the intended identity explicit:
./mvnw org.apache.maven.plugins:maven-help-plugin:3.5.2:describe   -Dplugin=org.apache.maven.plugins:maven-clean-plugin:3.5.0   -Dgoal=clean -Ddetail=true

# Inspect effective settings without placing credentials in output/logs:
./mvnw org.apache.maven.plugins:maven-help-plugin:3.5.2:effective-settings   -Doutput=evidence/effective-settings.xml

# Review pluginGroups, mirrors, and pluginRepositories in the sanitized file.

Repair: correct the settings/repository policy in a disposable or centrally managed configuration, or use an explicit fully qualified coordinate where that is the intended automation contract. Do not add an arbitrary public plugin repository or disable verification just to make a prefix resolve.

7. Plugin cache/repository suspicion — isolate instead of erasing normal state

Plugin artifacts and metadata live in the Maven local repository too. If one isolated repository behaves differently from another, that is evidence worth preserving. Create a second lab-local repository rather than recursively deleting normal user state.

REPO_A="$PWD/.lab-m2/repository"
REPO_B="$PWD/.lab-m2-fresh/repository"
mkdir -p evidence
set -o pipefail

./mvnw -Dmaven.repo.local="$REPO_A" -pl app clean verify   | tee evidence/repo-a.log
./mvnw -Dmaven.repo.local="$REPO_B" -pl app clean verify   | tee evidence/repo-b.log

# Compare plugin coordinates/versions and repository-resolution evidence.

8. Security-sensitive changes

Changing plugin repositories, mirrors, wrapper URLs/checksums, settings credentials, extensions, signing keys, or CI secrets changes a trust boundary. Use fake/local targets in labs. A plugin executes inside the build process and may inherit CI permissions; unknown build definitions should not be run with deployment credentials or broad host access.

Never bypass a checksum/signature/verification failure simply to make plugin resolution succeed. Determine whether the plugin/version/repository was intentionally changed, the metadata/artifact is corrupted, or the source is untrusted.

9. Performance — separate plugin resolution from plugin execution

The first build with an empty isolated repository pays plugin/dependency resolution cost. A warm build may resolve locally but still spend time executing compiler/tests/generation. Measure those separately. If a custom plugin adds minutes, profile its actual goal work and inputs rather than blaming Maven startup or disabling validation globally. Parent-wide activation can also impose cost on modules that never needed the plugin—another reason to scope executions deliberately.

10. Failure-to-evidence mapping

Symptom First evidence Likely control
No custom goal log line Effective POM: pluginManagement vs active plugins Activate one managed plugin reference.
Goal runs but output misses JAR Goal execution phase + JAR contents Move execution before packaging; clean rebuild.
Child changed after parent update Parent diff + child effective POM/execution ids Narrow inheritance/override intentionally.
Plugin refuses to start Wrapper/Maven/JDK + exact plugin requirements Choose compatible reviewed versions; do not guess.
Short prefix maps unexpectedly Effective settings/pluginGroups + explicit coordinate test Correct prefix/repository policy; prefer explicit identity in diagnosis.
Only one cache works Compare two isolated local repositories Investigate metadata/artifact origin/corruption without deleting normal state.

Knowledge check

The log shows AntRun ran during verify, but the marker is missing from the JAR. Is the plugin inactive?

A child unexpectedly inherits a plugin execution. What is the first model artifact to inspect?

Why can a plugin prefix be security-relevant?

When cache corruption is suspected, why use a second isolated repository?

A plugin requires a newer JDK than the application target. Are those contradictory?

Summary

Plugin diagnostics become straightforward when you separate model, activation, execution ordering, artifact state, compatibility, and repository source. Prove whether the plugin is active; prove when the goal ran; inspect inherited configuration; confirm exact versions and system requirements; then change the narrowest control. Cache deletion and repository sprawl are not diagnostic strategies.

Next lesson

Turn plugin behavior into an auditable checkpoint

Lesson 5 inventories the active plugin policy, deliberately breaks phase ordering, repairs it, and records evidence suitable for a CI/build-engineering handoff.

Official references and version notes

Version-sensitive statements in this lesson were checked against Apache Maven primary documentation on 2026-08-23. The required path uses Maven 3.9.16 through Maven Wrapper 3.3.4, JDK 21 to run Maven, Java 17 as the project release target, Maven Compiler Plugin 3.15.0, Surefire 3.5.4, Maven JAR Plugin 3.5.1, Maven Resources Plugin 3.5.0, Maven Help Plugin 3.5.2, and Maven AntRun Plugin 3.2.0. Maven 4 preview-only behavior is not required in this chapter.

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.