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

8 gedachten over “Maven aggregate reports for multi-module projects

  1. Kermit

    Hi,

    I tried out your example but the aggregate surefire-report is not generated at all. I’m using Maven 3.1.1 if this matters.

    Regards,
    Kermit

    Reageren
  2. barts Bericht auteur

    @Kermit: Which OS are you on, and what is the error that you see? All seems to be working fine on Ubuntu, but I have found some problems running the build on a Windows machine.

    The project uses maven-site-plugin version 3.0, which causes: java.lang.ClassNotFoundException: org.sonatype.aether.graph.DependencyFilter https://jira.codehaus.org/browse/MSITE-683 (fixed in 3.3). This problem occurs only on Windows, and not on Ubuntu.

    Upgrading the site plugin to 3.3 fixed the above, but it introduced a new problem: stage failed: Base URI is not absolute This seemes to be caused by another site-plugin bug (http://jira.codehaus.org/browse/MSITE-671). This problem occurs on both platforms.

    So using the latest version of the site-plugin is a bad idea. And if you are using Windows then we need to look into the problem to find a workaround.

    Reageren
    1. Kermit

      Hi,

      I’m on windows.

      Actually I don’t get any error messages in mvn verify, mvn site and mvn site:site.

      But if I open target/site/surefire-report.html, It seems as if no tests have been excecuted at all. All numbers are 0. In mod1/target/site/surefire-report.html and mod2/target/site/surefire-report.html everything is fine. So the aggregation of surefire-results does not work. (by the way aggregation of failsafe-results works perfectly)

      Regards Kermit

      Reageren
      1. barts Bericht auteur

        I have reproduced your problem. After the mvn site command the aggregated surefire reports should be available in target/site/surefire-report.html. Again, on Ubuntu this works as expected, but on Windows the reports are empty. I’ll have to look into this.

        Reageren
    1. barts Bericht auteur

      After some investigation I found that the problem is in the order of report generation. The surefire report plugin does generate the aggregate report, but it overwrites it with the surefire report of the parent pom which has no unit tests. That is why you see the empty unittest-report, you are looking at the report for the parent pom which we do not want to create at all.

      I also found out that the order or the reportSets in the maven-surefire-report-plugin influences the order of report-generation. It seems that on Ubuntu the plugin creates the reports in the order of the reportSets in the reporting plugin. On Windows it is the opposite order. This is unspecified behaviour and we cannot rely on it. It should quick-fix your report though. Try swapping the unit-tests reportSet and the unit-tests-aggregate reportSet in the parent pom. Then run mvn site.

      But there are better solutions. Option 1 below is the easiest fix and not too bad. I implemented this and pushed a commit to the bitbucket repo.

      1. specify alwaysGenerateSurefireReport = false in the unit-tests reportSet configuration; easiest solution, prevents generation of empty unittest report for the parent project
      2. specify unit test reports for child modules in the child-poms instead of in the parent pom; this is exacly what we want, but the disadvantage is that we must change the poms of all child projects
      3. generate only aggregate reports in the parent, no unittest reports for the child projects
      4. swap reportSet order for unit test reports; bad solution, we must not depend on reportSet order and this breaks the unittest aggregate report on Ubuntu

      Reageren

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd met *