I totally agree on the benefit of calling Java directly. I just want to create a seamless DSL for my users.
So subclassing JSObject is the only way it seems (e.g. an interface-based approach wouldn't work). What about a hybrid interface + annotation based approach? Annotate the class to tell it to dynalink, and have an interface that implements getMember, getSlot, etc... Is that possible? -----Original Message----- From: nashorn-dev-boun...@openjdk.java.net [mailto:nashorn-dev-boun...@openjdk.java.net] On Behalf Of A. Sundararajan Sent: Tuesday, October 22, 2013 12:55 PM To: nashorn-dev@openjdk.java.net Subject: Re: Docs/examples for JSAdapter It is possible to subclass jdk.nashorn.api.scripting.JSObject by an arbitrary Java class. Such a class will be linked by a special dynalink linker. Script can do normal obj.foo, obj.bar() etc. and these would be routed to JSObject.getMember/getSlot, JSObject.removeMember, JSObject.call etc. That said, being able to call/invoke arbitrary Java class/method from script is very useful as well. Allows lot of useful Java libraries be accessed from script code 'as is'. For eg. it is very easy to extend and/or use JavaFX library from script. Nice samples have been written. -Sundar On Tuesday 22 October 2013 10:13 PM, Rick Bullotta wrote: > Short version: > > I don't want my users to have to code anything like Java.type(XXX), which > they didn't need to do in Rhino and makes for some ugly code. I want > business people to be able to write scripts in most cases. A proper script > engine should be able to enable the developer to hide complexity from the > script author/user, not the other way around, I'd think. > > I need to be able to expose Java object(s) of a variety of types to the > scripting environment and be able to intercept the following: > > Object get(string) > put(string, Object) > Object get(int) > put(int, value) > Object[] ids() (for enumeration) > delete(string) > delete(i) > > get methods should be able to return values or function references (which > would of course implement a "call" method). > > This is what Rhino allows, and it is powerful and elegant, and GREATLY > simplifies the user's experience. > > > From: Jim Laskey (Oracle) [mailto:james.las...@oracle.com] > Sent: Tuesday, October 22, 2013 12:34 PM > To: Rick Bullotta > Cc: nashorn-dev@openjdk.java.net > Subject: Re: Docs/examples for JSAdapter > > In Nashorn, there is no need to wrap classes/types in JavaScript > objects. You can work with them directly or extended them directly. > As an example, > > jjs> var ArrayList = Java.type("java.util.ArrayList"); // or var > jjs> ArrayList = java.util.ArrayList; var Arrays = > jjs> Java.type("java.util.Arrays"); var list = new ArrayList(); > jjs> list.add("a"); > true > jjs> list.add("b"); > true > jjs> list.add("c"); > true > jjs> list.addAll(Arrays.asList(["d", "e", "f"])); > true > jjs> list.addAll(Arrays.asList("g", "h", "i")); > true > jjs> for each(var e in list) print(e); > a > b > c > d > e > f > g > h > i > > Is there a specific example of something you want to translate? We can help > you out. > > Cheers, > > -- Jim > > > > > > > On 2013-10-22, at 1:02 PM, Rick Bullotta > <rick.bullo...@thingworx.com<mailto:rick.bullo...@thingworx.com>> wrote: > > > In Rhino, you register custom adapters in a "wrap factory" that tells the > script engine to use these adapters for accessing instances of those > classes/types. What's the analog in Nashorn? Can custom types implement > interfaces that Nashorn will use? > > From: Jim Laskey (Oracle) > [mailto:james.las...@oracle.com<http://oracle.com>] > Sent: Tuesday, October 22, 2013 11:52 AM > To: Rick Bullotta > Cc: nashorn-dev@openjdk.java.net<mailto:nashorn-dev@openjdk.java.net> > Subject: Re: Docs/examples for JSAdapter > > In general the Nashorn docs start here. > https://wiki.openjdk.java.net/display/Nashorn/Nashorn+Documentation, but as > you point out, we seem to be lacking JSAdapter details. I should start an > FAQ. > > >From the javadoc (cd make; ant javadoc # ./dist/javadoc/index.html) > > > * public final class NativeJSAdapter > > * extends > ScriptObject<file:///\\Volumes\Elephant\Projects\nashorn~jdk8\nashorn\dist\javadoc\jdk\nashorn\internal\runtime\ScriptObject.html> > This class is the implementation of the Nashorn-specific global object named > JSAdapter. It can be thought of as the > Proxy<http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html?is-external=true> > equivalent for JavaScript. NativeJSAdapter calls specially named JavaScript > methods on an adaptee object when property access/update/call/new/delete is > attempted on it. Example: > > var y = { > > __get__ : function (name) { ... } > > __has__ : function (name) { ... } > > __put__ : function (name, value) {...} > > __call__ : function (name, arg1, arg2) {...} > > __new__ : function (arg1, arg2) {...} > > __delete__ : function (name) { ... } > > __getIds__ : function () { ... } > > }; > > > > var x = new JSAdapter(y); > > > > x.i; // calls y.__get__ > > x.foo(); // calls y.__call__ > > new x(); // calls y.__new__ > > i in x; // calls y.__has__ > > x.p = 10; // calls y.__put__ > > delete x.p; // calls y.__delete__ > > for (i in x) { print(i); } // calls y.__getIds__ > > > > JavaScript caller of adapter object is isolated from the fact that the > property access/mutation/deletion are really calls to JavaScript methods on > adaptee. > > JSAdapter constructor can optionally receive an "overrides" object. > Properties of overrides object is copied to JSAdapter instance. When user > accessed property is one of these, then adaptee's methods like __get__, > __put__ etc. are not called for those. This can be used to make certain > "preferred" properties that can be accessed in the usual/faster way avoiding > proxy mechanism. Example: > > var x = new JSAdapter({ foo: 444, bar: 6546 }) { > > __get__: function(name) { return name; } > > }; > > > > x.foo; // 444 directly retrieved without __get__ call > > x.bar = 'hello'; // "bar" directly set without __put__ call > > x.prop // calls __get__("prop") as 'prop' is not overridden > > > It is possible to pass a specific prototype for JSAdapter instance by passing > three arguments to JSAdapter constructor. So exact signature of JSAdapter > constructor is as follows: > > JSAdapter([proto], [overrides], adaptee); > > > Both proto and overrides are optional - but adaptee is not. When proto is not > passed JSAdapter.prototype is used. > * > As well as the test ./test/script/basic/jsadapter.js > > var obj = new JSAdapter() { > __get__: function(name) { > print("getter called for '" + name + "'"); return name; > }, > > __put__: function(name, value) { > print("setter called for '" + name + "' with " + value); > }, > > __call__: function(name, arg1, arg2) { > print("method '" + name + "' called with " + arg1 + ", " + arg2); > }, > > __new__: function(arg1, arg2) { > print("new with " + arg1 + ", " + arg2); > }, > > __getIds__: function() { > print("__getIds__ called"); > return [ "foo", "bar" ]; > }, > > __getValues__: function() { > print("__getValues__ called"); > return [ "fooval", "barval" ]; > }, > > __has__: function(name) { > print("__has__ called with '" + name + "'"); > return name == "js"; > }, > > __delete__: function(name) { > print("__delete__ called with '" + name + "'"); > return true; > } > }; > > // calls __get__ > print(obj.foo); > > // calls __put__ > obj.foo = 33; > > // calls __call__ > obj.func("hello", "world"); > > // calls __new__ > new obj("hey!", "it works!"); > > for (i in obj) { > print(i); > } > > for each (i in obj) { > print(i); > } > > var x = "foo" in obj; > print(x); > > var y = "js" in obj; > print(y); > > print(delete obj.prop); > > print(obj["js"]); > obj["js"] = "javascript"; > print(obj["javascript"]); > Hope that helps. Is there a specific question? > > Cheers, > > -- Jim > > On 2013-10-22, at 11:50 AM, Rick Bullotta > <rick.bullo...@thingworx.com<mailto:rick.bullo...@thingworx.com>> wrote: > > > > Hi, all. > > I've been searching everywhere for any form of documentation or substantive > examples as to how JSAdapter works in Nashorn, as it is an essential piece of > the puzzle for many of us who will naturally be migrating from Rhino. > > Can anyone provide and additional info? > > Thanks, > > Rick > ThingWorx > >