I have a scala test that dynamically generates a java source code and compiles it at runtime. It works perfectly when I run tests in IDE (IntelliJ), but fails when using sbt test
.
The main difference is when running in IDE my test class, third party classes (jars), and com.sun.tools.javac.api.JavacTool
class are loaded by jdk.internal.loader.ClassLoaders$AppClassLoader
. When running in sbt, my test class, third party classes (jars) are loaded using sbt.internal.LayeredClassLoader
, but com.sun.tools.javac.api.JavacTool
is still loaded by jdk.internal.loader.ClassLoaders$AppClassLoader
, thus JavacTool
fails to compile a generated code b/c thrid party classes cannot be found (parent class loader doesn't have access to child's classes). Is possible to overcome this issue?
UPDATE: I set -cp
using the code below:
List<String> optionList = new ArrayList<String>();
optionList.add("-cp");
optionList.add(System.getProperty("java.class.path"));
When running in IDE System.getProperty("java.class.path")
returns the whole classpath including third-party jars, however, when running from Sbt there is only one jar in classpath: C:\Users\PliashkouRaman\AppData\Roaming\JetBrains\IdeaIC2022.1\plugins\Scala\launcher\sbt-launch.jar
I hardcoded a list of jars and now the test is passing.
CodePudding user response:
I solved the problem by appending fullClasspath
to System.getProperty("java.class.path")
sbt:
Test / testOptions = Tests.Setup(() => {
val jars = scala.collection.mutable.ListBuffer.empty[String]
(Runtime / fullClasspath).value.foreach { e =>
jars = e.data.getAbsolutePath
}
jars = System.getProperty("java.class.path")
val classpath = jars.mkString(":")
System.setProperty("java.class.path", classpath)
println(classpath)
})
UPDATE:
classpath delimiter is OS specific
:
Linux
;
Win