maven change properties on the fly (runtime)
Asked Answered
J

5

5

I am having the following problem: I want to be able to change maven properties on the fly using a plugin. for instance if i have a property configured such as:

<properties>
   <someProperty>value</someProperty>
</properties>

i want to have a way to change it to "value-2" during the maven run itself (not before! for instance, i do not want to use -DsomeProperty=value-2 at command line)

I will try to explain my use case to clarify: My pom.xml has some default properties set. However, i am running a task that creates a property file with name=value pairs to match my properties (for instance, if i have a property such as someProperty=value in my pom.xml the run.properties file has someProperty=value-2 property). during some maven run i would like to pass it the location of my properties file and have it change the default properties in my pom.xml. I have tried using the "properties-maven-plugin" to achieve this goal but this only seems to work if i do not have the property configured in the pom.xml itself. That is, if the section in my pom.xml does not have the "someProperty" property then the change works successfully. If i do have it, however then no change is made and i want to be able to change it even if some property is defined in the pom.xml

Any suggestions? thanks in advance

Jenjena answered 2/7, 2013 at 12:29 Comment(0)
D
4

I've been playing with gmavenplus-plugin which replaces the older gmaven-plugin. In this example, I'm trying to conditionally direct the upload of docker images to either a SNAPSHOT and RELEASE docker registry similar to how the maven-deploy-plugin works. With this code, I parse the version and set a property pointing to the correct repo. Once you get into groovy you can mess around with maven like you are a regular java implemented maven plugin.

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>1.10</version>
    <executions>
      <execution>
        <id>parse-version</id>
        <goals>
          <goal>parse-version</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

  <plugin>
    <groupId>org.codehaus.gmavenplus</groupId>
    <artifactId>gmavenplus-plugin</artifactId>
    <version>1.5</version>
    <dependencies>
      <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.4.4</version>
        <scope>runtime</scope>
      </dependency>
      <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.0.13</version>
        <scope>runtime</scope>
      </dependency>
    </dependencies>
    <executions>
      <execution>
        <id>add-dynamic-properties</id>
        <phase>initialize</phase>
        <goals>
          <goal>execute</goal>
        </goals>
        <configuration>
          <scripts>
            <script>
<![CDATA[
import java.text.SimpleDateFormat;

Date now = new Date()
SimpleDateFormat timestamp = new SimpleDateFormat("yyyyMMdd.HHmmss");

myver  = "${project.version}"
myqual = "${parsedVersion.qualifier}"
myrepo = (myqual == "SNAPSHOT") ? "${docker.repo.snapshot}" : "${docker.repo.release}"
mytag  = (myqual == "SNAPSHOT") ? myver + "-" + timestamp.format(now) : myver

project.properties.setProperty('docker.repo.name', myrepo)
project.properties.setProperty('docker.image.tag', mytag) 

log.info("Docker repository name is " + project.properties['docker.repo.name'])
log.info("Docker image tag is " + project.properties['docker.image.tag'])
]]>
            </script>
          </scripts>
        </configuration>
      </execution>
    </executions>
  </plugin>
Darees answered 1/3, 2016 at 18:56 Comment(2)
Wow, java code in XML. I feel like it would be easier to just write a small Maven plugin and attach it to lifecycle. You could even unit-test it too.Redo
Java plugin is a much better approach.Darees
T
3

As you found out, you cannot use dynamically changed value of property defined in POM's properties section. If you want to know why, read this answer to the end.

In order to use dynamic values and default values you have to set default values dynamically. You can use GMaven plugin for this and configure it probably as a first plugin in build. See Guillaume Darmont's answer.

And here is the explanation why this is needed. Maven replaces property values two times:

  1. at the beginning (probably during assembling of effective POM) it replaces static properties (declared in properties sections)
  2. before each run of a plugin it replaces properties again so dynamic values used now

What the above means is that if you have static declaration <myProperty> and later you use this property like ${myProperty} the value is injected before you have a chance to dynamicaly change it. Later you can dynamicaly change the value but the placeholder is already replaced so the dynamic value is nowhere to be injected.

I also answered this behavior here, maybe it is better explained there for someone.

Treasatreason answered 18/11, 2014 at 18:19 Comment(1)
thanks, it was driving me crazy, because for what ever reason, it was working in another project.Gefell
S
2

I don't know if I fully understand your question, but you could try the Groovy Maven Plugin

<plugin>
    <groupId>org.codehaus.groovy.maven</groupId>
    <artifactId>gmaven-plugin</artifactId>
    <version>1.4</version>
    <executions>
      <execution>
        <id>add-dynamic-properties</id>
        <phase>initialize</phase>
        <goals>
          <goal>execute</goal>
        </goals>
        <configuration>
          <source>
            if (someCondition) {
                project.properties.myDynamicProperty = 'myDynamicValue'
            }
          </source>
        </configuration>
      </execution>
    </executions>
  </plugin>

Then, simply use ${myDynamicProperty}.

Hope this helps.

Sirkin answered 2/7, 2013 at 13:19 Comment(5)
This behaves exactly the same. that is, if i do NOT have the following in my pom: <properties> <prop>hello</prop> </properties> then this works.. however, if i DO have this, then i will get "hello" instead of "myDynamicValue". I want this to work in both scenariosJenjena
Hmm... Then the solution I see is using <profiles>. Try to configure a profile with default properties and another that will configure properties dynamically.Sirkin
But how can i have a profile load properties dynamically (from a properties file, for instance) and use those instead of the default ones?Jenjena
instead of stringUtils is it possible to call a method of a class in the same project? I am getting unable to resolve class error.Mind
@GuillaumeDarmont can you please have a look at my question, I'm stuck: #49938370Jeanejeanelle
C
1

this works for me

exept I had to change property to different name:

<source>
    import org.apache.commons.lang.StringUtils;
    project.properties["my.enc"] = StringUtils.lowerCase(project.properties["db_user_base.enc"]);
</source>

Because with same name it did not work - value was not overwritten.

Confession answered 23/10, 2014 at 21:28 Comment(0)
D
0

Another option is write a property file from one plugin - like the exec-maven-plugin - execution and then to read this property file via the properties-maven-plugin. For .e.g:

<build>
  <plugins>
    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <executions>              
          <execution>
            <id>write-some-file</id>
            <phase>pre-integration-test</phase>
            <configuration>
              <execuble>cmd</executable>
              <arguments>
                <argument>/c</argument>
                <argument>${project.basedir}\src\test\bin\some-batch-file-writing-file.bat</argument>
                <!-- Sample argument indicating name and path of property file to be generated-->
                <argument>${project.basedir}\target\classes\generated-file.properties</argument>
              </arguments>
            </configuration>
            <goals>
              <goal>exec</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>properties-maven-plugin</artifactId>
        <executions>
          <execution>
            <id>read-some-file</id>
            <phase>pre-integration-test</phase>
            <goals>
              <goal>read-project-properties</goal>
            </goals>
            <configuration>                 
              <files>
                <file>${project.basedir}/target/classes/generated-file.properties</file>
              </files>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
</build>
Desk answered 15/11, 2023 at 9:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.