skip to content

A teammate's build pulls a dependency version nobody declared, and a plugin runs with unexpected config. How do you diagnose this using the effective POM and related tools?

level: seniorimportance: should knowfreq 35%

answer

  1. effective-pom = merged model
  2. dependency:tree -Dverbose = mediation
  3. nearest-wins for transitives
  4. help:active-profiles + effective-settings
  5. management to force version

basics

~20 s

Generate the effective POM with mvn help:effective-pom to see the fully merged, resolved model and find where the version/config came from. For transitive dependency versions, also use mvn dependency:tree. Check active profiles and settings too.

solid answer

~40 s

Start with `mvn help:effective-pom -Doutput=eff.xml` to get the complete merged model — it reveals inherited dependencyManagement versions, plugin configurations from parents/profiles, and resolved properties, so you can trace 'who set this'. For a version that's transitive rather than declared, run `mvn dependency:tree -Dincludes=group:artifact` to see the path and `dependency:tree -Dverbose` for omitted/conflicting nodes and mediation (nearest-wins). If the surprise depends on environment, run `mvn help:active-profiles` and `mvn help:effective-settings` to confirm which profiles/settings are in play (settings.xml mirrors or BOM imports often explain it). Combining the effective POM (declared/managed model) with the dependency tree (resolved graph) pinpoints whether the source is a parent BOM, an active profile, plugin management, or transitive mediation.

code

bash · 4 lines
bash
mvn help:effective-pom -Doutput=eff.xml
mvn dependency:tree -Dverbose -Dincludes=com.fasterxml.jackson.core:jackson-databind
mvn help:active-profiles
mvn help:effective-settings

go deeper

for a junior

Knows help:effective-pom and dependency:tree exist and roughly what each shows.

for a middle

Picks the right tool: effective-pom for declared/managed, dependency:tree for transitive mediation.

for a senior

Systematically isolates source (parent/BOM/profile/settings/transitive) and applies management/exclusions to fix.

for a principal

Establishes team conventions (BOMs, pinned management, settings hygiene) so these surprises are rare and reproducible.

## The two complementary views Debugging 'where did this come from' needs two lenses: 1. **The effective POM** — the merged *declared* model: what your POM, parents, management sections, and active profiles say. Plugin versions/config and managed dependency versions live here. 2. **The dependency tree** — the *resolved* graph after transitive resolution and mediation. Transitive versions that no POM declares directly show up here. ## Step-by-step diagnosis ### 1. Dump the effective POM ```bash mvn help:effective-pom -Doutput=eff.xml ``` Search it for the plugin or dependency. If the version/config is present here, it came from inheritance (parent/BOM), `<dependencyManagement>`/`<pluginManagement>`, or an active profile. The effective POM flattens all of that into one place. ### 2. Trace transitive dependency versions If the dependency isn't declared anywhere but still appears, it's transitive: ```bash mvn dependency:tree -Dincludes=com.fasterxml.jackson.core:jackson-databind mvn dependency:tree -Dverbose ``` `-Dverbose` shows nodes that were omitted due to **mediation** (Maven's nearest-wins rule: the version closest to the root of the tree is chosen) or conflicts. This tells you which path introduced the version. ### 3. Account for environment ```bash mvn help:active-profiles mvn help:effective-settings ``` Profiles inject config last, and `settings.xml` can add repositories/mirrors or activate profiles per machine. A version difference between two developers' machines is often a profile or settings difference. ### 4. Pin the cause - In effective POM, declared/managed -> a parent or BOM `import` or a profile. - In tree only -> transitive; fix with an explicit declaration or `<dependencyManagement>` entry to force the version (management wins for direct conflicts), or an `<exclusion>`. ## Why management is the fix for transitive surprises Adding the dependency to `<dependencyManagement>` with the desired version forces that version everywhere it appears (directly or transitively for the same coordinates), which is the idiomatic way to override a transitive version cleanly. ## Summary Effective POM answers 'what model did I build', dependency:tree answers 'what graph resolved', and active-profiles/effective-settings answer 'under what environment'. Together they resolve almost any 'unexpected version/config' question.

  • The effective POM doesn't mention the dependency at all, yet it's on the classpath. Where is it from?
    It's transitive. Use mvn dependency:tree (with -Dverbose) to find which direct dependency pulls it and what mediation chose.
  • What's the cleanest way to force a transitive dependency to a specific version?
    Add it to <dependencyManagement> with the desired version; managed versions take precedence for matching coordinates across the graph.

saying these in an interview costs you the question

  • Only looking at pom.xml and concluding 'it's not here' for a transitive dependency.
  • Confusing the effective POM (declared model) with the resolved dependency tree.
  • Ignoring active profiles/settings.xml when a build differs across machines.

context