Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a good way to use maven to run an executable jar?

I have a multimodule maven project, and one of the modules is for distribution.

Project \
| moduleA \
| moduleB \
| ...
| dist-module \

The distribution contains an executable jar that I'd like to easily execute. However, to execute it I have to type something like:

java -jar dist-module/target/dist-module-1.0-SNAPSHOT-full-dist/myJar.jar

It would be quite preferable to simply type:

mvn exec:java \ OR
mvn exec:exec

Unfortunately, I can't find a way to get the java goal to execute a .jar. The exec goal will actually do it, but there's a catch: the jar contains an embedded jetty server, and due to the way exec works (doesn't use the same JVM as maven) the server doesn't terminate unless I kill the process manually, which is similarly bothersome.

Any recommendations on how to do this using maven?

Edit:
For clarification, this command will primarily be used for simple manual smoke-testing; to read the log output and ensure the program started up properly in its distribution environment. As such, it should probably be a blocking call with ctrl-c terminating both the server and maven.

The embedded server is specialized to run a few specific applications, and does not automatically reload them. So, there's not a big need to keep the server running independently of maven for long periods of time.

like image 455
Shaun Avatar asked Mar 01 '13 00:03

Shaun


People also ask

Can Maven project convert to jar?

Expand your project in the tree, expand Lifecycle and double-click on package. IntelliJ will run the Maven package phase, and you'll see the output in another window below. Your JAR file will be available at target/your-app-1.0. jar !


1 Answers

mvn exec:java runs the app directly from the compiler output below target/ - no need to run from the jar:

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.2.1</version>
        <executions>
            <execution>
                <id>default-cli</id>
                <goals>
                    <goal>java</goal>
                </goals>
                <configuration>
                    <mainClass>uk.co.pookey.hibernate.App</mainClass>
                    <systemProperties>
                        <systemProperty>
                            <key>derby.stream.error.file</key>
                            <value>${basedir}/target/derby.log</value>
                        </systemProperty>
                    </systemProperties>
                </configuration>
            </execution>
        </executions>
    </plugin>            

If you want to run the jar with mvn exec:exec :

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.2.1</version>
        <executions>
            <execution>
                <id>default-cli</id>
                <goals>
                    <goal>exec</goal>
                </goals>
                <configuration>
                    <executable>java</executable>
                    <!-- optional -->
                    <workingDirectory>/tmp</workingDirectory>
                    <arguments>
                        <argument>-jar</argument>
                        <argument>${basedir}/target/hibernate-derby-memory-${project.version}.jar</argument>
                    </arguments>
                </configuration>                        
            </execution>
        </executions>
    </plugin>         

If you have problems with jetty terminating, I'd recommend running an integration test (or just don't exit the jetty main thread without terminating jetty first, or just use jetty's stop port)! It is possible to run a JVM in the background and let maven stop it again after testing. There are three phases for this: pre-integration-test, integration-test or post-integration-test. You can read more about this at http://docs.codehaus.org/display/MAVENUSER/Maven+and+Integration+Testing . When using jetty maven plugin, the pom.xml config could like:

   <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <!-- test start/stop: -->
        <executions>                
            <execution>
                <id>start-jetty</id>
                <phase>pre-integration-test</phase>
                <goals>
                    <goal>deploy-war</goal>
                </goals>
                <configuration>
                    <daemon>true</daemon>
                    <systemProperties>
                        <systemProperty>
                            <name>some.prop</name>
                            <value>false</value>
                        </systemProperty>
                    </systemProperties>
                </configuration>
            </execution>
            <execution>
                <id>stop-jetty</id>
                <phase>post-integration-test</phase>
                <goals>
                    <goal>stop</goal>
                </goals>
            </execution>
        </executions>    
    </plugin>

Instead of binding the jetty maven plugin to these phases, you could bind the maven antrun plugin to execute arbitrary commands.

like image 137
3 revs Avatar answered Oct 31 '22 23:10

3 revs