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

ShinySpiderdude
  • 1,170
  • 4
  • 14
  • 18

4 Answers4

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>
Stagr.Lee
  • 73
  • 6
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.

Community
  • 1
  • 1
Mrkvozrout
  • 314
  • 1
  • 9
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.

Community
  • 1
  • 1
Guillaume Darmont
  • 5,002
  • 1
  • 23
  • 35
  • This behaves exactly the same. that is, if i do NOT have the following in my pom: hello then this works.. however, if i DO have this, then i will get "hello" instead of "myDynamicValue". I want this to work in both scenarios – ShinySpiderdude Jul 02 '13 at 13:45
  • Hmm... Then the solution I see is using ``. Try to configure a profile with default properties and another that will configure properties dynamically. – Guillaume Darmont Jul 02 '13 at 14:53
  • But how can i have a profile load properties dynamically (from a properties file, for instance) and use those instead of the default ones? – ShinySpiderdude Jul 02 '13 at 15:41
  • 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. – fiddle Sep 14 '17 at 06:35
  • @GuillaumeDarmont can you please have a look at my question, I'm stuck: https://stackoverflow.com/questions/49937870/how-to-set-project-version-in-maven-at-build-time – xbmono Apr 20 '18 at 11:56
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.

Community
  • 1
  • 1
Cipous
  • 952
  • 7
  • 19