问题
Trying to create a Java/JS link using Rhino with two very simple objects, one having as one member an instance of the second class.
Running the code below gives the following error:
org.mozilla.javascript.EcmaError: TypeError: Cannot find default value for object.
The problem seems to be accessing the member "a" from within second object. I've also tried with a getter like this:
public Object jsGet_a() {
return Context.toObject(a, this);
}
but i get the same error.
new A().doSmth(); is working fine, and outputs "I'm doing something" new B().a.doSmth(); raises the error
Can anyone help me with a possible solution for this?
Thank you!
public class Test {
public static class A extends ScriptableObject implements Scriptable {
public A() {
};
public String getClassName() {
return "A";
}
public void jsFunction_doSmth() {
System.out.println("I'm doing something");
};
}
public static class B extends ScriptableObject implements Scriptable {
private A a = new A();
public B() {
};
public String getClassName() {
return "B";
}
public void jsConstructor() {
}
public A jsGet_a() {
return a;
}
}
public static void main(String[] args) {
try {
Context cx = Context.enter();
Scriptable scope = cx.initStandardObjects(null, true);
ScriptableObject.defineClass(scope, A.class);
ScriptableObject.defineClass(scope, B.class);
cx.compileString("" +
"new A().doSmth();" +
"new B().a.doSmth();" +
"", "", 1, null).exec(cx, scope);
} catch (Exception e) {
e.printStackTrace();
}
}
}
回答1:
This seems to work:
- Made the context and the global scope private static variables.
- Added jsConstructor for the A class
- In the jsConstructor for the B class, created a javascript object in code.
- Used the Context.toObject(a, this); with return type of Scriptable in jsGet_a()
Finally, assigned the cx to the Context that was entered and scope to the global scope.
public class Test { private static Context cx; private static ScriptableObject scope; public static class A extends ScriptableObject implements Scriptable { public A() { } public void jsConstructor() { } public String getClassName() { return "A"; } public void jsFunction_doSmth() { System.out.println("I'm doing something"); } } public static class B extends ScriptableObject implements Scriptable { private A a = new A(); public B() { } public String getClassName() { return "B"; } public void jsConstructor() { Scriptable scriptable = cx.newObject(scope, "A"); this.put("a", this, scriptable); } public Scriptable jsGet_a() { return Context.toObject(a, this); } } public static void main(String[] args) { try { cx = Context.enter(); scope = cx.initStandardObjects(null, true); ScriptableObject.defineClass(scope, A.class); ScriptableObject.defineClass(scope, B.class); cx.compileString("" + "new A().doSmth();" + "new B().a.doSmth();" + "", "", 1, null).exec(cx, scope); } catch (Exception e) { e.printStackTrace(); } } }
回答2:
new B().a.doSmth();
will not work as a
is private.
new B().jsGet_a().jsFunction_doSmth();
seems like it should work.
回答3:
According to the API docs, you could use the method
// Get a named property from the object.
get(java.lang.String name, Scriptable start)
in your java object. My guess is that you got the reflection conversion wrong in the above.
来源:https://stackoverflow.com/questions/5863810/error-trying-to-access-class-members-using-rhino