Problems are often much more subtle than a direct error in the build, however, and dependencies can be a major cause. Because Maven resolves transitive dependencies, it is common to be using dependencies, or versions, that you may not have expected. Similar types of problems you are likely to see are:
Incorrect versions of dependencies being used
Duplicated dependencies (for example, if an artifact changes to a new group ID in a more recent version, both versions will appear in the dependency tree)
Missing dependencies
Unwanted dependencies
Incorrect dependency scopes leading to incorrect classpaths for certain goals
As illustrated in Chapter 1, Maven in a Nutshell, the Enforcer plugin can be used as preventative medicine against some of these problems.
One of the most useful tools you will be able to use in evaluating these problems is the dependency:tree
goal. Here is the output from the sample web application used in Chapter 1, Maven in a Nutshell:
[INFO] [dependency:tree] [INFO] com.effectivemaven.chapter01:simple-webapp:war:1.0-SNAPSHOT [INFO] +- org.slf4j:slf4j-api:jar:1.5.0:compile [INFO] +- org.slf4j:slf4j-simple:jar:1.5.0:runtime [INFO] \- org.testng:testng:jar:jdk15:5.8:test [INFO] \- junit:junit:jar:3.8.1:test
As you can see, we did not introduce many transitive dependencies, though it may have been surprising to see that we are still using JUnit as a part of TestNG!
Much like the earlier effective-pom
goal, the tree above will illustrate exactly what dependencies Maven ends up using in the build. This information is also shown in debug mode, though it contains a lot more of the decision points and other interspersed debug output that can make it much harder to read.
The remedies for dependency problems vary—you may use the dependency management section to enforce a particular version, the exclusions section of the dependency declaration to prune a particular dependency from the tree, or alter the repository metadata of another project to ensure it is correct in future. These alternatives are also discussed in Chapter 7, Maven Best Practices.
One final issue is worth special attention here. Maven constructs its dependency tree by reading the POM file for an associated dependency and drawing the transitive dependencies from that. If Maven fails to resolve the POM due to a missing file or other download problem, the build will still continue (as it is historically valid, though now considered deprecated, to have a project without a POM). In this case, the project will be considered to have no dependencies, even though they may have been expected. If this occurs, Maven will display a prominent warning message early in the build.