6

I have the following code which works:

ScriptEngine jsEngine = ScriptEngineManager.new().getEngineByName("nashorn");
jsEngine.eval("some script");

jsEngine.invokeMethod(jsEngine.eval("foo"), "bar");

but I want to do use a pre-compiled script so I don't have to evaluate the script every time I need to run it, so I'm trying;

ScriptEngine jsEngine = ScriptEngineManager.new().getEngineByName("nashorn");
CompiledScript compiledJS = jsEngine.compile("some script");

but then I'm not sure what to do with CompiledScript, how do I invoke a method? it doesn't implement anything else than eval() apparently: https://docs.oracle.com/javase/8/docs/api/javax/script/CompiledScript.html

Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622
  • I think my approach here might be wrong, so I wrote a more basic question: http://stackoverflow.com/questions/32252843/re-using-a-nashorn-scriptengine – Pablo Fernandez Aug 27 '15 at 14:58

1 Answers1

4

You call the method?

Here are few examples: http://www.programcreek.com/java-api-examples/index.php?api=javax.script.CompiledScript


Example:

import java.util.*;
import javax.script.*;

public class TestBindings {
    public static void main(String args[]) throws Exception {
        String script = "function doSomething() {var d = date}";
        ScriptEngine engine =  new ScriptEngineManager().getEngineByName("JavaScript");
        Compilable compilingEngine = (Compilable) engine;
        CompiledScript cscript = compilingEngine.compile(script);

        //Bindings bindings = cscript.getEngine().createBindings();
        Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
        for(Map.Entry me : bindings.entrySet()) {
            System.out.printf("%s: %s\n",me.getKey(),String.valueOf(me.getValue()));
        }
        bindings.put("date", new Date());
        //cscript.eval();
        cscript.eval(bindings);

        Invocable invocable = (Invocable) cscript.getEngine();
        invocable.invokeFunction("doSomething");
    }
}
Margus
  • 19,694
  • 14
  • 55
  • 103
  • how do you call the method? CompiledScript doesn't implement Invocable. – Pablo Fernandez Aug 27 '15 at 14:47
  • There's no single mention of invokeMethod or invokeFunction in that page you linked to. – Pablo Fernandez Aug 27 '15 at 14:49
  • I updated example, I have used similar approach before, however i can say it is a bit unintuitive. Have not used latest script engine, but I assume it works in similar manner. – Margus Aug 27 '15 at 14:53
  • 2
    So, you are calling invokeFunction in the ScriptEngine, why is the CompiledScript needed at all? Do I need to create new bindings every time I want to call a function/method again? Will calling the method modify the ScriptEngine itself? – Pablo Fernandez Aug 27 '15 at 14:55
  • 1) CompiledScript removes some overhead and if you run it over and over again, so it will be faster. The call can happen inside the script especially in case of recursive functions. It is not a immutability guarantee, but like a constant - if you need changes in the script you need to recompile. +more 2) No, you can just call "cscript.eval();" as well, however if you want to use different aka mutable parameters then, yes. It would not make sense to recompile each time as it has larger overhead. 3) It will change the context. You can reuse script engine with different bindings if you mean that – Margus Aug 28 '15 at 08:34