开发者

Activation of maven profile based on multiple properties

开发者 https://www.devze.com 2023-02-19 16:07 出处:网络
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 (Develo

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 woul开发者_Go百科d 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?


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.


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 ...


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>


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. :(


I believe you can do something like this

<properties>
        <env>dev</env>
        <location>North Pole</location>
    </properties>

<profiles>
        <!-- dev North Profile -->
        <profile>
            <id>dev North Pole</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <!-- qa North Profile -->
        <profile>
            <id>qa North Pole</id>
            <properties>
                         <env>qa</env>
                             <location>North Pole</location>
            </properties>
        </profile>

    </profiles>
<build>
do profile specific stuff here
</build>

Of couse, to activate a profile you can add in the command '-P=dev North Pole'


After an exhaustive investigation I've posted a video where I explain the usage of Maven profiles per environment with Spring Boot. That is a spring boot rest project that handle the application properties per environment using Maven profiles.

Here are the links:

Youtube: https://youtu.be/UbDpvh3YvDw

Github: https://github.com/carlosCharz/mavenprofilespringboot

Code snippet:

Application parameters

custom.server_url = @custom.server_url@

custom.server_port = @custom.server_port@

custom.debuggable = @custom.debuggable@

custom.image_quality = HIGH

Overrides parameters

custom.server_url = api-dev.yourserver.com

custom.server_port = 80

custom.debuggable = true

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.wedevol</groupId>
<artifactId>mvnspringboot</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<name>Spring Boot Project with Maven</name>
<description>This is a spring boot rest project that handle the application properties per environment using Maven profiles.</description>

<properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
    <!-- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes -->
</parent>

<dependencies>
    <!-- Spring -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>

<!-- Maven profile per environment -->
<profiles>
    <profile>
        <id>local</id>
        <activation>
           <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <overrides.props.file>local.overrides.properties</overrides.props.file>
            <current.profile>local</current.profile>
        </properties>
    </profile>
    <profile>
        <id>dev</id>
        <properties>
            <overrides.props.file>dev.overrides.properties</overrides.props.file>
            <current.profile>dev</current.profile>
        </properties>
    </profile>
    <profile>
        <id>qa</id>
        <properties>
            <overrides.props.file>qa.overrides.properties</overrides.props.file>
            <current.profile>qa</current.profile>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <overrides.props.file>prod.overrides.properties</overrides.props.file>
            <current.profile>prod</current.profile>
        </properties>
    </profile>
</profiles>

<build>
    <finalName>mvnspringboot</finalName>
    <!-- Maven Resources. It handles the copying of project resources to the output directory. -->
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <excludes>
                <exclude>profiles/*</exclude>
            </excludes>
        </resource>
    </resources>
    <!-- Maven filtering. The variables are included in the resources ( ${..} or @...@ delimiters) -->
    <filters>
        <filter>src/main/resources/profiles/${overrides.props.file}</filter>
    </filters>
    <plugins>
        <!-- Spring boot maven plugin -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <!-- Ant plugin to print the current maven profile -->
        <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <executions>
                <execution>
                    <phase>generate-resources</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <tasks>
                            <echo>Current maven active profile: ${current.profile}</echo>
                        </tasks>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Let me know if it worked! Gretings!

0

精彩评论

暂无评论...
验证码 换一张
取 消