For our end-2-end test we need to execute the following logical flow:
- Create and set up e2e schema (user) in the database (
pre-integration-test
)
- Run Liquibase to initially populate the schema (
pre-integration-test
)
- Add e2e-specific test data to the DB tables (
pre-integration-test
)
- Start Tomcat (
pre-integration-test
)
- Run the web application in Tomcat (
integration-test
) using Protractor
- Shut down Tomcat (
post-integration-test
)
- 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.
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.