add InterpretedFunction to the java scriptEngine using eval

RhinoScriptEngine

This is the typical engine we use for js evaluation.

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/com/sun/script/javascript/RhinoScriptEngine.java

without ScriptContext

import javax.script.*;

public class CallFunction {

    /**
     * @param args
     * @throws Exception oops!
     */
    public static void main(String[] args) throws Exception {
        ScriptEngine js = new ScriptEngineManager().getEngineByExtension("js");
        js.getContext().setAttribute("out", System.out, ScriptContext.ENGINE_SCOPE);
        Object a = js.eval(
                "out.println('Defining function a...');" +
                "function a() {out.println('hello from JavaScript!'); }" +
                "function foobar() {out.println('in foobar() definition');}" +    
                "out.println('Done!.');"
        );

        System.out.println(js.get("a")); // InterpretedFunction
        SimpleBindings bindings = new SimpleBindings();
        bindings.put("foobar",js.get("a"));
        js.eval("foobar();", bindings); // hello from JavaScript
        js.eval("foobar();"); // in foobar() definition
    }
}

When you get back the reference to a function, you need to ask the engine to execute that function for you. And although not pretty, asking js to eval() it for you with a specific set of bindings will actually do the job for you. You need to take care that the variables you’re manipulating belong to the right scope; I guess it’s easy to make mistakes here.

using ScriptContext

To make it less error-prone, we could call the eval with the ScriptContext. something like this:

import javax.script.*;

public class CallFunction {

    /**
     * @param args
     * @throws Exception oops!
     */
    public static void main(String[] args) throws Exception {
        // or:  js = new ScriptEngineManager().getEngineByName("JavaScript");
        ScriptEngine js = new ScriptEngineManager().getEngineByExtension("js");
        ScriptContext scriptContext = new SimpleScriptContext();
        Bindings scriptScope = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
        scriptScope.put("out", System.out);


        // this will add the function names into the scriptScope as key, value is the function itself.
        // later by calling scriptEngine.eval("fucntionName()", scriptContext) to invoke the function.
        js.eval(
            "out.println('Defining function a...');" +
                "function a() {out.println('hello from JavaScript!'); }" +
                "function foobar() {out.println('in foobar() definition');}" +
                "out.println('Done!.');"
            , scriptContext);

       js.eval("a()", scriptScope); // hello from JavaScript!
       js.eval("foobar()", scriptScope); // in foobar() definition
    }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s