Tagarchief: java

Maven aggregate reports for multi-module projects

December 2013

Maven aggregate reports are useful. They combine the reporting information of a number of maven projects, for example it shows the total amount of code. This article describes how to generate these reports.

If you are looking for a quick copy and paste solution, here is the maven root POM providing all reporting configuration for the aggregate-reports and the child-modules-reports. That’s it, one file, there is nothing to see in the child-modules POM files.

To start with, one of the best tools for quality reports is Sonar. Use it if you can. It allows you to detect changes in code quality over time and it detects hot-spots in your codebase. If it is not possible to use Sonar, or maybe in addition to sonar, the static maven reports can still be very useful.

Reporting for a single project is easy, but aggregate reports are often the most useful because they combine the results of all project-reports in a multi-module project. Configuring the aggregate reports takes some extra effort. The information about maven reporting is scattered and I decided to summarize it in this article.

There are several strategies that reporting-plugins use to create aggregate reports. After an introduction about reporting this article summarizes the aggregate configuration strategies for several widely used plugins using the maven recommended format for configuring reports.

Maven Reporting

Reporting goals and plugins

A reporting goal is a plugin goal that was designed to generate some report as a result of an invocation by the Maven Site Plugin. Reporting goals are marked in the plugin documentation ‘Report?’ column. See for example the Maven Javadoc Plugin goals. Project reporting plugins are maven plugins supporting one or more reporting goals. Maven Project reporting plugins are marked with an ‘R’ in the ‘Type’ column in the plugins overview.

The Site Plugin

Maven uses the Maven Site Plugin to generate the reports with the invocation of the site goal in the site lifecycle (mvn site:site). It executes the reporting plugins configured in the reporting section of the POM. By default, the Maven Site Plugin invokes every reporting goal of the plugins configured in the reporting section. Configuring a plugin without reporting goals in the reporting section has no effect. Even if you point a reportSet to some goal of the plugin. The Site Plugin just ignores the plugin or reportSet if it does not support reporting.

Configuring

If you need to customize the reporting behaviour then you can tune the plugin using reportSets specifications. A reportSet points to one or more reporting goal with the report element. If the plugin is configured without reportSets then all reporting goals are executed once.
If there are no special reporting requirements for some modules, it is a best practice to put all configuration in the parent POM. In this example the root and parent POM are the same project.

Maven aggregate support

The default behaviour of the Maven Site Plugin is to execute all reporting goals of the plugins mentioned in the reporting secion of the POM. This is why reporting plugins with an aggregate goal require no further configuration. Other plugins use an aggregate configuration parameter in the reporting goals. Some plugins support an aggregate goal and and configuration parameter to produce the aggregate reports. In this case using the goal is the way to go. The parameter is often deprecated in favour of the aggregate goal.

There is one problem with maven generating aggregate reports. It creates the reports of the root project before the child projects. Aggregate reports often need the child projects reporting results. That is why we need to run the site goal twice.

Source code & build

A simple multi-module project used for this article is available in bitbucket: https://bitbucket.org/bartswen/aggregate-report-demo

Download it and execute the build commands in the root project directory:

  1. mvn verify site
  2. mvn site:site site:stage

You will find the reports in ./target/staging/index.html

There are two ways to configure reports in maven 3. This article is based on the recommended ‘classic’ configuration format using the <reporting> section of the POM. Note that many online examples use the <reportPlugins> element in the site plugin configuration. This is not recommended and the element will be removed.

Reporting plugins configuration

I divide the reporting plugins into three categories.

1. Plugins with automatic aggregate support

Some reporting plugins are smart. They automatically detect an ‘aggregate scenario’. The JavaNCSS Plugin uses this strategy. If the project has no source and it has child modules then the plugins report goal tries to generate an aggregate. Unfortunately the NCSS Plugin does need two cycles to generate the aggregate reports. The declaration below is enough to produce the modules NCSS reports and the aggregate report showing the total amount of code of all modules:

2. Plugins supporting an aggregate goal

Other reporting plugins have a separate aggregate reporting goal. According to the site plugin documentation we should configure reportSets for these reports: read the ‘Notice’ below the code fragment on the Site Plugins reportSet documentation. But, although I am unable to find any documentation about this subject, these plugins seem to be smart enough to skip the aggregate goal on a non-aggregate project. The reports look good, even if we do not configure any reportSets to map the right plugin goals on the projects.

To validate a report, take for example the JXR Plugin. It produces a cross-reference of the project’s sources. Note how the aggregate report references the Mod1 from the Mod2 class. The non-aggregate report of the mod2 module has no reference to Mod1.

3. Plugins using an aggregate parameter

These plugins have no specific aggregate goals, but they require special configuration to produce aggregate reports. The trick here is to define two reportSets under the plugin configuration in the reporting section. One reportSet is to be inherited by the modules to build their reports. The other reportSet produces the aggregate report using <aggregate>true</aggregate> as a configuration parameter. In this case we must configure the reportSet to apply only to the root project and not be inherited by the modules, using <inherited>false<inherited>. The <report> element refers to a plugin reporting goal.

Taglist

Taglist Maven Plugin

Cobertura

Although there have been problems to create Cobertura aggregate reports, all seems to be working now with the current version of the Cobertura Maven Plugin. The <aggregate>true</aggregate> parameter does not seem to bother the modules projects report generation. So with Cobertura we only need one reportSet to generate both the project reports as well as the aggregate report.

And by the way, while you are there, for fun check the Cobertura report of the Cobertura Plugin. Ironically it’s pretty red itself (at the time of writing).

PMD and CPD reports

The PMD Plugin has two reporting goals. One for the PMD, and one for the CPD report. For each we need the two reportSets, so we have four reportSets here:

Unit and integration test reports

There exists a special plugin for generating the test-reports: the Surefire Report Plugin. Provided that you have configured the Failsafe Plugin to run the integration tests, it produces reports for unit-tests as well as for the integration-tests. So again we need to specify four reportSets: two for the unit-test reports, and two for the integration-test reports.

Final note

Unfortunately there exists a fourth category of reporting plugins: those that do not support aggregate reports. For example the FindBugs Plugin states that it is unable to generate these reports.

Resources

Maven

Reporting plugins not supported by the maven project