使用exec-maven-plugin执行test scope内嵌PostgreSQL主类报错求助
问题
我想用exec-maven-plugin执行一个Java主类,该类依赖test scope的com.opentable.components:otj-pg-embedded:0.13.4创建内嵌PostgreSQL并执行查询,但执行命令clean test exec:java后出现NoClassDefFoundError错误:
[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 34.374 s [INFO] Finished at: 2024-12-12T15:01:58Z [INFO] ------------------------------------------------------------------------ [WARNING] java.lang.NoClassDefFoundError: org/apache/commons/io/FileUtils at com.opentable.db.postgres.embedded.EmbeddedPostgres.close (EmbeddedPostgres.java:376) at com.opentable.db.postgres.embedded.EmbeddedPostgres$1.run (EmbeddedPostgres.java:342) at java.lang.Thread.run (Thread.java:829) Caused by: java.lang.ClassNotFoundException: org.apache.commons.io.FileUtils at org.codehaus.mojo.exec.URLClassLoaderBuilder$ExecJavaClassLoader.loadClass (URLClassLoaderBuilder.java:198) at java.lang.ClassLoader.loadClass (ClassLoader.java:527) at com.opentable.db.postgres.embedded.EmbeddedPostgres.close (EmbeddedPostgres.java:376) at com.opentable.db.postgres.embedded.EmbeddedPostgres$1.run (EmbeddedPostgres.java:342) at java.lang.Thread.run (Thread.java:829)
我的exec-maven-plugin配置如下:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.5.0</version> <executions> <execution> <phase>pre-integration-test</phase> <goals> <goal>exec</goal> </goals> </execution> </executions> <configuration> <executable>maven</executable> <classpathScope>test</classpathScope> <cleanupDaemonThreads>false</cleanupDaemonThreads> <mainClass>example.Main</mainClass> </configuration> </plugin>
项目依赖树显示commons-io:commons-io:jar:2.8.0存在于test scope中:
[INFO] --- maven-dependency-plugin:2.8:tree [INFO] com.example:example-console-app:jar:0.0.1 [INFO] +- org.eclipse.persistence:eclipselink:jar:4.0.3:compile [INFO] | +- jakarta.persistence:jakarta.persistence-api:jar:3.1.0:compile [INFO] | +- jakarta.xml.bind:jakarta.xml.bind-api:jar:4.0.2:compile [INFO] | \- com.sun.xml.bind:jaxb-xjc:jar:4.0.5:compile [INFO] | \- com.sun.xml.bind:jaxb-core:jar:4.0.5:compile [INFO] | \- org.eclipse.angus:angus-activation:jar:2.0.2:runtime [INFO] +- org.eclipse.persistence:org.eclipse.persistence.extension:jar:4.0.3:compile [INFO] | \- org.eclipse.persistence:org.eclipse.persistence.core:jar:4.0.3:compile [INFO] | \- org.eclipse.persistence:org.eclipse.persistence.asm:jar:9.7.0:compile [INFO] +- org.postgresql:postgresql:jar:42.7.3:compile [INFO] | \- org.checkerframework:checker-qual:jar:3.42.0:runtime [INFO] +- com.example:commons-testing:jar:0.0.1:test [INFO] | +- org.instancio:instancio-junit:jar:3.6.0:test [INFO] | | \- org.instancio:instancio-core:jar:3.6.0:test [INFO] | +- org.junit.jupiter:junit-jupiter-api:jar:5.8.2:test [INFO] | | +- org.opentest4j:opentest4j:jar:1.2.0:test [INFO] | | +- org.junit.platform:junit-platform-commons:jar:1.8.2:test [INFO] | | \- org.apiguardian:apiguardian-api:jar:1.1.2:test [INFO] | +- com.opentable.components:otj-pg-embedded:jar:0.13.4:test [INFO] | | +- org.apache.commons:commons-lang3:jar:3.11:test [INFO] | | +- org.apache.commons:commons-compress:jar:1.20:test [INFO] | | +- org.tukaani:xz:jar:1.5:test [INFO] | | +- commons-io:commons-io:jar:2.8.0:test [INFO] | | +- commons-codec:commons-codec:jar:1.15:test [INFO] | | +- com.github.spotbugs:spotbugs-annotations:jar:4.1.2:test [INFO] | | \- org.slf4j:jcl-over-slf4j:jar:1.7.30:test [INFO] | +- org.junit.jupiter:junit-jupiter-params:jar:5.8.2:test [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.626 s [INFO] Finished at: 2024-12-12T12:54:38+01:00 [INFO] ------------------------------------------------------------------------
解决方法
方法1:修正exec-maven-plugin的目标配置
你的插件配置里误用了<goal>exec</goal>,执行Java主类应该用exec:java目标而非exec:exec。修改插件执行配置:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.5.0</version> <executions> <execution> <phase>pre-integration-test</phase> <goals> <!-- 替换为java目标 --> <goal>java</goal> </goals> </execution> </executions> <configuration> <!-- 移除executable配置,java目标不需要该参数 --> <classpathScope>test</classpathScope> <cleanupDaemonThreads>false</cleanupDaemonThreads> <mainClass>example.Main</mainClass> </configuration> </plugin>
修改后可执行mvn clean test pre-integration-test触发阶段执行,或继续用mvn clean test exec:java手动触发目标。
方法2:显式引入commons-io依赖
虽然依赖树显示commons-io存在于test scope,但它是嵌套在com.example:commons-testing中的传递性依赖,exec-maven-plugin可能未正确加载。直接在pom.xml中显式添加该依赖:
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.8.0</version> <scope>test</scope> </dependency>
方法3:修复线程清理导致的类加载问题
EmbeddedPostgres的关闭线程是守护线程,插件默认会清理守护线程,导致类加载器提前销毁触发错误。可以:
- 移除
<cleanupDaemonThreads>false</cleanupDaemonThreads>配置,让插件默认处理线程; - 在主类中显式关闭EmbeddedPostgres并等待线程结束:
EmbeddedPostgres pg = EmbeddedPostgres.start(); // 执行查询逻辑 pg.close(); // 等待关闭线程完成 Thread.sleep(1000); // 或用CountDownLatch等更可靠的线程同步方式
内容的提问来源于stack exchange,提问作者The 5th column mouse
相关产品推荐
相关产品推荐

