Maven exec:java goal on a multi

I'm trying to run exec-maven-plugin 's exec:java goal on a simple two-module project where one module depends on the other. So far I can't find a configuration that works. Here's a boiled-down test case:

  • exec-multi-module-test/
  • pom.xml
  • module1/
  • pom.xml
  • src/
  • main/
  • java/
  • HelloPrinter.java
  • module2/
  • pom.xml
  • src/
  • main/
  • java/
  • MyMain.java
  • Here's the parent pom:

    <?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.mkscrg.sandbox</groupId>
        <artifactId>exec-multi-module-test</artifactId>
        <version>1.0</version>
        <packaging>pom</packaging>
    
        <modules>
            <module>module1</module>
            <module>module2</module>
        </modules>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>1.2.1</version>
                </plugin>
            </plugins>
        </build>
    </project>
    

    module1 's pom:

    <?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>
    
        <parent>
            <artifactId>exec-multi-module-test</artifactId>
            <groupId>com.mkscrg.sandbox</groupId>
            <version>1.0</version>
        </parent>
    
        <artifactId>module1</artifactId>
    </project>
    

    module2 's pom: http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0

        <parent>
            <artifactId>exec-multi-module-test</artifactId>
            <groupId>com.mkscrg.sandbox</groupId>
            <version>1.0</version>
        </parent>
    
        <artifactId>module2</artifactId>
    
        <dependencies>
            <dependency>
                <groupId>com.mkscrg.sandbox</groupId>
                <artifactId>module1</artifactId>
                <version>${project.version}</version>
            </dependency>
        </dependencies>
    </project>
    

    This project compiles successfully from the top, but running mvn exec:java -Dexec.mainClass=myMain fails:

    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Reactor Build Order:
    [INFO] 
    [INFO] exec-multi-module-test
    [INFO] module1
    [INFO] module2
    [INFO]                                                                         
    [INFO] ------------------------------------------------------------------------
    [INFO] Building exec-multi-module-test 1.0
    [INFO] ------------------------------------------------------------------------
    [INFO] 
    [INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) @ exec-multi-module-test >>>
    [INFO] 
    [INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) @ exec-multi-module-test <<<
    [INFO] 
    [INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ exec-multi-module-test ---
    [WARNING] 
    java.lang.ClassNotFoundException: MyMain
            at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
            at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:285)
            at java.lang.Thread.run(Thread.java:680)
    [INFO] ------------------------------------------------------------------------
    [INFO] Reactor Summary:
    [INFO] 
    [INFO] exec-multi-module-test ............................ FAILURE [0.363s]
    [INFO] module1 ........................................... SKIPPED
    [INFO] module2 ........................................... SKIPPED
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD FAILURE
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 0.566s
    [INFO] Finished at: Mon Jun 18 14:11:54 PDT 2012
    [INFO] Final Memory: 3M/81M
    [INFO] ------------------------------------------------------------------------
    [ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.2.1:java (default-cli) on project exec-multi-module-test: An exception occured while executing the Java class. MyMain -> [Help 1]
    [ERROR] 
    [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR] 
    [ERROR] For more information about the errors and possible solutions, please read the following articles:
    [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
    

    What's the right way to configure this project to allow exec:java to see MyMain ?

    EDIT: Here's a gist if you'd like to try this yourself: https://gist.github.com/2950830

    EDIT: Clarification: I know it's possible to mvn install and then either run exec:java from module2 's directory or use the -pl flag from the top. However, I'd like to avoid running mvn install . It shouldn't be necessary to modify my local repository in order to run this goal in a multi-module project. Just as mvn compile "just works" with a multi-module project, so should other goals/phases.


    Goals in a multi-module project, when run from the parent, will run against all modules. I don't think that's what you want. You can try:

    mvn exec:java -pl module2 -Dexec.mainClass=MyMain
    

    That might work? More info:

  • Running a specific Maven plugin goal from the command line in a sub-module of a multi-module reactor project
  • However, I think it's more intuitive to change directory to the sub-module containing the executable before running it.


  • You should bind the exec-maven-plugin to a maven lifecycle goal, say verify .
  • Since you want the plugin to be executed only for module 2, define the plugin configurations in the parent pom within pluginManagement . Use the same only in module 2 .
  • Then run the following:
  • mvn verify -Dexec.mainClass=MyMain .

    parent pom

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>1.2.1</version>
                    <executions>
                     <execution>
                         <phase>verify</phase>
                         <goals>
                             <goal>java</goal>
                         </goals>
                     </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
    

    module 2

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    

    See this answer for a single-command alternative without mvn install :

    https://stackoverflow.com/a/26448447/1235281

    By using skip in the parent pom.xml , you can tell Maven to only run exec:java on a specific submodule.

    GitHub: https://github.com/Oduig/mavenfiddle

    链接地址: http://www.djcxy.com/p/37578.html

    上一篇: Maven多模块项目

    下一篇: Maven exec:多目标Java的目标