Hey all, I've had some basic JS extensions to my application in place for
some time now. It's time to get serious about building a proper API for my
application. I do not want to expose my business objects directly to JS.
Suppose I have a JavaBomb class. I want JS to be able to set the fuse length
but not light the fuse. I might create a Java class JSBomb that wraps
JavaBomb and forwards the setFuseLength method to JavaBomb and has no
lightFuse() method at all. This approach would work fine for single objects
but I'm having trouble coming up with an approach for dealing with a
hierarchy. I want to call a JS function from Java passing in a "root"
object. The JS can then manipulate the hierachy. My Java code can then
proceed to operate on the root that may have been modified by the JS.

I can't figure out how to do this (my current solution is to copy the Java
object tree to my API classes, then copy it back -- ugly). I have
experimented with a wrap factory but I'm not sure it's appropriate, nor do I
understand the benefit to writing ScriptableObject extensions. Consider the
following (trying to be brief!):

My business model:

public class MyEntity {

    private MyEntity child;
    private String name;

    public MyEntity getChild() { return child; }
    public void setChild(MyEntity child) { this.child = child; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

}

My JavaScript wrapper:

public class MyEntityWrapper {

    private MyEntity delegate;

    public MyEntityWrapper() {
        this(new MyEntity());
    }

    public MyEntityWrapper(MyEntity del) {
        super();
        delegate = del;
    }

    public MyEntity getDelegate() { return delegate; }
    public void setDelegate(MyEntity wrappedEntity) { this.delegate =
wrappedEntity; }

    public MyEntity getChild() { return delegate.getChild(); }
    public void setChild(MyEntity child) { delegate.setChild(child); }
    public String getName() { return delegate.getName(); }
    public void setName(String name) { delegate.setName(name); }

}

Using a wrap factory with:

public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object
javaObject, Class staticType) {
     if (javaObject instanceof MyEntity) {
          MyEntity me = (MyEntity) javaObject;
          MyEntityWrapper mew = new MyEntityWrapper(me);
          return super.wrapAsJavaObject(cx, scope, mew, staticType);
     } else {
          return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
     }
 }

The wrap factory takes care of the "conversion" of
MyEntityWrapper.getChild() but not setChild(). I could fore go the wrap
factory and implement MyEntityWrapper.get/setChild like so:

public MyEntityWrapper getChild() { return new
MyEntityWrapper(delegate.getChild()); }
public void setChild(MyEntityWrapper child) {
delegate.setChild(child.getDelegate()); }

I *either case* the following JS code is false:

myEntity.getChild() == myEntity.getChild();

Either the wrap factory or my own wrapping creates a new object which makes
the above fail. I'd have to keep another member "wrappedChild" that is
MyEntityWrapper and implement MyEntityWrapper.getChild() like so:

public MyEntityWrapper getChild() {
    if (child == null) return null;
    if (wrappedChild == null) {
       wrappedChild = new MyEntityWrapper(child);
    }
    return wrappedChild;
}

This will quickly get out of hand, be difficult to manage and error prone.
It does have the advantage that all my wrapper classes clearly illustrate
the classes and functions exposed to the JavaScript. Is there some way to
take advantage of Rhino/JavaScript, ScriptableObject, etc. to achieve my
goal? It seems like this design problem would be pretty common to anyone
designing a JavaScript API for a Java application.

Thanks for the help.

-- 
Daryl Stultz
_____________________________________
6 Degrees Software and Consulting, Inc.
http://www.6degrees.com
mailto:[email protected]
_______________________________________________
dev-tech-js-engine-rhino mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-js-engine-rhino

Reply via email to