There is a strange difference when I evaluate a nashorn script with or without bindings: without bindings there is no problem invoking a function, but with the bindings the function is not found. Here is an example:
public class SimpleNashornTester {
public static void main(String[] args) throws ScriptException, NoSuchMethodException {
ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName("nashorn");
Compilable jsCompilable = (Compilable) jsEngine;
Invocable jsInvocable = (Invocable) jsEngine;
ScriptContext scriptCtxt = new SimpleScriptContext();
Bindings engineScope = scriptCtxt.getBindings(ScriptContext.ENGINE_SCOPE);
CompiledScript jsScript = jsCompilable.compile("function definition() {print(\"Hello\")}");
jsScript.eval(engineScope); // no error with jsScript.eval() !
jsInvocable.invokeFunction("definition", new Object[] {});
}
}
This yields the error:
Exception in thread "main" java.lang.NoSuchMethodException: No such function definition
at jdk.nashorn.api.scripting.ScriptObjectMirror.callMember(ScriptObjectMirror.java:204)
Without the parameter engineScope in the evaluation of the script the function is found and invoked. Can anybody explain this difference? How can I use bindings without getting an error?
You're using a new ScriptContext and it's associated ENGINE_SCOPE
Bindings to compile the script. invokeFunction
/invokeMethod
use the default ScriptContext (and it's associated ENGINE_SCOPE
Bindings) to search the function. Each different ENGINE_SCOPE
Bindings is associated with its own ECMAScript global object (and it's own ECMAScript global objects).
So, you can fix your program by
changing the default context to be the new context before invoke:
// change the default ScriptContext
jsEngine.setContext(scriptCtxt);
jsInvocable.invokeFunction("definition", new Object[] {});
Use the default ScriptContext for compiled script as well. As in:
ScriptContext scriptCtxt = jsEngine.getContext(); // new SimpleScriptContext();