# depgraph-maven-plugin: dependency graphs you can actually look at

> Maven's own dependency tree is a list of text, and reading a list of text to find out why a large project has forty copies of one library is not a pleasant activity. This plugin renders the same information as a graph, in five formats, for a single module or aggregated across a whole multi-module build, and it marks the duplicates and the version conflicts that are the reason you are reading it at all.

**ferstl/depgraph-maven-plugin** — A Maven plugin that generates dependency graphs in various formats (DOT, GML, PlantUML, JSON and Text)

- Repository: https://github.com/ferstl/depgraph-maven-plugin
- Stars: 607 · Forks: 87
- Language: Java
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/ferstl-depgraph-maven-plugin

## Five formats, and why more than one

The depgraph-maven-plugin generates dependency graphs on a single module or in an aggregated form on multi-module projects, and the five output formats are the interesting part of the design rather than an afterthought.

The DOT format is the one for the graph drawing tool, and when that tool is installed the generated files can be rendered directly into all of the image formats it supports. DOT is a small language for describing a graph, and it is the lingua franca here because the graph drawing tool is what most people already have.

The GML format is for the Graph Markup Language, and the readme points at a specific editor for it, one that allows further processing and layout of the dependency graph. So GML is the choice when you want to rearrange the picture, not just look at it.

The PlantUML format is the one for people who do not want to install anything, because the readme names a browser based renderer and an editor plugin. That is a deliberate choice: the fastest way to get a dependency diagram in front of a team is a URL they can open.

The JSON format is the one for machines. The readme says it is intended for JavaScript libraries to visualise the dependency graph or for further processing, which is the format you want if you are building your own viewer or feeding the data to something else.

And the text format is the one that is a more powerful alternative to the built-in dependency tree goal, printed to the console. That last one matters more than it looks, because a text graph in a console is a graph and a text tree is a tree. The ability to see the shape of the dependencies without opening a picture is what makes the plugin useful in a continuous integration log.

So the choice of format is a choice of consumer, and having five of them means the same information can go to a picture, to a diagram service, to a script, to an editor, or to a terminal. The project is Apache 2.0 licensed, published on the central repository, with the last push in September 2026.

## Adding it, and the short form on the command line

Installation is unremarkable because the plugin is on the central repository, so no further repository configuration is required. What is worth looking at is the two ways of invoking it.

In a project, the plugin is added to the build section, with a group, an artifact, a version, and a configuration block.

```xml
    <build>
      <plugins>
        <plugin>
          <groupId>com.github.ferstl</groupId>
          <artifactId>depgraph-maven-plugin</artifactId>
          <version>4.0.4</version>
          <configuration>
            ...
          </configuration>
        </plugin>
      </plugins>
    </build>
```

And on the command line, for ad-hoc analysis, the readme recommends adding the group as a plugin group in the settings file.

```xml
    <settings>
      ...
      <pluginGroups>
        <pluginGroup>com.github.ferstl</pluginGroup>
      </pluginGroups>
      ...
    </settings>
```

With that in place the short form works, so the graph goal can be invoked with the plugin's own name and the goal name and nothing else. Without it you have to write the full coordinates, and the readme gives both the form for the latest version and the form with a specific version pinned.

The plugin group setting is a small convenience with a broader effect. It is the difference between a command a person types and a command they have to paste from a wiki, and for a tool whose main use is ad-hoc investigation, that is the difference between using it and not using it.

Unless configured otherwise, the graphs are written into the project's build directory with a name based on the format, so the output lands in the same place as everything else the build produces and is cleaned up with it. That default is the right one: a tool that scatters files into the source tree is a tool people stop running.

The documentation is in three places, and the split is sensible. There is a plugin documentation site with a page per goal, a release notes page, and a wiki.

## The basic graph, and what you can turn on

The example project the readme uses is a small multi-module one, with a parent, two modules, and a sub-parent containing a third module, and each module holding dependencies in different scopes.

