With the release of Scala 2.11 it became fully JSR-223 compliant scripting language for Java. JSR-223 is the community request to allow scripting language to have an interface to Java and to allow Java to use the scripting language inside of applications.
In Java 8 the Nashorn scripting engine was released as a native component of the JDK to support JavaScript with applications. This is possible through another JSR in Java 7 – namely JSR-229, which brings support for invoke dynamics, a way to support dynamic programming by the Java byte code compiler. Nashorn can be seen as a proof of concept of this newly added functionality.
Running Scala Script in Java Application
Let’s make a simple example to execute Scala as a script inside of a Java application.
We need to import and initialize the script engine like this:
import javax.script.*; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; public class TestScript { public static void main(String... args) throws Exception { ScriptEngine engine = new ScriptEngineManager().getEngineByName("scala"); ...
With ScriptEngineManager().getEngineByName(“scala”) a matching script engine is looked up. This just gives us the engine but not the required libraries and hooks to really execute a script.
There is one thing to note about the way Scala loads the required standard classes for the JVM. In case of the execution of scala standard Scala libraries are placed in the classpath of the JVM. This would not be the case here. You can read this for a reference. Trying to run a sample class would result in the following exception:
reflect.jar:. TestScript [init] error: error while loading Object, Missing dependency 'object scala in compiler mirror', required by /Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre/lib/rt.jar(java/lang/Object.class) Failed to initialize compiler: object scala in compiler mirror not found. ** Note that as of 2.8 scala does not assume use of the java classpath. ** For the old behavior pass -usejavacp to scala, or if using a Settings ** object programmatically, settings.usejavacp.value = true. Exception in thread "main" scala.reflect.internal.MissingRequirementError: object scala in compiler mirror not found.
We can work around this by using the scala java tools helping us to load the standard Scala libraries into the JVM classpath. This is one way to make our Scala script work:
mport javax.script.*; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import scala.tools.nsc.interpreter.IMain; import scala.tools.nsc.settings.MutableSettings.BooleanSetting; public class TestScript { public static void main(String... args) throws Exception { .... ((BooleanSetting)(((IMain)engine).settings() .usejavacp())).value_$eq(true); ....
The other is to simply execute the code with the following option:
$ java -Dscala.usejavacp=true ...
The complete script is this:
import javax.script.*; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import scala.tools.nsc.interpreter.IMain; import scala.tools.nsc.settings.MutableSettings.BooleanSetting; public class TestScript { public static void main(String... args) throws Exception { ScriptEngine engine = new ScriptEngineManager().getEngineByName("scala"); ((BooleanSetting)(((IMain)engine) .settings().usejavacp())) .value_$eq(true); String testScript = "var a:Int = 10"; engine.eval(testScript); String testScript2 = "println(a)"; engine.eval(testScript2); String testScript3 = "println(a+5)"; engine.eval(testScript3); }
Compiling and running this is pretty straight forward as we do need the Scala libraries they get places into the classpath.
Compiling:
$ javac -cp /Users//hkropp/bin/scala-2.11.7/lib/scala-library.jar: /Users//hkropp/bin/scala-2.11.7/lib/scala-compiler.jar: /Users//hkropp/bin/scala-2.11.7/lib/scala-reflect.jar TestScript.java
Running:
$ java -Dscala.usejavacp=true -cp /Users//hkropp/bin/scala-2.11.7/lib/scala-library.jar: /Users//hkropp/bin/scala-2.11.7/lib/scala-compiler.jar: /Users//hkropp/bin/scala-2.11.7/lib/scala-reflect.jar:. TestScript 10 15
The Scala 2.12.1 jar seems to no longer export the ScriptEngine. Trying to use it gives null.
https://groups.google.com/forum/#!topic/scala-user/6CnnKPOL0Rk
LikeLike