skip to content

How do you inspect the full dependency graph of a Maven project, and what does dependency:tree show you?

level: juniorimportance: must knowfreq 80%

answer

  1. tree = resolved graph
  2. indent = who pulled it in
  3. -Dincludes filters branches
  4. -Dverbose shows omitted/conflicts
  5. group:artifact:type:version:scope

basics

~10 s

Run mvn dependency:tree. It prints every dependency your project pulls in, including transitive ones, as an indented tree showing which dependency brought in which, plus the scope and version of each.

solid answer

~40 s

`mvn dependency:tree` (the `tree` goal of the `maven-dependency-plugin`) renders the resolved dependency graph as an indented tree. Each node shows groupId:artifactId:type:version:scope, and indentation shows the parent that pulled it in transitively. It is the first tool you reach for to answer 'why is this jar on my classpath?' or 'which version actually won?'. You can scope output with `-Dincludes=groupId:artifactId` to show only the paths leading to a given artifact, and add `-Dverbose` to also see omitted/conflicting versions that mediation removed. It reflects the *resolved* graph after version mediation and scope rules, so it is the source of truth for what Maven actually puts on each classpath, not just what you declared in your pom.

code

bash · 1 line
bash
mvn dependency:tree -Dverbose -Dincludes=org.slf4j:slf4j-api

go deeper

for a junior

Knows to run mvn dependency:tree and read the indentation to find transitive deps.

for a middle

Uses -Dincludes and -Dverbose to isolate and debug a specific artifact and see conflicts.

for a senior

Treats the tree as authoritative resolved state and uses it to drive mediation/exclusion decisions.

for a principal

Standardizes graph-inspection workflows and teaches teams to debug classpath issues from the resolved graph rather than guessing from poms.

## What the dependency graph is Maven builds projects with declared dependencies, but each dependency can itself declare dependencies — these are **transitive dependencies**. The complete set forms a directed graph. Your classpath is determined by *resolving* that graph, applying version mediation and scope rules. ## dependency:tree `mvn dependency:tree` invokes the `tree` goal of the `maven-dependency-plugin`. It prints the resolved graph as an indented ASCII tree. The root is your project; children are direct dependencies; grandchildren are transitive ones. Each line has the coordinate form: `groupId:artifactId:type:version:scope` (e.g. `org.springframework:spring-core:jar:6.1.0:compile`). ## Key options - `-Dverbose` — also shows nodes that were *omitted* during resolution, annotated with reasons like `(omitted for conflict with 6.1.0)` or `(omitted for duplicate)`. This is how you see losing versions. - `-Dincludes=group:artifact` — filters to only the branches that lead to the matching artifact. Wildcards allowed, e.g. `-Dincludes=com.fasterxml.jackson.core:*`. - `-Dexcludes=...` — inverse filter. - `-DoutputType=dot` / `-DoutputFile=...` — emit a Graphviz/text file. ## Why it matters It answers the two most common dependency questions: *what is on my classpath* and *who pulled it in*. Because it shows the **resolved** graph (post-mediation, post-scope), it is authoritative — far more reliable than reading the pom by hand, which only shows what you declared, not what won. ```bash mvn dependency:tree -Dverbose -Dincludes=com.fasterxml.jackson.core:jackson-databind ``` This prints only the paths leading to jackson-databind and includes the conflicting versions that mediation discarded.

  • What does the -Dverbose flag add to the output?
    It shows dependency nodes that resolution omitted (e.g. losing versions in a conflict or duplicates), annotated with the reason, so you can see what mediation discarded.
  • Does dependency:tree show declared or resolved versions?
    Resolved — it reflects the graph after version mediation and scope filtering, which is why it's authoritative for what's actually on the classpath.

Like a family tree where each ancestor can bring relatives you never invited — the tree shows the whole bloodline and who introduced whom.

saying these in an interview costs you the question

  • Saying the tree shows only direct dependencies (it shows transitive too)
  • Claiming it reflects what you declared rather than what was resolved
  • Confusing -Dincludes (a filter) with adding a dependency

context