'Defining a default/global Java object to Nashorn script engine?

With Java's Nashorn script engine, I can provide objects in the context of an eval() using bindings like so:

Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
bindings.put("rules", myObj); 
scriptEngine.eval("rules.someMethod('Hello')", scriptContext);

I'd like to be able to simplify the javascript by providing a default object, so that instead of the javascript being:

rules.someMethod('Hello')

I can just write:

someMethod('Hello')

Is there any way to accomplish this? (someMethod is a method on an object, not a static method)



Solution 1:[1]

You can use Object.bindProperties extension of nashorn to bind properties of arbitrary object to JS global object. That way user can invoke methods (and access properties) on your "default" object from script without qualification. See Object.bindProperties documentation here https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-Object.bindProperties

Example code:

import javax.script.*;

public class Main {
   public static void main(String[] args) throws Exception {
       ScriptEngineManager m = new ScriptEngineManager();
       ScriptEngine e = m.getEngineByName("nashorn");

       // get JavaScript "global" object
       Object global = e.eval("this");
       // get JS "Object" constructor object
       Object jsObject = e.eval("Object");

       Invocable invocable = (Invocable)e;

       // calling Object.bindProperties(global, "hello");
       // which will "bind" properties of "hello" String object
       // to JS global object
       invocable.invokeMethod(jsObject, "bindProperties", global, "hello");

       // you're calling "hello".toUpperCase()"
       e.eval("print(toUpperCase())");
       // accessing bean property "empty" on 'hello' object
       e.eval("print(empty)");

       // just print all (enumerable) properties of global
       // you'll see methods, properties of String class
       // (which'd be called on "hello" instance when accessed)
       e.eval("for (var i in this) print(i)");
   }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 A. Sundararajan