Error trying to access class members (using Rhino)

99封情书 提交于 2020-01-03 02:40:06

问题


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:

  1. Made the context and the global scope private static variables.
  2. Added jsConstructor for the A class
  3. In the jsConstructor for the B class, created a javascript object in code.
  4. Used the Context.toObject(a, this); with return type of Scriptable in jsGet_a()
  5. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!