How to develop the Maven life cycle (in the proper sense) from a plugin?

Common Problem: I am testing a web application in a large service oriented architecture company. External services often fail in our test environment due to background noise. This prevents the integration tests from running for our service, since our service will not work if calls to these external services do not work. For this reason, we want us to be able to brush off external services, so that we do not have to depend on them, and we can isolate our own services.

There is a tool for this Mockey that we hope to use. This is a Java program that passes through the Jetty Embedded Server and acts as a proxy for service calls. Our web application is reconfigured to call Mockey instead of external services. Then, Mockey is configured to provide dynamically repulsive answers to these calls depending on the URL and header data that is being transmitted.

To use this tool, we would like to launch Mockey in the pre-integration phase of the Maven test cycle so that it is available for use in the integration phase.

The specific problem . To start and close Mockey during the pre-integration and testing phases after integration in the Maven life cycle, I wrote a Maven 3 plugin called mockey-maven -plugin:

File pom.xml mockey-maven-plugin:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mycompany.mockey</groupId>
    <artifactId>mockey-maven-plugin</artifactId>
    <packaging>maven-plugin</packaging>
    <version>1.3</version>

    <dependencies>

        <!-- Maven plugin dependencies -->
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.4</version>
            <scope>provided</scope>
        </dependency>

        <!-- Mockey dependency -->
        <dependency>
            <groupId>com.mycompany.mockey</groupId>
            <artifactId>Mockey</artifactId>
            <version>1.16.2015</version>
        </dependency>

    </dependencies>

    <build>

        <plugins>

            <!-- This plugin is used to generate a plugin descriptor
                 xml file which will be packaged with the plugin -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.4</version>
            </plugin>

        </plugins>

    </build>

</project>

Hockey-maven-plugin StartMockey Class:

@Mojo(name="start-mockey")
@Execute(phase= LifecyclePhase.PACKAGE) // Not sure about this annotation
public class StartMockey extends AbstractMojo
{
    /**
     * Flag which controls Mockey startup.
     */
    @Parameter(property="mockey.skipStartup", defaultValue="false", required=true)
    private Boolean skipStartup;

    // Do I need these getters and setters or does Maven ignore them?

    public Boolean getSkipStartup()
    {
        return skipStartup;
    }

    public void setSkipStartup(Boolean skipStartup)
    {
        this.skipStartup = skipStartup;
    }

    // *SNIP* Defining Mockey parameters...

    // Maven will call this method to start the mockey-maven-plugin
    public void execute()
    {
        if(skipStartup)
        {
            getLog().info("Skipping Mockey startup");
            return;
        }

        getLog().info("Starting Mockey");

        // Load specified parameters into array
        List<String> argsList = new ArrayList<>();

        // *SNIP* Adding Mockey parameters to argList...

        String[] args = new String[argsList.size()];
        argsList.toArray(args);

        // Start Mockey with specified parameters and wait for it to return
        try
        {
            JettyRunner.main(args);
        }
        catch(Exception e)
        {
            getLog().error("Mockey died... :(");
        }
        getLog().info("mockey-maven-plugin now exiting");
    }
}

The mockey-maven-plugin ShutdownMockey Class:

@Mojo(name="shutdown-mockey")
public class ShutdownMockey extends AbstractMojo
{
    /**
     * Flag which controls Mockey shutdown.
     */
    @Parameter(property="mockey.skipShutdown")
    private Boolean skipShutdown;

    // Again, Do I need these getters and setters or does Maven ignore them?

    public Boolean getSkipShutdown()
    {
        return skipShutdown;
    }

    public void setSkipShutdown(Boolean skipShutdown)
    {
        this.skipShutdown = skipShutdown;
    }

    public void execute()
    {
        if(skipShutdown)
        {
            getLog().info("Skipping Mockey shutdown");
            return;
        }
        getLog().info("Shutting down Mockey");
        JettyRunner.stopServer();
        getLog().info("mockey-maven-plugin now exiting");
    }
}

Input for plugin for mockey-maven-plugin in my pom.xml project file:

<plugin>
    <groupId>com.mycompany.mockey</groupId>
    <artifactId>mockey-maven-plugin</artifactId>
    <version>1.3</version>
    <configuration>
        <skipShutdown>${keepMockeyRunning}</skipShutdown>
        <skipStartup>${skipMockey}</skipStartup>

        <!-- *SNIP* Other Mockey parameters... -->

    </configuration>
    <executions>
        <execution>
            <id>start-mockey</id>
            <goals>
                <goal>start-mockey</goal>
            </goals>
            <phase>pre-integration-test</phase>
        </execution>
        <execution>
            <id>shutdown-mockey</id>
            <goals>
                <goal>shutdown-mockey</goal>
            </goals>
            <phase>post-integration-test</phase>
        </execution>
    </executions>
</plugin>

This plugin is great for launching Mockey during the pre-integration phase, but blocks the build until the Mockey game exits. I'm not sure why this is happening, as I specifically added this annotation to prevent this problem:

 @Execute(phase= LifecyclePhase.PACKAGE)

, , ( maven-tomcat7-plugin - ). , , .

:

  • Maven build .
  • () , .
  • , , - mockey-maven-plugin -.
  • - ( ) - . Mockey Jetty, JettyRunner.main(args) ( Mockey).
  • (IE: ).
  • , , - mockey-maven-plugin - shutdown-mockey.
  • shutdown-mockey JettyRunner.stopServer(), JettyRunner Jetty. (, , , ), Jetty .
  • Jetty, , , .
  • Maven.

, :

  • Maven build .
  • () , .
  • , , - mockey-maven-plugin -.
  • - . Maven , .
  • , .
  • , .
  • , . - ( ). JettyRunner.main(args), Mockey Jetty.
  • , Jetty ( Maven).

, Maven, , , , . forking , , . Unix, . . , , , . . , , "" Maven, , ? . , , "forking" Maven:

:

  • Maven , ?
  • Maven , , ? , ?
  • , Tomcat7 ( )?
  • Tomcat7, - ?

(. ):  - , , ?

+4
2

, Maven, :

  • @Execute StartMockey.
  • Java.

StartMockey.execute():

// Start Mockey with the specified parameters on a new thread.
MockeyRunner mockeyRunner = new MockeyRunner(args);
mockeyRunnerThread = new Thread(mockeyRunner);
mockeyRunnerThread.start();

MockeyRunner:

public class MockeyRunner implements Runnable
{
    private String[] args;
    private Exception exception;

    /**
     * We cannot throw the Exception directly in run() since we're implementing the runnable interface which does not
     * allow exception throwing.  Instead we must store the exception locally and check for it in whatever class is
     * managing this MockeyRunner instance after the run method has returned.
     * @return Exception thrown by Mockey
     */
    public Exception getException()
    {
        return exception;
    }

    /**
     * Constructor
     * @param args The arguments to pass to Mockey on startup
     */
    public MockeyRunner(String[] args)
    {
        this.args = args;
    }

    /**
     * This method starts Mockey from inside a new Thread object in an external class.  It is called internally by Java
     * when the Thread.start() method is called on that object.
     */
    @Override
    public void run()
    {
        try
        {
            JettyRunner.main(args);
        }
        catch(Exception e)
        {
            exception = e;
        }
    }
}

. , , "" Maven!

+2

All Articles