The basic graph comes from the graph goal, and the readme then shows the two display options. There is a flag to show the versions of the dependencies, and a flag to show the group identifiers. Each produces its own image in the documentation.

Those two flags are the difference between a graph that tells you what is in your project and one that tells you what is wrong with it. A graph with no version information is a picture of the shape of your dependencies, which is useful when you are new to a project. A graph with versions on the edges is a picture of the versions, and that is where the interesting failures live: two paths to the same library, one asking for version three and one asking for version five.

The default is the simple graph, which is a sensible default, because the shape is the thing you look at first, and the versions are the thing you add once the shape is familiar.

The goal is documented on its own page, and each goal in this plugin has one, with the options for that goal. The documentation is generated from the goal descriptions, so the page and the implementation cannot disagree, and a reader who wants to know what a flag does does not have to read the source.

And the flags are set on the command line with the usual system property syntax, so you can turn them on for a single run without editing the build file. For an investigation tool that is the right ergonomics: the common case is a one-off question about the project as it is, and a permanent configuration change to a build file is a much heavier thing to do.

## Duplicates and conflicts, which are not the same thing

This is the part of the plugin that earns its place, and the distinction it draws is the useful part.

Duplicate versions are shown as dotted black arrows. Conflicting versions are shown as dashed red arrows. Two different visual treatments, and the readme explains why the difference matters.

A duplicate occurs when more than one module defines the same dependency. And the readme says plainly that this is not a problem: Maven's dependency resolution will pick one dependency and omit all the duplicates. So a duplicate is noise in the graph, and the dotted arrow is the tool telling you that it noticed something you do not have to act on.

A conflict is different. It occurs when the same dependency appears in different versions in the reactor, in other words when two modules of your build want different versions of the same library. In that case Maven chooses the nearest version and omits the others, which is the mechanism that causes the problems people know as dependency hell. The readme's guidance is that occurrences of conflicting versions should be investigated and solved if possible.

That is a genuinely useful distinction, because the two look similar in a dependency tree and require completely different responses. A duplicate is a fact about your project. A conflict is a fact about your project that will change the behaviour of a library at run time, and which nobody will find by reading the tree.

And the visual treatment carries it: the red dashed edge is the one you look for. A graph where most edges are dotted black is a graph with a lot of noise; a graph with one red dashed edge is a graph with one thing to fix, and it is now a picture rather than a hundred lines of text.

## Grouped graphs, aggregated graphs, and arbitrary artifacts

Two more views, and they answer different questions.

The first groups by the group identifier rather than by the artifact. The readme's description of the result is that such graphs give a higher level overview of a project, and that they show better which frameworks a project uses. That is the right description: at the artifact level a graph shows you library after library, and at the group level it shows you the handful of organisations your project actually depends on, which is the level at which an architectural conversation happens.

The second is the aggregated view, and the readme explains the idea in one line: the goals show the union of all the modules' dependencies by omitting redundant edges. So instead of a graph per module, you get one graph for the whole build, and the edges that appear in more than one module are drawn once.

That is the view that answers the question a multi-module build actually raises, which is whether the whole thing pulls in more than it should. The example in the readme connects the parent project and its modules with dotted black arrows, and it notes that two of the modules were left out of the picture for clarity.

The same aggregation exists for the grouped view, so you can ask the same question at either level.

And there is a goal for making a graph of an arbitrary artifact, meaning you can point the tool at a dependency that is not part of your build and see what it would drag in. That is the goal for the upgrade decision, the one where you want to know what a candidate library would cost you before you adopt it.

So there are four goals to think about: the plain graph, the grouped graph, the two aggregated variants, and the arbitrary artifact one. Each is documented on its own page, and the naming follows the same pattern, which makes them easy to find.

## The repository, and a release line worth reading

The repository is small, and it is an ordinary Java project. There is a build file, a source directory, a licence, a readme, a checkstyle configuration, and a continuous integration directory.

The checkstyle configuration is worth a mention for a plugin, because the tool reads your project's own dependency metadata to build the graph, and the styles of the graphs it produces are often judged against the standards of the project the graph came from. A plugin that renders dependency information about a codebase has an interest in the codebase being tidy, and a style configuration is the mechanism for caring about that.

