Provide exactly one of two Maven profiles

I have a Maven project that defines two separate profiles, developer and release (of course, you get a drift here). I want one of these two profiles to be activated at any time, but never both. If both of them are somehow activated, this assembly does not make sense and should fail. If none of them are activated, this assembly also makes no sense and should fail.

I'm sure I can write some custom code for this, and I could have ended up doing it that way, but I would be interested to achieve this using the POM configuration (possibly using existing plugins from Maven Central).

You need to activate plugins with -P ( --activate-profiles ), so <activation> through properties will not be a valid solution. Solutions using activeByDefault are also invalid, since activeByDefault usually known as a trap, unreliable (and we can actually activate other profiles, thereby making activateByDefault unusable).

Your suggestions are greatly appreciated.

+7
maven maven-profiles
source share
5 answers

The simplest solution to this kind of problem would be to use the maven-enforcer-plugin , which definitely has the rule to force at least one of two or more profiles to be activated.

Unfortunately, requireActiveProfile is currently a bug . But at present, preparations are underway for a new release that solves this problem.

+2
source share

I always issue the build command like this:

 mvn package -P-dev,prod 

It explicitly disables the dev profile and allows you to create it. As far as I know, you cannot conditionally enable one assembly profile if the other is active (which is a bit unsuccessful), and because of this, you cannot guarantee that the profiles are mutually exclusive.

+3
source share

I had a similar need (i.e. for mutual exclusivity of two profiles) and was solved by considering two target profiles as internal profiles that should not be indicated on the command line: instead, the property of the control system can be specified or not. For example. Suppose you want the dev profile to be active by default. Then we can activate / deactivate the corresponding internal profiles based on whether the -Drelease option is -Drelease as follows:

 <!-- Internal profile: FOR INTERNAL USE ONLY - active if -Drelease is *not* specified. --> <profile> <id>internal-dev</id> <activation> <!-- Activation via *absence* of a system property to ensure mutual exclusivity of this profile with internal-release --> <property> <name>!release</name> </property> </activation> ... </profile> <!-- Internal profile: FOR INTERNAL USE ONLY - active if -Drelease *is* specified. --> <profile> <id>internal-release</id> <activation> <!-- Activation via *presence* of a system property to ensure mutual exclusivity of this profile with internal-dev --> <property> <name>release</name> </property> </activation> ... </profile> 
+3
source share

I needed a slightly more advanced version of this rule. I ended up writing myself. I sent a patch for them, which includes the following 2 rules:

  • The ability to specify a set of mutually exclusive profiles (p1, p2: p1, p3 means that p1 cannot be active with either p2 or p3).

  • Ability to ban profiles (opposite requireActiveProfile ). p1, p2 means that neither p1 nor p2 can be active for this assembly.

Both of these rules support wildcards and also take into account legacy profiles. They are built on v1.4 rules.

http://jira.codehaus.org/browse/MENFORCER-225

+1
source share

This can still be done using the Maven Enforcer Plugin.

Although the mutual exception, <requireActiveProfile>...<all>false</all>... wrong, as @khmarbaise reported, there is still a built-in <evaluateBeanshell/> rule that allows you to do whatever it wants.

I wrote specifically for this case: XOR of two profiles. Hope this helps.

  <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.4.1</version> <executions> <execution> <id>enforce-PROFILE_ONE-XOR-PROFILE_TWO-is-active</id> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <requireActiveProfile> <profiles>PROFILE_ONE,PROFILE_TWO</profiles> <all>false</all> </requireActiveProfile> <evaluateBeanshell> <condition><![CDATA[ // ensure PROFILE_ONE XOR PROFILE_TWO print("Checking if only one of PROFILE_ONE and PROFILE_TWO profiles is active ..."); boolean profile1 = false, profile2 = false; for(s: "${project.activeProfiles}".replaceAll("\\[?\\s?Profile \\{id: (?<profile>\\w+), source: \\w+\\}\\]?", "${profile}").split(",")) { if("PROFILE_ONE".equalsIgnoreCase(s)){ profile1 = true;} if("PROFILE_TWO".equalsIgnoreCase(s)){ profile2 = true;} } print("PROFILE_ONE XOR PROFILE_TWO: "+(profile1 != profile2)); return profile1 != profile2; ]]></condition> </evaluateBeanshell> </rules> <failFast>true</failFast> </configuration> </execution> </executions> </plugin> 

The tricky part is the active profile cycle, which I have already done here. If you need, you can expand it to more than two profiles. But you have to write a long xor expression, since beanshell does not implement the Java xor ^ operator.

0
source share

All Articles