Monitoring and Improving the Health of your Dependencies
Many people use Maven primarily as a dependency manager. While this is only one of Maven’s features, used well it is a significant time saver.
Maven 2.0 introduced transitive dependencies, where the dependencies of dependencies are included in a build, and a number of other features such as scoping and version selection. This brought much more power to Maven’s dependency mechanism, but does introduce a drawback: poor dependency maintenance or poor scope and version selection affects not only your own project, but any projects that depend on your project. Left unchecked, the full graph of a project’s dependencies can quickly balloon in size and start to introduce conflicts.
The first step to effectively maintaining your dependencies is to review the standard report included with the Maven site. If you haven’t done so already, run mvn site in the proficio-core directory, and browse to the file generated in target/site/dependencies.html. The result is shown in Figure 6-11.

Figure 6-11: An example dependency report
This report shows detailed information about your direct dependencies, but more importantly in the second section it will list all of the transitive dependencies included through those dependencies. It’s here that you might see something that you didn’t expect – an extra dependency, an incorrect version, or an incorrect scope – and choose to investigate its inclusion.
Currently, this requires running your build with debug turned on, such as mvn -X package. This will output the dependency tree as it is calculated, using indentation to indicate which dependencies introduce other dependencies, as well as comments about what versions and scopes are selected, and why. For example, here is the resolution process of the dependencies of proficio-core (some fields have been omitted for brevity):
proficio-core:1.0-SNAPSHOT
junit:3.8.1 (selected for test)
plexus-container-default:1.0-alpha-9 (selected for compile)
plexus-utils:1.0.4 (selected for compile)
classworlds:1.1-alpha-2 (selected for compile)
junit:3.8.1 (not setting scope to: compile; local scope test wins)
proficio-api:1.0-SNAPSHOT (selected for compile)
proficio-model:1.0-SNAPSHOT (selected for compile)
Here you can see that, for example, proficio-model is introduced by proficio-api, and that plexus-container-default attempts to introduce junit as a compile dependency, but that it is overridden by the test scoped dependency in proficio-core.
This can be quite difficult to read, so at the time of this writing there are two features that are aimed at helping in this area:
- The Repository Manager (Archiva) will allow you to navigate the dependency tree through the metadata stored in the Ibiblio repository.
- A dependency graphing plugin that will render a graphical representation of the information.
Another report that is available is the “Dependency Convergence Report”. This report is also a standard report, but appears in a multi-module build only. To see the report for the Proficio project, run mvn site from the base proficio directory. The file target/site/dependency-convergence.html will be created, and is shown in Figure 6-12.
The report shows all of the dependencies included in all of the modules within the project. It also includes some statistics and reports on two important factors:
- Whether the versions of dependencies used for each module is in alignment. This helps ensure your build is consistent and reduces the probability of introducing an accidental incompatibility.
- Whether there are outstanding SNAPSHOT dependencies in the build, which indicates dependencies that are in development, and must be updated before the project can be released.

Figure 6-12: The dependency convergence report
These reports are passive – there are no associated checks for them. However, they can provide basic help in identifying the state of your dependencies once you know what to find. To improve your project’s health and the ability to reuse it as a dependency itself, try the following recommendations for your dependencies:
- Look for dependencies in your project that are no longer used
- Check that the scope of your dependencies are set correctly (to test if only used for unit tests, or runtime if it is needed to bundle with or run the application but not for compiling your source code).
- Use a range of supported dependency versions, declaring the absolute minimum supported as the lower boundary, rather than using the latest available. You can control what version is actually used by declaring the dependency version in a project that packages or runs the application.
- Add exclusions to dependencies to remove poorly defined dependencies from the tree. This is particularly the case for dependencies that are optional and unused by your project.
Given the importance of this task, more tools are needed in Maven. Two that are in progress were listed above, but there are plans for more:
- A class analysis plugin that helps identify dependencies that are unused in your current project
- Improved dependency management features including different mechanisms for selecting versions that will allow you to deal with conflicting versions, specification dependencies that let you depend on an API and manage the implementation at runtime, and more.


Comments
I'd like to start by thanking
I'd like to start by thanking everyone who has been involved in the Maven community over the years, for sticking with it through some of the early development and for holding the development team to a higher standard. Maven is the cumulative work of nearly 40 committers and an even larger number of contributors who've taken the time to give feedback, contribute ideas, answer questions, test features, and submit fixes.