Dependency Graph

When resolving transitive dependencies, Resolver (former Aether) constructs a dependency graph consisting of DependencyNode instances where each node represents a dependency and its direct dependencies are represented as child nodes. During early stages of the resolution process, there are usually duplicate dependencies or even cycles in the graph as sketched below:

   root
   / \
  /   \
a:1   b:1  <--+
  \   / \     |
   \ /   \    |
   c:1   a:2  |
    |         |
    +---------+

Once this dependency graph has undergone conflict resolution, i.e. duplicate dependencies have been removed, one actually has a dependency tree. Taking the previous example, the tree might look like this:

   root
   / \
  /   \
a:1   b:1
 |
 |
c:1

The dependency tree is a handy data structure to get the complete set of artifacts one would need to form a classpath etc. as a simple recursive traversal is sufficient to gather the relevant dependencies.

Troubleshooting a Dependency Graph

The dependency tree provides a compact and basic means to end users to understand why/how a given artifact ended up among the dependencies. But as the examples above illustrate, the dependency tree misses some information compared to the dependency graph. For instance, the tree does not indicate that b:1 also depends on c:1. To help troubleshooting complex dependency graphs, some configuration properties exist to keep useful data in the dependency graph returned by RepositorySystem.collectDependencies().

For instance, the configuration property ConflictResolver.CONFIG_PROP_VERBOSE can be enabled to produce a graph similar to m2e's dependency hierarchy view where conflicting nodes are retained. This gives end users a better understanding of all the paths that pull in a given dependency.

The configuration property DependencyManagerUtils.CONFIG_PROP_VERBOSE can be enabled to record the attributes of a dependency before they were updated due to dependency management. This helps end users to understand why one version of a dependency and not the other is found in the graph or why a dependency ended up in a given scope.

Please see the API docs for said configuration properties for details regarding their effects and ways to access the additional data.