How to exclude a module from a Maven reactor build?

Maven 2Maven

Maven 2 Problem Overview


We have a Maven 2 project with lots of modules in it. Example:

<modules>
  <module>common</module>
  <module>foo</module>
  <module>data</module>
  <module>bar</module>
  ... more ...
</module>

Let's say the "data" module is time consuming to build and we want to exclude it when the project is build by a CI server. Currently we use two pom.xml files to achieve this. One has all modules in it and the other one has all modules except the ones which can be left out for CI. But that's pretty annoying because sometimes we forget to put a new module into both files.

Is there a solution which doesn't need two separate module lists?

Maven 2 Solutions


Solution 1 - Maven 2

With Maven 3.2.1, you can now use -pl !<module_name>,!<module_name> to exclude certain modules from the reactor build.

See this feature request: https://issues.apache.org/jira/browse/MNG-5230

Solution 2 - Maven 2

The easiest might be to use profiles like this:

<project>
  ...
  <modules>
    <module>common</module>
    <module>foo</module>
    <module>bar</module>
  <modules>
  ...
  <profiles>
    <profile>
      <id>expensive-modules-to-build</id>
      <modules>
        <module>data</module>
      </modules>
    </profile>
  </profiles>
</project>

You should then check out ways you can activate profiles

Solution 3 - Maven 2

The projects to build can also be specified on the mvn command line. This would remove the need for a separate pom, but instead you would have to change the CI configuration everytime there is a new module.

-pl,--projects <arg>                Comma-delimited list of specified
                                    reactor projects to build instead
                                    of all projects. A project can be
                                    specified by [groupId]:artifactId
                                    or by its relative path.

Maybe a combination of this flag and --also-make-dependents or --also-make would reduce this maintenance burden again.

-am,--also-make                     If project list is specified, also
                                    build projects required by the
                                    list
-amd,--also-make-dependents         If project list is specified, also
                                    build projects that depend on
                                    projects on the list

Solution 4 - Maven 2

I assume you want the default build to always build everything, regardless of speed, so that new developers can get started quickly without having to understand lots about the POM. You can use profiles like this:

<modules>
    <module>common</module>
    <module>foo</module>
    <module>bar</module>
  </modules>
  ...
  <profiles>
    <profile>
      <id>expensive-modules-to-build</id>
      <activation>
         <activeByDefault>true</activeByDefault>
      </activation>
      <modules>
        <module>data</module>
      </modules>
    </profile>
  </profiles>
</project>

The problem with this is that if a developer specifies another profile on the command line, then the expensive-modules-to-build isn't included (unless the developer also specifies it). This makes it complicated to remember which profiles need to be included.

Here is a hacky way around that. Both profiles are always included, because the pom.xml file always exists. So to exclude the expensive modules, you can use -P!full-build on the command line.

<profiles>
	<profile>
		<id>full-build</id>
		<activation>
			<file>
				<exists>pom.xml</exists>
			</file>
		</activation>
		<modules>
			<module>data</module>
		</modules>
	</profile>
	<profile>
		<id>short-build</id>
		<activation>
			<file>
				<exists>pom.xml</exists>
			</file>
		</activation>
		<modules>
		   <module>common</module>
		   <module>foo</module>
		   <module>bar</module>
		</modules>
	</profile>
</profiles>

Solution 5 - Maven 2

Another idea: Reactor modules can be nested, so it should be possible to group your fast and slow-building modules into separate poms and then add another aggregator pom containing these two as modules. Your CI Server could then only reference the pom containing the fast building modules.

<artifactId>fast</artifactId>
<modules>
    <module>fast-a</module>
    <module>fast-b</module>
    <module>fast-c</module>
</module>

<artifactId>all</artifactId>
<modules>
    <module>fast</module>
    <module>slow</module>
</module>

Solution 6 - Maven 2

You could be to use maven profiles. In our build environment, we created a profile quick that disables many plugins and test execution.

This is done by

	<profile>
		<id>quick</id>
		<properties>
			<skipTests>true</skipTests>
			<!-- others... -->
		</properties>	
		<build>
			<plugins>
			     <!-- configuration... -->
			</plugins>
		</build>
	</profile>

And then we invoke maven the following way

mvn groupId:artifactId:goal -P quick

You could maybe disable compilation and other standard plugins in the pom of your module to speed it up.

Solution 7 - Maven 2

Not exactly the answer these folks were asking for. My situation was I wanted to deploy only the parent pom. I'm using the spring-boot-thin-layout in a child module. This requires the parent module be deployed into artifactory. I added the following into my project. It enables skipping of install and/or deploy phase.

In my parent pom:

<properties>
    <disable.install>true</disable.install>
    <disable.deploy>true</disable.deploy>
    <enable.deployAtEnd>true</enable.deployAtEnd>
</properties>

<profiles>
    <profile>
        <id>deploy-parent</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <disable.install>true</disable.install>
            <disable.deploy>true</disable.deploy>
            <deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
        </properties>
        <build>
            <finalName>${project.version}</finalName>
        </build>
    </profile>
</profiles>

And the in my child pom(s) or any module you don't want deployed with parent:

<properties>
    <maven.install.skip>${disable.install}</maven.install.skip>
    <maven.deploy.skip>${disable.deploy}</maven.deploy.skip>
    <deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
</properties>

So effectively when I run mvn deploy on the parent pom, it will compile all the modules, not run install on anything, and then at the end deploy any module not having <maven.deploy.skip>${disable.deploy}</maven.deploy.skip> in it's properties. So in my case only deploying the parent.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkayahrView Question on Stackoverflow
Solution 1 - Maven 2Yogesh_DView Answer on Stackoverflow
Solution 2 - Maven 2SaMView Answer on Stackoverflow
Solution 3 - Maven 2Jörn HorstmannView Answer on Stackoverflow
Solution 4 - Maven 2artbristolView Answer on Stackoverflow
Solution 5 - Maven 2Jörn HorstmannView Answer on Stackoverflow
Solution 6 - Maven 2Nr9View Answer on Stackoverflow
Solution 7 - Maven 2ranma2913View Answer on Stackoverflow