Trouble Shooting Wiki

Troubleshooting Maven

From TroubleshootingWiki

Jump to: navigation, search
Troubleshooting Maven
Official Page
Project Documentation
Download
Source Book
200px-1847194540.jpg
ISBN 978-1-847194-54-1
Publisher Packt Publishing
Author(s) Brett Porter, Maria Odea Ching

Maven's strengths can also be its weaknesses. With so much functionality provided by plugins, when something goes wrong it can be hard to tell exactly what is at fault. Here we will look at some common scenarios and learn how to investigate an issue when it occurs.

These may not be solutions, or the ideal behavior for Maven to exhibit in many cases, but it should give you the tools necessary to track down the cause of a problem before investing too many hours into it.

Contents

[edit] Examining Maven output

If an error occurs that seems unfamiliar, the first step is to examine the output of the build.

This can be as simple as looking for the last goal executed. In the event that the error message is not clear enough, we will at least know what Maven was running at the time it occurred, and can jump to the plugin web site for information on the possible cause, or at least configuration options that will alter the behavior or output of the plugin (such as the verbosity level) to help troubleshoot.

However, often the error is not that simple, and finding the cause in a large amount of output is difficult. Two steps can be taken to make this part easier.

Firstly, you can scan the output for the [WARN] or [ERROR] prefix. While not always used, anything logged at this level by a Maven plugin may indicate a problem. If you prefer not to scan the output, you can also run Maven with the -q option. This is an extremely quiet mode of operation, logging only warnings, errors, and messages output directly to the system by plugins.

A more reasonable measure you can take in advance is to reduce the amount of output during the build. This has a number of side benefits, such as reducing the size of build results in a continuous integration server, but more importantly helps you see what is really happening in the build. A key offender in the area of build output can be unit tests. As they often do their own logging or produce their own output, this may appear during the build rather than just receiving the test summary.

However, Surefire has a configuration option to remedy this by channeling all of the output into a separate file for each test. It can be configured like this:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
</plugin>

As simple as this step seems, it can be of great benefit in maintaining your build without any loss of information.

Of course, another option that gives greater control is to avoid the use of the System.out and System.err streams in your test cases, and to configure the logging system used by your code to be as silent as possible,or to write to a file directly.

A final note on Maven output: don't be misled. There are some plugins and even internals of Maven that will report a [WARN] or even [ERROR] message where the behavior is actually correct but it is trying to communicate something that may only potentially be a problem, or is actually a programming fault. Review each message carefully to see if it is the cause of a problem rather than assuming that it is by the label.

[edit] Using debug mode

Often, rather than focusing on a piece of output to find an error, you will need more information than is presented by default for successful debugging. Maven offers two levels of extra information.

The first is the -e option. This simply reports the Java exception that caused Maven to fail when a build error occurs. Intended more for developers troubleshooting bugs in their plugins, it can be of benefit to all in certain circumstances. By examining the stack trace, you have two extra courses of action:

  • Review the nested exceptions (by looking for the Caused by text) for a potential cause that was not originally reported by Maven. This can occur when a plugin does not carry along important information from an original exception. For example, a download may fail due to a particular HTTP error code, but that may only be reported at two or three levels of exceptions deep.
  • If the plugin is open source, you can use the stack trace to examine the source code of the plugin and try to understand the actual problem. Obviously, this would be a last resort!

The stack trace will also be helpful to developers that might later need to fix a bug that caused the problem you are experiencing, so this option is helpful to capture when reporting the issue.

The second option is the kitchen sink alternative, referred to as debug output, which is the -X option. This outputs everything logged anywhere in Maven, and unfortunately there is no middle-of-the-road alternative. It will contain information on the parameters passed to plugins, class paths used to execute Java code, command line parameters for external tools, information about dependency resolution, and much, much more. You should almost certainly capture the output to a file to examine the failure afterwards.

[edit] Confirming the expected models

The assembly of the actual project model used for the Maven build can be a reasonably complex process through inheritance and the application of profiles and management sections of the POM. For this reason, it can be useful to examine exactly what model Maven is attempting to use to see if there is an error in the content.

The Help plugin can be of assistance here. Maven in a Nutshell, three goals are particularly geared towards troubleshooting. The first is the effective-pom goal:

$ mvn help:effective-pom

The output of this goal is very straightforward. It consists of a full listing of the POM file as Maven resolves it. This will have populated fields that have been inherited; including defaults, as well as adjusting paths to the location you are running the build from, and so on. Its counterpart for your settings files is the effective-settings goal:

$ mvn help:effective-settings

Again, this will display the complete settings model being used by Maven, collapsing the one located in the Maven installation with the one stored in the home directory.

Settings caution
Occasionally, your Maven settings will contain sensitive information such as passwords in plain text. While these may be stored in a relatively secure location on your hard drive, executing the above goal will output them to the screen. In particular, do not blindly copy that output into a bug report or mailing list post while you are investigating a problem!Maven 2.1.0 and above have the capability to mask those passwords to avoid such issues.

[edit] Analyzing dependencies

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

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. 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.

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.

[edit] Download problems

Getting into trouble downloading artifacts for the build or dependencies of the project can be a common issue in Maven builds as well. The following are some tips for alleviating these issues.

If you have an outright connection issue, the debug output described earlier may contain the exception that occurred, even if the build happened to continue. It is worth taking the URL that Maven was attempting to download from and checking that you can access it from a browser to rule out any external factors.

You might be inclined to use the command line application wget on GNU-based systems. This may give you a false failure, however, as applications that are capable of scraping content are banned from the central repository from time to time to prevent bandwidth abuse.

You may notice a problem in these situations where a repository has been "blacklisted": [INFO] Repository 'central' will be blacklisted

This is often misinterpreted as meaning that the repository will never be used again but this is not the case. It is actually only blacklisted during the same build to avoid repeatedly trying to use a repository that cannot be reached or may have timed out, for the speed of the build. The decision is not remembered across builds and the repository will be used again on the next run.

If you operate in a constrained network environment, you should also check your proxy settings or server username and password for the repository in question (the help:effective-settings goal described above can be of assistance here).

If the download itself seems to succeed but the resolution process fails with an artifact not being found, then you may have a problem with corrupted local metadata. While the cases where this occurs have been reduced, there have been some situations that can lead to this in particular:

  • Running offline or where network connections will regularly fail, causing

Maven to permanently assume an artifact cannot be found

  • Running in an environment where incorrect content is deliberately returned.

A classic example is the Wi-Fi in the airport lounge that throws up a perfectly valid HTML login page on every single request, getting into the local repository metadata and artifacts if checksums are not being enforced

  • Running with an incorrect clock time that can cause update checks to stop running in the future as the files never appear out of date

While it is possible to prune out corrupted metadata selectively, it can be very tedious. The most comprehensive solution is to delete the content from the local repository entirely and while this is technically harmless, it is not recommended, as it will cause the need to download a large portion of the internet again on subsequent runs!

For this reason, it is highly recommended to install a repository manager in a local network, or even on your own machine. This can run with a low footprint and can

act as your personal proxy to all other remote repositories with a clean set of artifacts and metadata. With this in place, it is possible to delete your local repository at any time without having to worry about the cost of downloading the artifacts again on subsequent builds. It can also reduce the number of potential download problems you will experience and give you more control over how to handle issues with metadata and checksums, for example.

[edit] Source

The source of this content is Appendix A: Troubleshooting Maven of Apache Maven 2 Effective Implementation by Brett Porter, Maria Odea Ching(Packt Publishing, 2009).

Personal tools