Fork me on GitHub

Usage

Exec goal

You can formally specify all the relevant execution information in the plugin configuration. Depending on your use case, you can also specify some or all information using system properties.

Command line

Using system properties you would just execute it like in the following example.

mvn exec:exec -Dexec.executable="maven" [-Dexec.workingdir="/tmp"] -Dexec.args="-X myproject:dist"

POM Configuration

Add a configuration similar to the following to your POM:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>3.6.3</version>
        <executions>
          <execution>
            ...
            <goals>
              <goal>exec</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <executable>maven</executable>
          <!-- optional -->
          <workingDirectory>/tmp</workingDirectory>
          <arguments>
            <argument>-X</argument>
            <argument>myproject:dist</argument>
            ...
          </arguments>
          <environmentVariables>
            <LANG>en_US</LANG>
          </environmentVariables>
        </configuration>
      </plugin>
    </plugins>
  </build>
   ...
</project>

Java goal

This goal helps you run a Java program within the same VM as Maven.

Differences compared to plain command line

The goal goes to great length to try to mimic the way the VM works, but there are some subtle differences. Today all differences come from the way the goal deals with thread management.

command line Java Mojo
The VM exits as soon as the only remaining threads are daemon threads By default daemon threads are joined and interrupted once all known non daemon threads have quit. The join timeout is customisable. The user might wish to further cleanup by stopping the unresponsive threads. The user can disable the full extra thread management (interrupt/join/[stop])

Important limitation: Thread Group Isolation

The java goal tracks threads created within its own isolated thread group. It does not track threads created in other thread groups. This means that if your code creates threads outside the isolated thread group (for example, through RMI, JMX, or other frameworks), those threads will not be detected as "known" threads, and the plugin may exit even if such non-daemon threads are still running.

Examples of affected scenarios:

  • RMI - java.rmi.registry.LocateRegistry.createRegistry() creates non-daemon threads in the system thread group, not in the plugin's isolated thread group.
  • JMX - Similar to RMI, JMX remote connectors may create threads outside the isolated group.
  • Other frameworks that manage their own thread pools or create threads using the system thread group.

In such cases, the plugin will exit when all threads in its own thread group have completed, even though non-daemon threads may still be running in other thread groups. This can cause servers or services to be terminated prematurely.

Workaround: If you need threads created by frameworks like RMI to keep the JVM alive, use the exec goal to run your Java program in a separate JVM process instead. The exec goal spawns a new process which will behave like running java from the command line.

Read the documentation for the java goal for more information on how to configure this behavior.

If you find out that these differences are unacceptable for your case, you may need to use the exec goal to wrap your Java executable.

Command line

If you want to execute Java programs in the same VM, you can either use the command line version

mvn exec:java -Dexec.mainClass="com.example.Main" [-Dexec.args="argument1"] ...

POM Configuration

or you can configure the plugin in your POM:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>3.6.3</version>
        <executions>
          <execution>
            ...
            <goals>
              <goal>java</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <mainClass>com.example.Main</mainClass>
          <arguments>
            <argument>argument1</argument>
            ...
          </arguments>
          <systemProperties>
            <systemProperty>
              <key>myproperty</key>
              <value>myvalue</value>
            </systemProperty>
            ...
          </systemProperties>
        </configuration>
      </plugin>
    </plugins>
  </build>
   ...
</project>

Note: The java goal doesn't spawn a new process. Any VM specific option that you want to pass to the executed class must be passed to the Maven VM using the MAVEN_OPTS environment variable. E.g.

MAVEN_OPTS=-Xmx1024m

Otherwise consider using the exec goal.