Maven Tip: Activating Profiles With Multiple Conditions

When working with Maven profiles, sometimes you need to activate a profile when multiple conditions are true. Although the <activation> element in pom.xml lets you specify more than one condition, the conditions are evaluated with the OR operator rather than the AND operator.

When Maven executes profiles, it executes them in the following manner:

  • Profiles that were specified with the "-P" command line switch, according to their order of appearance in the pom
  • All other profiles that might conditionally activate, such as profiles that activate based on the existence of a file in the current module

Using this knowledge of profile execution, I came up with a way of activating profiles when multiple conditions are true, based on the presence of a temporary file whose name has one or more property values.

HOWEVER... this only works when Maven is executed in a directory that contains a parent pom. It does not work in a sub-module (like a war project), because the temporary file is created after all of the profiles have been activated.

Example: Only include Xerces as a dependency for portlet WAR projects that are to be deployed on WebLogic:

<profiles>
    <!-- The following profile must appear before other profiles -->
    <!-- and is activated only when WEB-INF/portlet.war is found -->
    <profile>
        <id>activate-portlet-war</id>
        <activation>
            <file>
                <exists>src/main/webapp/WEB-INF/portlet.xml</exists>
            </file>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <executions>
                        <execution>
                            <phase>generate-resources</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <target>
                                    <touch file="target/${app.server.type}-portlet-war-activation.tmp" />
                                </target>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
    <!-- The following profile is activated with "-P weblogic" on the command line -->
    <profile>
        <id>weblogic</id>
        <properties>
            <app.server.type>weblogic</app.server.type>
        </properties>
    </profile>
    <!-- The following profile is activated only for weblogic portlet wars -->
    <profile>
        <id>weblogic-portlet-war</id>
        <activation>
            <file>
                <exists>target/weblogic-portlet-war-activation.tmp</exists>
            </file>
        </activation>
        <dependencies>
            <dependency>
                <groupId>xerces</groupId>
                <artifactId>xercesImpl</artifactId>
                <version>2.11.0</version>
            </dependency>
        </dependencies>
    </profile>
</profiles>

This is an approach that can be used in Maven 2/3. Perhaps MNG-4565 will be implemented as a feature in some future version of Maven.