A simple unit test (without junit) gives weird exception
import java.io.StringReader;
import java.sql.PreparedStatement;
import org.codehaus.janino.SimpleCompiler;
public class TestJanino {
public void testJanino() throws Exception {
PreparedStatement ps = null;
String sampleClass = "import java.sql.PreparedStatement; public class Test{}";
SimpleCompiler sc = new SimpleCompiler();
sc.setParentClassLoader(getClass().getClassLoader());
sc.cook("Test.java", new StringReader(sampleClass));
System.out.println(sc.getBytecodes().size());
}
public static void main(String[] args) throws Exception {
TestJanino d = new TestJanino();
d.testJanino();
}
}
Message is:
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ xx.xxx.server.nn ---
[WARNING] useSystemClassloader setting has no effect when not forking
[INFO] Surefire report directory: D:\workspace\XXXX\xx.xxx.server.nn\target\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running xx.xxx.server.nn.TestJanino
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.057 sec <<< FAILURE!
xx.xxx.server.nn.TestJanino.testJanino() Time elapsed: 0.056 sec <<< FAILURE!
org.codehaus.commons.compiler.CompileException: File 'Test.java', Line 1, Column 1: A class "java.sql.PreparedStatement" could not be found
at org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:12679)
at org.codehaus.janino.UnitCompiler.getSingleTypeImport(UnitCompiler.java:10639)
at org.codehaus.janino.UnitCompiler.checkForConflictWithSingleTypeImport(UnitCompiler.java:454)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:410)
at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:231)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:391)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:386)
at org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1692)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:386)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:359)
at org.codehaus.janino.UnitCompiler.access$000(UnitCompiler.java:231)
at org.codehaus.janino.UnitCompiler$1.visitCompilationUnit(UnitCompiler.java:333)
at org.codehaus.janino.UnitCompiler$1.visitCompilationUnit(UnitCompiler.java:330)
at org.codehaus.janino.Java$CompilationUnit.accept(Java.java:367)
at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:330)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:245)
at org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:473)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:223)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:209)
at xx.xxx.server.nn.TestJanino.testJanino(TestJanino.java:14)
Results :
Failed tests: xx.xxx.server.nn.TestJanino.testJanino(): File 'Test.java', Line 1, Column 1: A class "java.sql.PreparedStatement" could not be found
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.738 s
[INFO] Finished at: 2021-12-14T07:52:08+01:00
[INFO] ------------------------------------------------------------------------
But if I run the main without maven it resolves:
How is that possible?
This is my pom.xml
:
<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>xx.xxx</groupId>
<version>xxx-SNAPSHOT</version>
<properties>
<forkMode>never</forkMode>
</properties>
<artifactId>xxx</artifactId>
<dependencies>
<dependency>
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
<version>3.1.6</version>
</dependency>
</dependencies>
</project>
I finally was able to reproduce your issue with Java 11 and Maven 3.8.
As indicated in the question comments, the problem seems to be related to the fact that the Maven surefire plugin is not using the system class loader. Please, consider read the relevant documentation.
You can verify that point using the following plugin configuration:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
</plugin>
</plugins>
</build>
You are not providing this configuration explicitly but as indicated in the Maven trace:
...
[WARNING] useSystemClassloader setting has no effect when not forking
...
you aren't using forking, which is coherent with the configuration provided in your pom.xml
:
<properties>
<forkMode>never</forkMode>
</properties>
In order to solve the problem you could remove that configuration, and the test will run without further problems.
Having said that, as I said in the comments as well, I tested the code with different Maven versions and JDK 8 and it worked even setting useSystemClassloader
to false
, so I honestly cannot tell you the exact reason of the problem, probably it may have to do with the JDK version, but it could be the Maven version or even Janino as well.