Search code examples
mavenpom.xmlmulti-modulemaven-profiles

Maven - Child Module Profiles


Problem

I have a maven project that has a similar structure to the following one:
(simplified for explanation purposes)

--parent
    |-- child A (inherits from parent)
    |-- child B (inherits from parent)
          |-- child B1 (inherits from B)
          |-- child B2 (inherits from B)
          |-- child B3 (inherits from B)

Solely the children B1 and B2 have to be built using a certain profile that includes some extra build stuff. By consequence the profile has been specified in module B.

Logically the modules belong to module B and additionally inherit some dependencies etc. (aggreagtion + inheritance).
(imagine something like B = Frontend, B1 = UI, B2 = Themes, B3 = Something else)


Question

  • Is there a possibility to still use a full build from the parent pom and activate the according profile only in the correct children? (would be my favorite solution)
  • Or do I need separate builds using advanced reactor options (-pl, etc.)?
  • Or is there a completely other approach for such scenarios?

Edit

Edit as the question was identified as duplicate: The problem is that the solution mentioned in the according question does not work.

If I activate the sub profile by using a property, it will be activated as well for module B (the parent), and for ALL children.

I only want it to be active for child B1 and B2.


Solution

  • If you want to have a profile which should be applied to sub-modules (and only some of them), defined in a centralized way in their parent project (pom) and yet not apply the profile to the parent itself, here is a proposed approach:

    Define the profile in the parent pom, sample one:

    <profiles>
        <profile>
            <id>sample-profile</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-antrun-plugin</artifactId>
                        <version>1.5</version>
                        <executions>
                            <execution>
                                <id>print-hello</id>
                                <phase>${phase.prop}</phase>
                                <goals>
                                    <goal>run</goal>
                                </goals>
                                <configuration>
                                    <target>
                                        <echo message="hello there!" />
                                    </target>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
    

    Note what we are doing:

    • the plugin phase element is parametrized, so the binding of the plugin to a build phase will also be parametrized
    • We can now decide via property to which phase attach this plugin execution
    • We can now decide via property to attach this plugin execution to no phase (or empty phase)

    So, in the same parent pom, let's define the property:

    <properties>
        <phase.prop>none</phase.prop>
    </properties>
    

    As such, the build running on the parent pom will attach the plugin execution to no phase (none is not a keyword or known-value, just a de-fact standard used for a non existing phase, you could leave it empty or put it any value you like, it would have the same effect) and hence skip it. It will also be skipped by default in all the declared modules. The profile will still be active in every module, but would be harmless since it would not execute any plugin by default.

    Then, in modules where you want the plugin executions to be active you could re-define only the concerned property and the required phase:

    <properties>
        <phase.prop>package</phase.prop>
    </properties>
    

    When then activating the profile from the main build (the parent)

    mvn clean install -Psample-profile
    

    The parent will apply it to all modules, but the effective profile execution will only occur where the phase.prop value has a maven-meaningful value.

    If you need to have different phases for different plugin executions, then you could define more than one property and apply the same pattern.

    If you don't have a plugin execution but rather a global plugin configuration for a plugin already executed by Maven (as part of its packaging and default build), you could then re-define its execution overriding the default execution id.

    Note that we could have done the same using the skip configuration element, but:

    • not all plugins provide the skip configuration entry
    • using the phase element is not related to any configuration and can be reused for executions attached to the same phase