1

In my POM, I have:

<properties>
    <custom.properties>
        ${basedir}/src/main/props/${environment}-${flavor}.properties
    </custom.properties>
</properties>

Where environment and flavor can be provided at command line:

mvn clean install -Denvironment=test -Dflavor=guest

And inside the maven-resources plugin definition, I have:

<filters>
    <filter>${basedir}/src/main/props/base.properties</filter>
    <filter>${custom.properties}</filter>
</filters>

If the file created by ${environment}-${flavor}.properties doesn't exist, can I define a fallback, or ignore it completely? Maven will currently throw an error.

I'd rather not have to create a dummy file for every possible combo of environment and flavor.

Thanks.

Matt
  • 23,363
  • 39
  • 111
  • 152
  • is your problem only that `maven-resources-plugin` throws an error for non-exsitent file? Do you need to define filtering exactly like in your question? – pirho Jan 03 '18 at 18:27
  • I’m open to suggestions for how to do my filtering differently. There are about 5 environments and 2 flavors, any combination of which could need specific properties that override the defaults in `base.properties`. My root POM sets default values for the 2 properties, and there are many child modules that will use the POM setup from my question. Some may need to define props for a unique environment-flavor combo that others may not. I just don’t want to have to create dummy files in each module for every possible combo. – Matt Jan 03 '18 at 18:38

2 Answers2

1

Leave only the base.properties in to the default <build /> section

<build>
   <filters>
      <filter>src/main/props/base.properties</filter>            
   </filters>
</build>

Add the custom property file to filters in a profile that is activated by the existence of this custom property file, like

<profiles>
   <profile>
      <activation>
         <file><exists>src/main/props/${custom.properties}</exists></file>
      </activation>
      <build>
         <filters>
            <filter>src/main/props/${custom.properties}</filter>
         </filters>         
      </build>
   </profile>
</profiles>

Problem with this approach is that there can not be any working default values for environment & flavor in main <properties />. It seems to cause <exists/> in profile activation think that file exists even the properties are changed when invoked from command line.

For this problem I suggest to have all the default data in base properties if possible.

pirho
  • 11,565
  • 12
  • 43
  • 70
  • It seems that when base.properties is set in pluginManagement the custom props do not correctly override the abase props so i removed that part from my edit. – pirho Jan 03 '18 at 19:46
  • This nearly solves it. But unfortunately, per Maven documentation, the only properties available for use in the `` tag are ones provided at command line, and `${baseDir}`. So the `${custom.properties}` property that the POM creates will not be available for use there. – Matt Jan 03 '18 at 19:55
  • @MattPowell Well, it anyway is working for me fine both from my eclipse and mvn cmd-line... Maybe I then misunderstood your problem? Did you try it on a cmd-line and if what error you got? – pirho Jan 03 '18 at 20:19
  • I’ve tried from command line, but it seems to ignore the `environment` and `flavor` properties that I’ve defaulted in my root POM to `test` and `guest`, respectively. When I do `mvn clean install`, it does not use the `test-guest.properties` file that I’ve created, and instead uses the `base.properties` file. Again, per Maven’s documentation, properties you’ve defined in a `` section can’t be used in the `` tag. It seems like a terrible limitation, and I’m not sure how it’s working for you. See the **file** bullet here: https://maven.apache.org/pom.html#Activation – Matt Jan 03 '18 at 20:51
  • @MattPowell Ok, for me it actually works also so that if I define in `` some default env&flavour it then requires any cmd-lin params to be valid also so file must exists. But: without default props it works fine. So either uses only base props OR overrides base props with valid custom prop file. But should there be any default props for custom props? Should they then be base props taht maybe then are overridden? – pirho Jan 03 '18 at 21:06
  • I’ll have to try it with a fresh project to test just this functionality, if it’s working for you this way. You’re right that defaults should probably be in `base.properties`, but it turns out my test environment, which I wanted to be default, is the odd one out: most other environments are the same. So if I were to make `base.properties` the default test environment props, I’d have to create files for each of my remaining environments, all of which would be nearly the same, just to override the defaults. I’d hoped to have `base.properties` be the majority, and override with default props. – Matt Jan 03 '18 at 21:34
  • No, this still does not work for me. Defining `${custom.properties}` in the `` section of the POM, then attempting to use that property inside the `` tag, does not work. It's not recognized. – Matt Jan 04 '18 at 17:18
0

This is somewhat untested, however I've used the properties-maven-plugin for a similar use case where I want to load a file that may or may not exist. Might not be a totally working answer, but I hope it gives you ideas.

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>properties-maven-plugin</artifactId>
  <version>1.0.0</version>
  <executions>
    <execution>
      <id>load-filters</id>
      <phase>initialize</phase>
      <goals>
        <goal>read-project-properties</goal>
      </goals>
      <configuration>
        <files>
          <file>${basedir}/src/main/props/${environment}-${flavor}.properties</file>
        </files>
        <quiet>true</quiet>  <!-- important! -->
      </configuration>
    </execution>
  </executions>
</plugin>

The "quiet" part tells the plugin not to fail the build if the file doesn't exist; it will simply log a message and move on. If the file exists, the properties are loaded as Project properties.

When the resources plugin executes, it filters using

System properties, project properties, and filter properties files specified in the POM build/filters section

so the properties will be applied to the resources without any further config. You won't need to specify <filters> in the resources plugin.

The above covers the 'ignore' case. It may get a little trickier if you want to provide a fallback. I am not sure how the properties plugin interacts with

<filters>
  <filter>${basedir}/src/main/props/base.properties</filter>
</filters>

for example - which would take precedence, the loaded project properties, or the filter properties? I'd be tempted to try something like this:

<properties>
    <prop1>defaultValue</prop1>
    <prop2>anotherDefaultValue</prop2>
</properties>

and then have the loaded files override the values as needed. I believe this works.

You might also check out the code for the properties plugin to see which properties take precedence if multiple files specifying the same property are loaded, then configure the plugin to load both files in the order that results in the behavior desired.

user944849
  • 14,524
  • 2
  • 61
  • 83
  • This did exactly what I needed. I'm disappointed in the verbosity it adds to the POM, but it is what it is. One important note: I had to make sure that the execution phase of the copy-resources goal in the maven-resources-plugin was the same or later than the phase of the read-project-properties goal of the properties-maven-plugin. I assume that determines order of filtering. – Matt Jan 04 '18 at 17:27
  • Yes, the properties loaded by this plugin execution are available to any plugin executions that happen afterwards. Glad it helped. – user944849 Jan 04 '18 at 17:31