2

I have a Maven project which includes a Maven plugin (the Liquibase Maven plugin) which exposes different goals. Two of these goals (update and diff) need different parameters which are in conflict between them (because the semantics of the two is different), so I need to give Maven different properties in the two goal executions.

That's what I've done

<plugin>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-maven-plugin</artifactId>
    <version>3.4.1</version>

    <!-- This configuration is used for every goal except "diff" -->
    <configuration>
        <propertyFile>src/main/resources/liquibase.properties</propertyFile>
        <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
    </configuration>
    <executions>
        <execution>
            <id>default-cli</id>
            <goals>
                <goal>diff</goal>
            </goals>
            <!-- This configuration is used for the "diff" goal -->
            <configuration>
                <propertyFile>src/main/resources/liquibaseDiff.properties</propertyFile>
                <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
            </configuration>
        </execution>
    </executions>
</plugin>

However, this configuration is wrong because for each goal (diff, update of the others) only the liquibaseDiff.properties file is used.

Is there any way to pass different configurations for different goals in Maven?

Tunaki
  • 132,869
  • 46
  • 340
  • 423
gvdm
  • 3,006
  • 5
  • 35
  • 73

1 Answers1

10

Configuration of plugins can be done in two different locations:

  • Globally for all executions. The global configuration is done with the <configuration> element under <plugin>. This configuration in inherited by all executions.
  • Per execution. This is done using the <configuration> element under <execution>.

In your example, consider this POM:

<plugin>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-maven-plugin</artifactId>
    <version>3.4.1</version>
    <configuration>
        <!-- put the configuration here that is common to all executions -->
    </configuration>
    <executions>
        <execution>
            <id>diff</id>
            <goals>
                <goal>diff</goal>
            </goals>
            <configuration>
                <!-- put the specific configuration of the diff goal here, this will inherit from the global configuration -->
            </configuration>
        </execution>
        <execution>
            <id>update</id>
            <goals>
                <goal>update</goal>
            </goals>
            <configuration>
                <!-- put the specific configuration of the update goal here, this will inherit from the global configuration -->
            </configuration>
        </execution>
    </executions>
</plugin>

The default inheritance behavior is to merge the content of the configuration element according to element name. If the child POM has a particular element, that value becomes the effective value. If the child POM does not have an element, but the parent does, the parent value becomes the effective value.

In case of conflicts, you can control the default inheritance performed by Maven using combine.children and combine.self. Quoting the Maven docs:

combine.children="append" results in the concatenation of parent and child elements, in that order. combine.self="override", on the other hand, completely suppresses parent configuration.


In addition to this, you need to be aware that when executing a Maven command, on the command line, that directly invokes a goal, such as mvn liquibase:diff, it creates a new execution with an id that is default-cli. As such, since the specific configuration above of the goal diff is done in an execution with id diff, it will not be used. This is actually normal, since the same goal of the same plugin could be present in multiple execution blocks with different configuration: which one should be used if it is executed on the command line, without additional information?

Typically, this situation is solved in 2 manners:

  • Execute on the command line a specific execution, i.e. the one you configured. This is possible since Maven 3.3.1 and you would execute

    mvn liquibase:diff@diff
    

    The @diff in the command above refers to the unique <id> of the execution that is configured in the POM.

  • Bind your execution to a specific phase of the Maven lifecycle, and let it be executed with the normal flow of the lifecycle. This is generally the prefered solution. In the example above, we could, for example, add a <phase>test</phase> in the execution block of the diff execution; and then Maven will execute it when the test phase is ran during the course of the build.

Community
  • 1
  • 1
Tunaki
  • 132,869
  • 46
  • 340
  • 423
  • Hi @Tunaki. I tried this configuration: http://pastebin.com/1mHJqFjj This is the output of both goals: http://pastebin.com/0A65iGXL It seems that both update and diff goals read the liquibase.properties file (so diff doesn't switch to liquibaseDiff.properties) – gvdm Oct 15 '15 at 12:39
  • @gvdm Try to remove the `default-cli` from your execution. – Tunaki Oct 15 '15 at 12:41
  • Yes, I posted the wrong configuration. I tried the configuration at this link (http://pastebin.com/1mHJqFjj) but nothing.. – gvdm Oct 15 '15 at 12:42
  • @gvdm I can't test your particular use-case right now. I will later, but this should be working. – Tunaki Oct 15 '15 at 12:44
  • I re-tried many times with the per-goal configurations and general+diff-specific configurations, but nothing. Maven can only find the liquibase.properties file – gvdm Oct 15 '15 at 14:38
  • 1
    @gvdm I understand what you're doing wrong. Basically, the answer works, it's just that your test is wrong. When you're invoking directly `mvn liquibase:diff`, Maven does not invoke a specific execution and it parses the global plugin configuration (so it always take the global property file). When you add `default-cli`, Maven always invoke that execution (for `mvn liquibase:whatever`) so the configuration taken will always be the execution configuration. A correct test would be to bind the `diff` and `update` goal to a specific phase (say `test`) and invoke Maven with that phase (`mvn test`). – Tunaki Oct 15 '15 at 18:12
  • Ok, but what if I should only run the two goals withous linking them to a phase? – gvdm Oct 16 '15 at 07:33
  • @gvdm Then give each execution an ID and invoke Maven specifying that execution ID with `mvn liquibase:diff@executionId` – Tunaki Oct 16 '15 at 07:36
  • 1
    mmm...It's a pity I cannot assign the "default-cli" ID to both the executions and discriminate the configurations by the goal – gvdm Oct 16 '15 at 07:39