Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nashorn replace Java.type with binding

Tags:

java-8

nashorn

To invoke Java from JS you can use Java.type. Is there a way to bind a java class in the Bindings?

So replace:

scriptEngine.eval("Java.type('my.own.AwesomeObj')");

with something like:

Bindings bindings = new SimpleBindings();
bindings.put("AwesomeObj", my.own.AwesomeObj.class);
scriptEngine.setBindings(bingings, ScriptContext.GLOBAL_SCOPE);

I am working on a framework where I want to make a lot of classes available for the js scripts, and preferably not use a string concatenation and an eval. Currently it throws an exception with message: AwesomeObj is not a function, what makes sense.

like image 527
Kalidasya Avatar asked Nov 26 '25 03:11

Kalidasya


2 Answers

Nashorn distinguishes a type from a java.lang.Class instance, just like Java does (in Java language, my.own.AwesomeObj is a type, while my.own.AwesomeObj.class is an instance of java.lang.Class. You can use a type to access static members, or as a constructor. You can't use a Class object for that purpose. The bad news is, you can't directly obtain the object that Nashorn uses for representing types; it's an instance of jdk.internal.dynalink.beans.StaticClass and it lives in a restricted package. However, you can evaluate it in script with

engine.eval("Java.type('my.own.AwesomeObj')");

and put the result of that in the bindings. Incidentally, within Nashorn, if you put the Class object into bindings under name AwesomeObjClass, you can use the synthetic property .static to obtain the type, e.g.:

var AwesomeObj = AwesomeObjClass.static;

In this sense, .static on a Class object is the dual of .class on a type object (.static obviously doesn't exist in Java, where types aren't reified as runtime objects).

var stringType = Java.type("java.lang.String");
var stringClass = stringType.class
print(stringClass instanceof java.lang.Class); // true
print(stringType === stringClass.static); // true

Hope this helps.

like image 179
Attila Szegedi Avatar answered Nov 27 '25 22:11

Attila Szegedi


since Java 9 you can use jdk.dynalink.beans.StaticClass.forClass as it is not internal anymore:

Bindings bindings = engine.createBindings();
bindings.put("AwesomeObj", StaticClass.forClass(my.own.AwesomeObj.class));

then you can utilize the binding in the JS code with :

var awesome = new AwesomeObj();
like image 43
pero_hero Avatar answered Nov 27 '25 22:11

pero_hero



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!