ClassNotFoundException when dynamically loading a Java class executed by exec-maven-plugin
Minimal reproducer project: https://github.com/Kirchoffs/exec-plugin-issue
What I am trying to do, is to create a java class (PrimitiveServlet.class) file by javac, and then use URLClassLoader to load this class file dynamically.
To reproduce the bug using exec-maven-plugin, run the following command:
>> javac -cp webroot/javax.servlet-api-4.0.1.jar webroot/PrimitiveServlet.java
>> mvn clean install
>> mvn exec:java
The first command is to create the class file, the third command is to run the whole program.
Error Information:
java.lang.NoClassDefFoundError: javax/servlet/Servlet
at java.lang.ClassLoader.defineClass1 (Native Method)
at java.lang.ClassLoader.defineClass (ClassLoader.java:1016)
at java.security.SecureClassLoader.defineClass (SecureClassLoader.java:174)
at java.net.URLClassLoader.defineClass (URLClassLoader.java:550)
at java.net.URLClassLoader$1.run (URLClassLoader.java:458)
at java.net.URLClassLoader$1.run (URLClassLoader.java:452)
at java.security.AccessController.doPrivileged (Native Method)
at java.net.URLClassLoader.findClass (URLClassLoader.java:451)
at java.lang.ClassLoader.loadClass (ClassLoader.java:588)
at java.lang.ClassLoader.loadClass (ClassLoader.java:521)
at org.syh.demo.App.main (App.java:25)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:279)
at java.lang.Thread.run (Thread.java:834)
Caused by: java.lang.ClassNotFoundException: javax.servlet.Servlet
at java.net.URLClassLoader.findClass (URLClassLoader.java:471)
at java.lang.ClassLoader.loadClass (ClassLoader.java:588)
at java.lang.ClassLoader.loadClass (ClassLoader.java:521)
at java.lang.ClassLoader.defineClass1 (Native Method)
at java.lang.ClassLoader.defineClass (ClassLoader.java:1016)
at java.security.SecureClassLoader.defineClass (SecureClassLoader.java:174)
at java.net.URLClassLoader.defineClass (URLClassLoader.java:550)
at java.net.URLClassLoader$1.run (URLClassLoader.java:458)
at java.net.URLClassLoader$1.run (URLClassLoader.java:452)
at java.security.AccessController.doPrivileged (Native Method)
at java.net.URLClassLoader.findClass (URLClassLoader.java:451)
at java.lang.ClassLoader.loadClass (ClassLoader.java:588)
at java.lang.ClassLoader.loadClass (ClassLoader.java:521)
at org.syh.demo.App.main (App.java:25)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:279)
at java.lang.Thread.run (Thread.java:834)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.111 s
[INFO] Finished at: 2022-08-01T21:21:09-07:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.1.0:java (default-cli) on project exec-plugin-issue: An exception occurred while executing the Java class. javax/servlet/Servlet: javax.servlet.Servlet
However, if we use pure java command to run the program, the code can work without any error:
>> javac -cp webroot/javax.servlet-api-4.0.1.jar webroot/PrimitiveServlet.java
>> mvn clean install
>> java -cp webroot/javax.servlet-api-4.0.1.jar:target/exec-plugin-issue-1.0-SNAPSHOT.jar org.syh.demo.App
Try set compile scope to https://www.mojohaus.org/exec-maven-plugin/java-mojo.html#classpathScope
Or not use dependency in provided scope.
Thanks for the reply @slawekjaranowski
I add the parameter classpathScope with the value compile like the code below, but it still doesn't work.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>org.syh.demo.App</mainClass>
<classpathScope>compile</classpathScope>
</configuration>
</plugin>
Probably I missed something?