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
>
>

Reply via email to