While working on my TDD book, I played with Maven profiles to write the chapter.
If you use Maven profiles, you might want to use an activation strategy to enable the profile under certain circumstances automatically. There’s also a particular option, “<activeByDefault>”, which seems self-explanatory. This must mean that that profile will be constantly active by default unless you explicitly disable it, e.g., with “-P!profileid”.
Here’s a possible minimal example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.examples</groupId> <artifactId>example-profiles</artifactId> <version>1.0-SNAPSHOT</version> <profiles> <profile> <id>notReallyActiveByDefault</id> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> </profiles> </project> |
By using the maven-help-plugin‘s goal “active-profiles,” we can verify that:
1 2 3 4 5 6 7 |
mvn help:active-profiles ... Active Profiles for Project 'com.examples:example-profiles:jar:1.0-SNAPSHOT': The following profiles are active: - notReallyActiveByDefault (source: com.examples:example-profiles:1.0-SNAPSHOT) |
Unfortunately, this will probably never work as we expect. For example, let’s add another profile (without any activation strategy in this example):
1 2 3 4 5 |
... <profile> <id>anotherProfile</id> </profile> ... |
If we explicitly enable such a profile, we’d expect the previous one is still “active by default”, but we have a terrible surprise:
1 2 3 4 5 6 7 |
mvn help:active-profiles -PanotherProfile ... Active Profiles for Project 'com.examples:example-profiles:jar:1.0-SNAPSHOT': The following profiles are active: - anotherProfile (source: com.examples:example-profiles:1.0-SNAPSHOT) |
As it is documented (https://maven.apache.org/guides/introduction/introduction-to-profiles.html):
This profile will automatically be active for all builds unless another profile in the same POM is activated using one of the previously described methods. All profiles that are active by default are automatically deactivated when a profile in the POM is activated on the command line or through its activation config.
Counterintuitive, but it’s like that, like it or not.
However, the documentation also tells you how to achieve the “really active by default”; it’s a matter of activating the profile when a property is NOT defined. Let’s create another profile following this approach:
1 2 3 4 5 6 7 8 9 10 |
... <profile> <id>reallyActiveByDefault</id> <activation> <property> <name>!skipMe</name> </property> </activation> </profile> ... |
And verify that:
1 2 3 4 5 6 7 8 |
mvn help:active-profiles -PanotherProfile ... Active Profiles for Project 'com.examples:example-profiles:jar:1.0-SNAPSHOT': The following profiles are active: - anotherProfile (source: com.examples:example-profiles:1.0-SNAPSHOT) - reallyActiveByDefault (source: com.examples:example-profiles:1.0-SNAPSHOT) |
The profile we’ve just added will be activated when the system property “skipMe” is not defined. So, it’s really active by default unless you pass to the command line “-DskipMe”.
Note also that the “<activeByDefault>” property is really misleading. In fact, as long as another profile is automatically activated (i.e., not explicitly), the “<activeByDefault>” is useless. In fact, with the profile we’ve just active since it’s really active by default, it also disables, by default, “notReallyActiveByDefault”:
1 2 3 4 5 6 7 |
mvn help:active-profiles ... Active Profiles for Project 'com.examples:example-profiles:jar:1.0-SNAPSHOT': The following profiles are active: - reallyActiveByDefault (source: com.examples:example-profiles:1.0-SNAPSHOT) |
Let’s do some further experiments and add another profile, which is activated when the property “activateMe” is defined:
1 2 3 4 5 6 7 8 |
<profile> <id>activatedByProperty</id> <activation> <property> <name>activateMe</name> </property> </activation> </profile> |
Let’s define the property on the command line, and we get the expected result:
1 2 3 4 5 6 7 8 |
mvn help:active-profiles -DactivateMe ... Active Profiles for Project 'com.examples:example-profiles:jar:1.0-SNAPSHOT': The following profiles are active: - reallyActiveByDefault (source: com.examples:example-profiles:1.0-SNAPSHOT) - activatedByProperty (source: com.examples:example-profiles:1.0-SNAPSHOT) |
We can also refine the activation:
1 2 3 4 5 6 7 8 9 |
<profile> <id>activatedByProperty</id> <activation> <property> <name>activateMe</name> <value>true</value> </property> </activation> </profile> |
If we define that property, the profile will be activated, and if we define that property with another value, it will not be activated (in any case, “reallyActiveByDefault” is still activated):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
> mvn help:active-profiles -DactivateMe ... Active Profiles for Project 'com.examples:example-profiles:jar:1.0-SNAPSHOT': The following profiles are active: - reallyActiveByDefault (source: com.examples:example-profiles:1.0-SNAPSHOT) - activatedByProperty (source: com.examples:example-profiles:1.0-SNAPSHOT) mvn help:active-profiles -DactivateMe=false ... Active Profiles for Project 'com.examples:example-profiles:jar:1.0-SNAPSHOT': The following profiles are active: - reallyActiveByDefault (source: com.examples:example-profiles:1.0-SNAPSHOT) |
REMEMBER: You CANNOT activate that profile by defining a property in the POM, though:
1 2 3 |
<properties> <activateMe>true</activateMe> </properties> |
If you want, you can temporarily switch the activation with a negated property, similar to what we’ve done before:
1 2 3 4 5 6 7 8 9 10 11 12 |
<profile> <id>activatedByProperty</id> <activation> <property> <!-- temporarily enabled by default. TODO: remember to change it back to <name>activateMe</name> --> <name>!reallySkipMe</name> </property> </activation> </profile> |
And verify the expected result:
1 2 3 4 5 6 7 8 |
mvn help:active-profiles ... Active Profiles for Project 'com.examples:example-profiles:jar:1.0-SNAPSHOT': The following profiles are active: - reallyActiveByDefault (source: com.examples:example-profiles:1.0-SNAPSHOT) - activatedByProperty (source: com.examples:example-profiles:1.0-SNAPSHOT) |
That’s the complete example of POM:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.examples</groupId> <artifactId>example-profiles</artifactId> <version>1.0-SNAPSHOT</version> <profiles> <profile> <id>notReallyActiveByDefault</id> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <id>anotherProfile</id> </profile> <profile> <id>reallyActiveByDefault</id> <activation> <property> <name>!skipMe</name> </property> </activation> </profile> <profile> <id>activatedByProperty</id> <activation> <property> <name>activateMe</name> </property> </activation> </profile> </profiles> </project> |
However, please remember not to abuse profiles, or the build will easily become hard to maintain.