Mozilla Rhino переопределяет метод объекта из javascript

Я ищу переопределение метода java из javascript в rhino. Вот мой код:

public class CustomClass {
public String s="some string";
public void doSomething(){}
}

а потом:

        Object wrappedOut = Context.javaToJS(new CustomClass(), scope);
        ScriptableObject.putProperty(scope, "CustomClass", wrappedOut);
        String s="CustomClass.s='aaa'; \n CustomClass.doSomething=function(args){};";
        Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);

Таким образом, можно изменить значение на CustomClass.s, но не на метод doSomething.

Я получаю следующую ошибку:

org.mozilla.javascript.EvaluatorException: метод Java "doSomething" не может быть назначен. (# 2)

ОБНОВЛЕНИЕ Как и просили в комментариях, вот мой полный исходный код:

CustomClass.java

public class CustomClass {
    public String s="Do something now!";

    public void doSomething(Object ... v){
        System.out.println("do something");
    }
}

Скрипты.java

import org.mozilla.javascript.*;
public class Scripting {
    public static void main(String args[])
    {

        Context cx = Context.enter();
        try {

            Scriptable scope = cx.initStandardObjects();

            Object wrappedOut = Context.javaToJS(new CustomClass(), scope);
            ScriptableObject.putProperty(scope, "CustomClass", wrappedOut);


            String s="CustomClass.doSomething=function(args){};";

            Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);

            System.err.println(Context.toString(result));
        }catch(WrappedException e){
            e.printStackTrace();

        } catch(Exception e){
            e.printStackTrace();
        }finally {
            // Exit from the context.
            Context.exit();
        }
    }
}

person Doua Beri    schedule 04.01.2013    source источник
comment
Где вы переопределяете метод? Я не вижу никакого наследования в вашем коде.   -  person kaysush    schedule 04.01.2013
comment
@SushilKumar Я хочу переопределить метод из javascript. см. мой строковый код оценки: CustomClass.doSomething=function(args){};   -  person Doua Beri    schedule 04.01.2013
comment
Я не могу запустить этот код. пожалуйста, опубликуйте SSCCE   -  person linski    schedule 04.01.2013
comment
@linski Я обновил пост. посмотреть весь код   -  person Doua Beri    schedule 04.01.2013
comment
У меня не получилось написать именно так, как вы просили (надеюсь, скоро получится), но я нашел альтернативное решение для переопределения Java-метода из JS, см. пример здесь.   -  person linski    schedule 05.01.2013


Ответы (1)


Когда этот код выполняется, Rhino не вызывает метод Java doSomething. Вместо этого он пытается вызвать свой аналог JavaScript (который отсутствует), а затем генерирует исключение sun.org.mozilla.javascript.internal.EvaluatorException: Java class "CustomClass" has no public instance field or method named "doSomething". (#1).

Ваш CustomClass — это чистый класс Java без аналога JavaScript. Если вы замените эту строку в своем источнике:

String s="CustomClass.doSomething=function(args){};";

с этой строкой:

String s = "CustomClass";

и оцените его как команду javasript, он выведет как CustomClass@15e0be38. Обычно это означает, что это какой-то ("15e0be38") экземпляр объекта класса CustomClass.

Из apidoc для метода ScriptableObject.defineClass(Scriptable scope, java.lang.Class clazz):


Определяет объекты JavaScript из класса Java, реализующего Scriptable.
(...)
Затем все методы сканируются на наличие специальных префиксов, указывающих на то, что они имеют особое значение для определения объектов JavaScript. Эти специальные префиксы

jsFunction_ для функции JavaScript
jsStaticFunction_ для функции JavaScript, которая является свойством конструктора
jsGet_ для метода получения свойства JavaScript
jsSet_ для метода установки свойства JavaScript
jsConstructor для функции JavaScript, которая является конструктором

Если имя метода начинается с «jsFunction_», создается функция JavaScript с именем, состоящим из остальной части имени метода Java, следующего за «jsFunction_». Таким образом, метод Java с именем "jsFunction_foo" будет определять метод JavaScript "foo". Вызов этой функции JavaScript приведет к вызову метода Java. Параметры метода должны иметь количество и типы, определенные классом FunctionObject. Затем функция JavaScript добавляется как свойство прототипа.


Метод JavaScript print ((определенный в классе org.mozilla.javascript.tools.shell.Global)) взаимодействует с методом Java System.out.println. При запуске

public class CustomClass {

public static class _CustomClass extends ScriptableObject {

    @Override
    public String getClassName() {
        return "CustomClass";
    }

    public int jsFunction_method() {
        System.out.println("from java method");
        return 2;
    }
}

public static void main(String[] args) {
    Context context = Context.enter();
    Global global = new Global(context);
    try {            
        //ScriptableObject.defineClass(global, CustomClass.class); 
        ScriptableObject.defineClass(global, _CustomClass.class);            
        String script = "myInstance = new CustomClass();myInstance+' ';";
        System.out.println(context.evaluateString(global, script, "", 1, null));
        script = "myInstance.method+' '+myInstance.method()";
        System.out.println(context.evaluateString(global, script, "script", 1, null));
        script = "CustomClass.prototype.method=function(){print('overriden from javascript method');return 3;}";
        context.evaluateString(global, script, "", 1, null);
        script = "myInstance.method+' '+myInstance.method();";
        System.out.println(context.evaluateString(global, script, "script", 1, null));
    } 
    catch (Exception e) {
        e.printStackTrace();
    } 
    finally {
        Context.exit();
    }
  }
  }

он выводит:

[object CustomClass]
from java method
function method() {
[native code, arity=0]
}
 2

overriden from javascript method
function () {
    print("overriden from javascript method");
    return 3;
}
 3
  • обратите внимание, что если бы этот же код JS выполнялся в Chrome, он работал бы по-другому — возвращайте 2 дважды.
  • если бы использовался внешний класс (как в комментарии), возникла бы общая ошибка времени компиляции. Этот код был написан с использованием Rhino 1.7r2.
person linski    schedule 07.01.2013