Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Process spawned by exec-maven-plugin blocks the maven process

I am trying to execute the following scenario using maven :

  1. pre-integration-phase : Start a java based application using a main class (using exec-maven-plugin)
  2. integration-phase : Run the integration test cases (using maven-failsafe-plugin)
  3. post-integration-phase: Stop the application gracefully (using exec-maven-plugin)

Here is pom.xml snip:

    <plugins>
    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.2.1</version>
        <executions>
            <execution>
                <id>launch-myApp</id>
                <phase>pre-integration-test</phase>
                <goals>
                    <goal>exec</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <executable>java</executable>
            <arguments>
                <argument>-DMY_APP_HOME=/usr/home/target/local</argument>
                <argument>-Djava.library.path=/usr/home/other/lib</argument>
                <argument>-classpath</argument>
                <classpath/>
                <argument>com.foo.MyApp</argument>
            </arguments>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>2.12</version>
        <executions>
            <execution>
                <goals>
                    <goal>integration-test</goal>
                    <goal>verify</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <forkMode>always</forkMode>
        </configuration>
    </plugin>
</plugins>

If I execute mvn post-integration-test, my application is getting started as a child process of the maven process, but the application process is blocking the maven process from executing the integration tests which comes in the next phase. Later I found that there is a bug (or missing functionality?) in maven exec plugin, because of which the application process blocks the maven process. To address this issue, I have encapsulated the invocation of MyApp.java in a shell script and then appended “/dev/null 2>&1 &” to spawn a separate background process. Here is the snip (this is just a snip and not the actual one) from runTest.sh:

java - DMY_APP_HOME =$2 com.foo.MyApp > /dev/null 2>&1 &

Although this solves my issue, is there any other way to do it? Am I missing any argument for exec-maven-plugin?

like image 590
Arnab Biswas Avatar asked Mar 30 '12 05:03

Arnab Biswas


People also ask

What does Mvn exec exec do?

Maven exec plugin allows us to execute system and Java programs from the maven command. There are two goals of the maven exec plugin: exec:exec - can be used to execute any program in a separate process. exec:java - can be used to run a Java program in the same VM.

What is the correct syntax for executing a maven plugin?

Usage of a Maven Plugin xml you can use the shorthand notation to execute the plugin: mvn <prefix>:<goal> , commonly the “prefix” is the artifact ID minus the “-maven-plugin”. For example mvn example:version .

What is Mvn exec Java?

mvn exec:java is a goal from the exec plugin for maven. It lets you specify a main class to execute (see pom. xml). This lets you avoid having to figure out the proper java command to run and classpath arguments and the like.


2 Answers

You can use the async configuration parameter to achieve what you require. Also see asyncDestroyOnShutdown which will shutdown the app on JVM exit by default.

https://www.mojohaus.org/exec-maven-plugin/exec-mojo.html#async

If set to true the child process executes asynchronously and build execution continues in parallel.

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.6.0</version>
        <executions>
            <execution>
                <id>launch-myApp</id>
                <phase>pre-integration-test</phase>
                <goals>
                    <goal>exec</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <executable>java</executable>
            <arguments>
                <argument>-DMY_APP_HOME=/usr/home/target/local</argument>
                <argument>-Djava.library.path=/usr/home/other/lib</argument>
                <argument>-classpath</argument>
                <classpath/>
                <argument>com.foo.MyApp</argument>
            </arguments>
            <async>true</async>
        </configuration>
    </plugin>
like image 190
CamW Avatar answered Sep 23 '22 12:09

CamW


(Unix only) Use exec:exec and start a script. This script should call

java -DMY_APP_HOME =$2 com.foo.MyApp > /dev/null 2>&1 &

first, and check the startup before the script finishes. Did the program crash in 2 seconds?

When your java app needs some time to start you can add a script that waits for a complete startup.

   retrymax=30
   retry=0
   RETURNCODE=1
   while [ ${retry} -lt ${retrymax} ]; do
      todo_your_test
      RETURNCODE=$?
      if [ ${RETURNCODE} -eq 0 ]; then
         echo MyApp started
         break
      else
         (( retry = retry + 1 ))
         sleep 2
      fi
   done
   exit ${RETURNCODE}
like image 39
Walter A Avatar answered Sep 25 '22 12:09

Walter A