Activation of maven profile based on multiple properties

34,164

Solution 1

why not using profile directly like:

<profiles>
   <profile>
    <id>north-pole</id>
    <activation>
      <activeByDefault>false</activeByDefault>
    </activation>
    ....
  </profile>
   <profile>
    <id>dev</id>
    <activation>
      <activeByDefault>false</activeByDefault>
    </activation>
    ....
  </profile>
</profiles>

Now you can activate the profiles by command line.

mvn -Pdev,north-pole ...

Solution 2

I am afraid there is no good solution to your problem (unless there are new Maven features I am not aware of).

In theory, you could introduce a derived property whose value is concatenated from the two properties you listed. However, the problem is that profiles are evaluated before properties defined in the pom, so such a derived property can't be used to activate a profile :-(

The best workaround I could think of for a similar problem was to activate the profile explicitly, and put the different combinations of command line parameters into separate batch/script files to make execution simpler and avoid mistyping issues.

Solution 3

Possible Solution

Try this extension: https://github.com/kpiwko/el-profile-activator-extension

This allows to have such syntax:

<profile>
    <id>NOrth Pole DEV</id>

    <activation>
        <property>
            <!-- mvel property name is obligatory -->
            <name>mvel</name>
            <value>isdef location &amp;&amp; location=="NorthPole" &amp;&amp; 
                   isdef environment &amp;&amp; environment=="DEV"</value>
        </property>
    </activation>
</profile>

I did not try it myself, but seems to be a nice project.

How to avoid manual configuration of Maven

You need to put the needed two jars of the project into $MAVEN_HOME/lib/ext. You can however automize configuring them. Like this:

  • You can add a profile which is activated on absense of $MAVEN_HOME/lib/ext/el-profile-activator-extension.jar file
  • This profile can download the jars from maven using dependency plugin into the $MAVEN_HOME/lib/ext folder in init phase
  • Then you can write out a message, that the build configured the maven folder, and the next build will be successful.

Tested profile:

<profile>
    <id>prepare-maven-extended-libs</id>
    <activation>
      <file>
        <missing>${maven.home}/lib/ext/el-profile-activator-extension.jar</missing>
      </file>
    </activation>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.8</version>
                <executions>
                    <execution>
                        <id>copy</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>com.redhat.jboss.maven</groupId>
                                    <artifactId>el-profile-activator-extension</artifactId>
                                    <version>1.0.0-SNAPSHOT</version>
                                    <type>jar</type>
                                    <overWrite>true</overWrite>
                                    <outputDirectory>${maven.home}/lib/ext</outputDirectory>
                                    <destFileName>el-profile-activator-extension.jar</destFileName>
                                </artifactItem>
                                <artifactItem>
                                    <groupId>org.mvel</groupId>
                                    <artifactId>mvel2</artifactId>
                                    <version>2.1.3.Final</version>
                                    <type>jar</type>
                                    <overWrite>true</overWrite>
                                    <outputDirectory>${maven.home}/lib/ext</outputDirectory>
                                    <destFileName>mvel2.jar</destFileName>
                                </artifactItem>
                            </artifactItems>
                            <outputDirectory>${project.build.directory}/wars</outputDirectory>
                            <overWriteReleases>true</overWriteReleases>
                            <overWriteSnapshots>true</overWriteSnapshots>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.gmaven</groupId>
                <artifactId>gmaven-plugin</artifactId>
                <version>1.4</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals><goal>execute</goal></goals>
                    </execution>
                </executions>
                <configuration>
                    <source>
                        fail("For profile activation we use an extension jar. It is now in your ${maven.home}/lib/ext folder. Please restart the build, and then it will be successful.")
                    </source>
                </configuration>
            </plugin>               
        </plugins>
    </build>
</profile>

Solution 4

khmarbaise's answer seems more elegant to me. To Jan's comment, you can refer to the file by appending the properites e.g. with profile dev, North Pole activated you can refer to NorthPole-dev.xml with ${location}-${env}.xml.

I had to post another reply as I'm not able to add comments to other's replies. :(

Share:
34,164
Jan Zyka
Author by

Jan Zyka

Java developer

Updated on May 02, 2020

Comments

  • Jan Zyka
    Jan Zyka about 4 years

    I am creating a maven 2 build for a project and I came up with profiles since the build has to be created for both different locations (say Berlin, Paris, North Pole) and different environment (Development, Production). Those are specified via properties. So for "North Pole" "DEV" I do:

    -Dlocation=NorthPole -Denvironment=DEV
    

    Now I would like to acivate my porfile based on both these properties, not just one. So I tried following:

    <profiles>
      <profile>
        <id>NOrth Pole DEV</id>
        <activation>
          <property>
            <name>location</name>
            <value>NorthPole</value>
          </property>
          <property>
            <name>environment</name>
            <value>DEV</value>
          </property>
        </activation>
        ... <!-- Set some North Pole DEV specific stuff -->
      </profile>
    </profiles>
    

    This doesn't work, maven expect to see at most one <property> element there.

    Please note I have another use for the properties as well so making it single property locationEnvof value NorthPole-DEV isn't what I want to have.

    So is there any way or workaround or whatever else how to activate an profile based on combination of properties?

  • Jan Zyka
    Jan Zyka over 13 years
    Hm, but this is for the case there is North Pole only. In such case I wouldn't need a property for it at all. right? :) There are other locations as well sa described in the question.
  • Prabhjot
    Prabhjot over 13 years
    Yes, you can add other profiles as per your requirement.Essentially, location and env properties are being set as per the profile selected, thus you won't need a separate properties file.
  • Jan Zyka
    Jan Zyka over 13 years
    Sure but if I have config file NorthPole-DEV.xml and NorthPole-PROD how would I know which one to use in your scenario? I need to decide based on both location and environment and act upon them
  • Sean Patrick Floyd
    Sean Patrick Floyd over 13 years
    well, you could have added this to your first answer instead :-)
  • Jan Zyka
    Jan Zyka over 13 years
    Since I was converting the ANT build into maven I probably was too fixed on using commandline properties. It turned out that it is really better to do it via profiles, set required properties in them and forget the properties at all. Sorry for missleading question. Marking this as correct answer.
  • Jan Zyka
    Jan Zyka over 13 years
    You are right, it turned out that going directly with profiles and set the properties in them (just as if they were set via commandline) will be the best option here. Thanks for answer anyway!
  • Ivaylo Slavov
    Ivaylo Slavov about 12 years
    Could you clarify what should be expected if the 2 profiles define different values for the same property? Which one is taken?
  • woky
    woky almost 12 years
    That does not solve the problem because second property will trigger the profile even thought first is not set (it matters in my case). -1 for typical useless Maven advice (eg. "do it Maven way and make everything dumb, bloated & unmaintainable").
  • khmarbaise
    khmarbaise over 7 years
    @worky If you are the opinion is is useless than you should improve maven in a way you think it would be better.
  • rogerdpack
    rogerdpack about 6 years
    example might be nice... :)
  • Zack
    Zack almost 6 years
    Op's question is not spring-boot related