JSObject and delegation to other java classes
Marc Downie
marc at openendedgroup.com
Sun Jul 20 15:39:53 UTC 2014
Dear Nashorn-dev,
I'm building a JSObject-implementation-based to a fairly complex Java class
--- in order to present a more JavaScript-flavored façade to some Java and
I'm finding that I have to build a tremendous amount of boilerplate to call
existing Java methods in a JSObject. You can see where this is heading in
your own example code (
https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions):
...
public Object getMember(String name) {
switch (name) {
case "length":
return buf.capacity();
case "buf":
// return a 'function' value for this property
return new AbstractJSObject() {
@Override
public Object call(Object thiz, Object... args) {
return BufferArray.this.buf;
}
// yes, I'm a function !
@Override
public boolean isFunction() {
return true;
}
};
}
return null;
}
...
Imagine this code copied and pasted out to 50-odd methods & fields.
Question 1: have I missed something?
My main use case is actually less general:
public class ClassWithBigAPI
{
.... many methods and fields ...
}
public class JSMassageLayer extends ClassWithBigAPI implements JSObject
{
...
public void getMember(String n)
{
// how to lookup and return all methods and fields in super?
}
}
Question 2: is there something better that I can return than a whole new
AbstractJSObject? I've gotten some distance by returning
(SomeFunctionalInterface)this::someMethod, but I can't build those
automatically. In my case all I want is the standard method / field lookup
that I would have gotten before I implemented JSObject if that would
succeed. As far as I can tell, not only is this cumbersome to write and
maintain (even building these AbstractJSObject's based on reflection of the
class I'm delegating too), but it seems non-performant and loses
functionality that's hard to restore (for example magic SAM conversion on
calling). For example, is there a sane (and api-legal) way of building
SimpleDynamicMethod/OverloadedDynamicMethod instances?
Question 3: is this a real design problem? In other languages / interfaces
to languages there's a distinction made between a "getMember" that's called
for all member lookup and a "getMember" that's called when other, standard
member lookups fail (for example __getattr__ / __getattribute__ in
python/jython, groovy invokeMethod / methodMissing). Other languages /
runtimes privilege the second case (Ruby methodMissing, Scala's
selectDynamic). I've found Jython's functionality here, in particular,
vital to creating Pythonic interfaces to already-existing Java things, but
I was hoping to move my whole operation over to Nashorn.
Finally, I've also tried, in JS, new JSAdaptor(new ClassWithBigAPI()){ ...
}, but that doesn't seem to get me anywhere --- unexpectedly, __get__ is
still called for things that are in ClassWithBigAPI. Of course, being in JS
gives me more options, so I'm pursuing that route for now.
many thanks,
Marc
More information about the nashorn-dev
mailing list