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