Search code examples
mavenmaven-3maven-pluginmaven-failsafe-pluginmaven-docker-plugin

Maven plugin crossed execution order


I'm writing some integration tests using failsafe plugin.

I want to execute the following:

1) Start Docker (goal start in phase pre-integration-test)

2) Start Spring (goal start in phase pre-integration-test)

3) Tests (phase integration-test)

4) Stop Spring (goal stop in post-integration-test)

5) Stop Docker (goal stop in post-integration-test)

Why? I want to start Docker BEFORE Spring so all databases are ready when Spring boots and also I want to stop Docker AFTER Spring to avoid a lot of errors in Spring due to database connection losses.

I have the following pom.xml:

        <plugin>
            <groupId>io.fabric8</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>0.20.1</version>
            <executions>
                <execution>
                    <id>run-docker-containers</id>
                    <goals>
                        <goal>start</goal>
                    </goals>
                    <configuration>
                        ...
                    </configuration>
                </execution>
                <execution>
                    <id>stop-docker-containers</id>
                    <goals>
                        <goal>stop</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>pre-integration-test</id>
                    <goals>
                        <goal>start</goal>
                    </goals>
                    <configuration>
                        ...
                    </configuration>
                </execution>
                <execution>
                    <id>post-integration-test</id>
                    <goals>
                        <goal>stop</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>

But with this pom.xml I'm getting this order:

1) Start Docker

2) Start Spring

3) Tests

4) Stop Docker

5) Stop Spring

This is, Docker is stopped BEFORE Spring and I don't want that.

I know that the execution order in Maven is given by the order in pom.xml, but in this case I need to have crossed goals.

Any advice?

Thanks.


Solution

  • Execution order in Maven is based on two components:

    • First, the lifecycle phase to which the execution is bound
    • For executions bound to the same phase, the ordering in the POM takes precedence.

    Maven doesn't allow the same plugin to be configured twice, so it's not possible to move the Docker Stop execution below Spring. The only way I know to fix things like this is to introduce a third phase into the mix. It looks a bit weird to bind 'stop' goals to the verify phase, and I'd definitely add comments to explain why this was done for posterity - but it works.

    This plugin config does the following (assuming you use the maven-failsafe-plugin for integration tests; if you use a different plugin follow the same principles with that plugin). Maven lifecycle phase in parentheses:

    1) Docker Start (pre-integration-test)

    2) Spring Start (pre-integration-test; Spring plugin config after Docker)

    3) Execute tests (integration-test)

    4) Spring Stop (post-integration-test)

    5) Docker Stop (verify)

    6) Verify test results (verify; Failsafe plugin config after Docker)

    <plugin>
        <groupId>io.fabric8</groupId>
        <artifactId>docker-maven-plugin</artifactId>
        <version>0.20.1</version>
        <executions>
            <execution>
                <id>run-docker-containers</id>
                <phase>pre-integration-test</phase>
                <goals>
                    <goal>start</goal>
                </goals>
            </execution>
            <execution>
                <id>stop-docker-containers</id>
                <phase>verify</phase>    <!-- important: note phase -->
                <goals>
                    <goal>stop</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>${version.maven.failsafe.plugin}</version>
        <executions>
            <execution>
                <id>failsafe-integration-tests</id>
                <phase>integration-test</phase>
                <goals>
                    <goal>integration-test</goal>
                </goals>
            </execution>
            <execution>
                <id>failsafe-verify</id>
                <phase>verify</phase>
                <goals>
                    <goal>verify</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <executions>
            <execution>
                <id>pre-integration-test</id>
                <phase>pre-integration-test</phase>
                <goals>
                    <goal>start</goal>
                </goals>
            </execution>
            <execution>
                <id>post-integration-test</id>
                <phase>post-integration-test</phase>
                <goals>
                    <goal>stop</goal>
                </goals>
            </execution>
        </executions>
    </plugin>