Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven: run plugin twice during a phase, interleaved with another plugin

For our end-2-end test we need to execute the following logical flow:

  1. Create and set up e2e schema (user) in the database (pre-integration-test)
  2. Run Liquibase to initially populate the schema (pre-integration-test)
  3. Add e2e-specific test data to the DB tables (pre-integration-test)
  4. Start Tomcat (pre-integration-test)
  5. Run the web application in Tomcat (integration-test) using Protractor
  6. Shut down Tomcat (post-integration-test)
  7. Clean up the DB: drop the schema (post-integration-test)

For running SQL the sql-maven-plugin is used, however this flow doesn't fit the regular POM layout:

  • The SQL plugin has to run during pre-integration-test twice, before and after the liquibase-maven-plugin
  • The SQL plugin has to run before Tomcat plugin during pre-integration-test, however it has to run after during post-integration-test, so that the DB schema is dropped after Tomcat has shut down.

As far as I could conclude from Maven docs, the order of plugins in the POM defines the order of execution during the same phase, and a plugin cannot be mentioned twice in the same POM.

Question: Is there any way to achieve this, apart from writing a shell script that would invoke Maven multiple times?

P.S. found a similar unanswered question.

like image 240
yktoo Avatar asked Oct 18 '22 08:10

yktoo


1 Answers

Given the sample POM below:

<project>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sample</groupId>
    <artifactId>sample-project</artifactId>
    <version>0.0.2-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.5</version>
                <executions>
                    <execution>
                        <id>print-hello</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <echo message="hello there!" />
                            </target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.5.0</version>
                <executions>
                    <execution>
                        <id>exec-echo</id>
                        <phase>validate</phase>
                        <configuration>
                            <executable>cmd</executable>
                            <arguments>
                                <argument>/C</argument>
                                <argument>echo</argument>
                                <argument>hello-from-exec</argument>
                            </arguments>
                        </configuration>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.5</version>
                <executions>
                    <execution>
                        <id>print-hello-2</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <echo message="hello there 2!" />
                            </target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

We are actually configuring:

  • The maven-antrun-plugin to print the hello there! message
  • The exec-maven-plugin to print the hello-from-exec message
  • The maven-antrun-plugin to print the hello there 2! message

Goal executions are all attached to the same phase, validate, and we would expect to be executed in the same defined order.

However, when invoking (the -q option is used to have exactly and only their output):

mvn validate -q

we would have as output:

main:
     [echo] hello there!

main:
     [echo] hello there 2!
hello-from-exec

That is, for the same phase, Maven executed the defined plugins, however merging all of the defined executions for the same plugins (even if defined as different plugin sections) and then execute them in the order to merged definitions.

Unfortunately, there is no mechanism to avoid this merging. The only options we have for configuring plugins execution behaviors are:

  • The inherited configuration entry:

    true or false, whether or not this plugin configuration should apply to POMs which inherit from this one. Default value is true.

  • The combine.children and combine.self to

    control how child POMs inherit configuration from parent POMs by adding attributes to the children of the configuration element.

None of these options would help us. In this case we would need a kind of merge attribute on the execution element or have a different behavior by default (that is, Maven should respect the definition order).


Invoking the single executions from command line as below:

mvn antrun:run@print-hello exec:exec@exec-echo antrun:run@print-hello-2 -q

We would instead have the desired output:

main:
     [echo] hello there!
hello-from-exec

main:
     [echo] hello there 2!

But in this case:

  • We are not attached to any phase
  • We are invoking directly specific executions (and their configurations) via command line (and via a new feature only available since Maven 3.3.1

You can achieve exactly the same via scripting or via exec-maven-plugin invoking maven itself, but - again - the same would apply: no phase applied, only sequence of executions.

like image 134
A_Di-Matteo Avatar answered Oct 20 '22 23:10

A_Di-Matteo