The release history is the more interesting part, because it contains a small oddity. The most recent releases are two patch versions published on the same day, and the release note for the earlier one says to use the later one directly. In other words, the second release exists to redirect people who pinned the first.

That is a pattern worth understanding rather than dismissing. When a plugin is used in a build, the version is usually pinned, often in a parent build file that many modules inherit, so a bad release cannot simply be unpublished: anybody who already resolved it keeps it. Releasing a fixed version and then publishing a note that supersedes the broken one is the practical way to handle that, because the build tool will not re-resolve a version that is already pinned but it will read a release note that says the other one is fine.

There is also a gap in the history. A version from the end of 2023 is followed by two in September 2026, which suggests a long period where the plugin was stable and the work was elsewhere, and then a burst of maintenance.

The documentation is in three places, and the readme links all of them: a plugin documentation site with a page per goal, the release notes, and the wiki. The plugin documentation is the one that matters, because it is generated from the goal descriptions, and the goal descriptions are the same code the plugin runs. A flag documented there is a flag that exists.

And the plugin is on the central repository under a group with a reverse domain name, which is the convention that keeps it out of everybody else's namespace and makes it safe for a tool that people put in their builds without reading the source.

## Conclusion

depgraph-maven-plugin fits a team with a large multi-module build where nobody can hold the dependency set in their head, and a reviewer who needs a picture to put in a discussion. It does not fit a project with a handful of dependencies, where the text tree is already enough. Verify first that the plugin version you use matches the Maven version you run, since the release line is tied to the build tool, that you run it in a mode that suits the question, because the per module and the aggregated views answer different questions, and that the conflicts it reports are the conflicts you meant to see, since the difference between a duplicate and a conflict determines whether anything actually needs fixing.

## FAQ

### What does the depgraph-maven-plugin do?

It generates dependency graphs for a single module or aggregated across a multi-module project, in five formats: DOT for the graph drawing tool, GML for an editor that can lay the graph out further, PlantUML for a browser based renderer, JSON for processing by a script, and a text format printed to the console as a more powerful alternative to the built-in dependency tree goal.

### How do I run the depgraph-maven-plugin on the command line?

Add the plugin group to the plugin groups in the settings file, and then the short form works, invoking the plugin by name and the goal by name. Without that setting you have to write the full group, artifact, and goal coordinates, optionally with a specific version pinned.

### What is the difference between a duplicate and a conflict in the depgraph-maven-plugin?

A duplicate is when more than one module declares the same dependency, which is not a problem because resolution picks one and omits the rest, and it is drawn as a dotted black arrow. A conflict is when the same dependency appears at different versions in the reactor, where resolution picks the nearest and omits the others, and it is drawn as a dashed red arrow and is worth investigating.

### What is the difference between the depgraph-maven-plugin goals?

The plain goal graphs one module's dependencies, the grouped goal graphs them by group identifier for a higher level view of which frameworks a project uses, the two aggregate goals produce the union of all modules' dependencies at the root of the build with the redundant edges omitted, and the artifact goal graphs an arbitrary dependency that is not part of the project.

### Where does the depgraph-maven-plugin write its output?

Unless configured otherwise, into the project's build directory with a name based on the format, so the graph lands alongside the other build output and is cleaned up with it. The plugin is published on the central repository, so no repository configuration is needed to use it.

## Sources

- [ferstl/depgraph-maven-plugin on GitHub](https://github.com/ferstl/depgraph-maven-plugin)
- [Issues](https://github.com/ferstl/depgraph-maven-plugin/issues)
- [License: Apache-2.0](https://github.com/ferstl/depgraph-maven-plugin/blob/master/LICENSE)
- [README](https://github.com/ferstl/depgraph-maven-plugin/blob/master/README.md)
- [Releases](https://github.com/ferstl/depgraph-maven-plugin/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ferstl-depgraph-maven-plugin
