I'm trying to migrate/update my project to use Nashorn from Rhino. I have some global utility functions implemented in Java and added into global scope of the target script engine, typical example is log(message)
.
In Rhino it is implemented via
public static class LogFunction extends org.mozilla.javascript.BaseFunction {
@Override
public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
...
}
}
whose instance added into target scope. What has to be done in case of Nashorn? I can't find how standalone function can be implemented for Nashorn.
You can easily implement script functions in Java. You just implement any @FunctionalInterface (https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html) interface using a lambda and expose the same as a global variable by calling ScriptEngine.put (https://docs.oracle.com/javase/8/docs/api/javax/script/ScriptEngine.html#put-java.lang.String-java.lang.Object-) method. The following example implements two such script 'functions' implemented in Java code.
import javax.script.*;
import java.util.function.*;
import java.util.Random;
public class Main {
public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
// expose 'log' function - any @FunctionInterface Java
// object can be exposed as 'function'
e.put("log", (Consumer<String>)System.out::println);
Random r = new Random();
// expose 'next gaussian' as script global function
e.put("gaussian", (Supplier<Double>)r::nextGaussian);
// call functions implemented in Java!
e.eval("log('hello')");
e.eval("print(gaussian())");
e.eval("print(gaussian())");
}
}