Question

I am trying to get project with submodules to test and generate reports correctly, but have got some problems.

I have the following project structure:

parent
  |-test1
  |-test2

and the pom.xml for parent looks like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>parent</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>

<modules>
    <module>test1</module>
    <module>test2</module>
</modules>

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.16</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-report-plugin</artifactId>
                <version>2.16</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-site-plugin</artifactId>
                <version>3.3</version>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

<reporting>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-report-plugin</artifactId>
            <configuration>
                <aggregate>true</aggregate>
                <reportsDirectories>
                    <reportsDirectory>${basedir}/target/surefire-reports</reportsDirectory>
                </reportsDirectories>
            </configuration>
            <reportSets>
                <reportSet>
                    <inherited>false</inherited>
                    <reports>
                        <report>report-only</report>
                    </reports>
                </reportSet>
            </reportSets>
        </plugin>
    </plugins>
</reporting>

And I use mvn clean install site to build the project, run the tests and generate a site (which uses maven site plugin, which in turn uses maven surefire report plugin, to generate test report).

The trouble is the parent pom.xml is executed with all phases (clean, install and site) before submodules' pom.xml are executed, hence no test report from test1 and test2 are aggregated in parent.

So is there a way to execute mvn clean install site in a single line, or do I absolutely have to execute mvn clean install first then mvn site?

Thanks for any suggestions.

Was it helpful?

Solution

The config shown uses the same POM as both the parent and aggregator. Documentation will also discuss inheritance vs. multi-module. A parent POM passes values to its children, while an aggregator POM manages a group of subprojects or modules. Section 3.6.2 of the Sonatype Maven Book goes into a lot more detail.

In my experience, Maven builds work better when the parent and aggregator POMs are separate.

The reason has to do with dependencies, how Maven determines build order, and how Maven runs commands. If your sample structure was like this, with a separate parent and aggregator, where test1 and test2 inherited from parent:

project (aggregator POM)
  |- parent
  |- test1
  |- test2

then the Maven build order will look like this (assuming dependencies are defined correctly of course):

  • parent
  • test1
  • test2
  • aggregator

A command like mvn clean install site will start with the parent project, cleaning and building, installing to the local artifact repository, then generating the project site. It repeats this command sequence in order for each project shown. Because the aggregator is separate, it may have separate configuration to perform report aggregation for tests, coverage and javadoc. The aggregator runs last, so the coverage databases and intermediate javadoc files for the modules already exist, ready to be appropriately combined.

When the parent and aggregator are the same POM as you have it, the build order is:

  • parentAggregator
  • test1
  • test2

When you run mvn clean install site now, Maven must build the parent POM (here, parentAggregator) so it has the information required for the child modules depending on it. parentAggregator is also the aggregator, so Maven will happily run any aggregating reports as part of site. Of course, the child modules haven't been built yet, so there are no coverage databases or intermediate javadoc files to aggregate. Or, possibly worse, old files exist so the aggregator operates on those files. After the parent-aggregator builds, the child modules build, and then the command exits. There is no final aggregation step at the end of the build. The overall results are probably not what you want.

This phenomenon can cause problems during multi-module project release builds, painful enough that developers wrote a versions-maven-plugin mojo to help correct them. The issue:

If you have a multi-module build where the aggregator pom (i.e. the one with packaging of pom and the modules section) is also the parent referenced by its child modules, and the aggregator version does not match the version specified in the parent section of the child modules, Maven will not let you build the project.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top