Home > Enterprise >  Dynamic code compilation fails when running tests with Sbt
Dynamic code compilation fails when running tests with Sbt

Time:07-23

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

  • Related