Maven build lifecycle phase synchronization across modules

116 views Asked by At

I have a maven project with a reactor and a couple of modules, most of which are being packed as war. The order in which they are specified in the reactor / root pom.xml defines the order in which they are built.

pom.xml

....
<module>library1</module>
<module>library2</module>
<module>webapp1</module><!--war-->
<module>webapp2</module><!--war-->
<module>blackduck-scan</module><!-- create file to be placed into webapp2 post-build but pre-packaging of webapp2 -->
...

The last module, purposely, is destined to simply run an executable in the prepare-package phase. More precisely a blackduck license scanner, which itself eventually produces the license notice file which is then placed into the /webapp folder of one of the web applications to be displayed after deployment.

The idea is what this notice file is being placed after compilation of the applications but before packaging these as WAR artifacts to have it included in the current delivery of our pipeline without re-building just for the sake of re-packaging.

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
    <executable>java</executable>
    <workingDirectory>.</workingDirectory>
    <arguments>
        <argument>-jar</argument>
        <argument>synopsys-detect-8.4.0.jar</argument>
    </arguments>
    ...
</configuration>
<executions>
    <execution>
        <goals>
            <goal>exec</goal>
        </goals>
        <phase>prepare-package</phase>
    </execution>
</executions>
</plugin>

I've tried two options to achieve this without success.

a) Adding the plugin/goal to the reactor pom.xml leads to the goal being executed first as soon as the target phase is prepare-package and thus may lead to incomplete scan results while the actual project has not yet been built.

b) Adding then plugin/goal as a module as described above puts the execution at the end of the chain, however, packaging of the webapps has already been concluded.

c) The third (arguably working) but less elegant approach would be to split this into two separate maven calls:

mvn clean install && mvn package

I see that modules are build in sequence and for good reason. However, is there any method to "synchronize" build phases such that each phase is started only after the previous phase has been completed for all modules? Effectively to simply call, all included:

mvn clean install
1

There are 1 answers

0
Andrey B. Panfilov On BEST ANSWER

I believe the option is:

  • disable war creation and run exploded goal instead
  • use maven-assembly-plugin to pack target war
  • inject execution of blackduck between maven-war-plugin and maven-assembly-plugin

smth. like:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <executions>
        <execution>
            <!-- disabling building war -->
            <id>default-war</id>
            <phase>none</phase>
        </execution>
        <execution>
            <id>exploded</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>exploded</goal>
            </goals>
        </execution>
    </executions>
</plugin>

<!-- blackduck execution here -->

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <descriptors>
            <descriptor>war-assembly.xml</descriptor>
        </descriptors>
        <appendAssemblyId>false</appendAssemblyId>
    </configuration>
</plugin>

war-assembly.xml:

<assembly>
    <id>war</id>
    <formats>
        <format>war</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}/${project.build.finalName}</directory>
            <outputDirectory>.</outputDirectory>
            <includes>
                <include>/**/*</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>