Вызов функции JavaScript в коде Java

Я передаю функцию из файла JavaScript в код Java. Функция JavaScript выглядит так:

entity.handler = function(arg1, arg2) {
    //do something
};

В коде Java класс реализует интерфейс Scriptable. И когда я вызываю JavaScript, на самом деле в Java вызывается следующий метод:

Scriptable.put(java.lang.String s, org.mozilla.javascript.Scriptable scriptable, java.lang.Object o)

где для моего случая:

с = 'обработчик';

scriptable - объект, тип которого com.beanexplorer.enterprise.operations.js.ScriptableEntity

o - на самом деле является функцией, ее тип org.mozilla.javascript.gen.c15, ( o instanceof Scriptable ) возвращает true в отладчике.

В реализации метода Scriptable.put() я хочу делегировать действие объекту «o»:

SomeClass.invoke( new SomeListener(){
    @override
    public void someAction(int arg1, float arg2) {
       //here I need to delegate to the 'o' object.
       //do something looked like: 
       o.call(arg1, arg2); // have no idea how to do it, if it's possible.
    }
}

Как мне это сделать? Я не могу найти ни одного примера, необходимого для моего случая.

Спасибо.

РЕДАКТИРОВАТЬ, решение: Actully o - может быть переведено в Function. В итоге помогло следующее решение:

@Override
put(java.lang.String s, org.mozilla.javascript.Scriptable scriptable, java.lang.Object o) {
    ....
    final Function f = ( Function )o;
    final SomeInterface obj = new ...;
    obj.someJavaMethod( Object someParams, new SomeJavaListener() { 
        @Override
    public void use(Object par1, Object par2) throws Exception {
        Context ctx = Context.getCurrentContext();
        Scriptable rec = new SomeJavaScriptableWrapperForObject( par1);
            f.call( ctx, scriptable, scriptable, new Object[] { rec, par2 } );
        }
});

person Alexandr    schedule 13.03.2013    source источник
comment
Из Документация по API Scriptable: Host system implementors may find it easier to extend the ScriptableObject class rather than implementing Scriptable when writing host objects. Я бы попробовал...   -  person ppeterka    schedule 13.03.2013
comment
Если я вас правильно понимаю, вы предлагаете расширить ScriptableObject с помощью класса Java вместо реализации интерфейса. Но в любом случае я должен переопределить метод put, потому что стандартная реализация не подходит. В результате я не вижу никаких преимуществ от расширения класса ScriptableObject вместо реализации интерфейса.   -  person Alexandr    schedule 13.03.2013
comment
Ваш аргумент отчасти верен. Однако я бы сделал это, потому что при этом ваш код будет чище, и это может помочь обнаружить причину проблемы, и таким образом вам не нужно писать весь этот код, чтобы начать работу... Вам нужно только переопределите полезные методы, затем...   -  person ppeterka    schedule 13.03.2013
comment
Могу я спросить, что именно вы пытаетесь сделать? Не уверен, потому что ваш вопрос неоднозначен. Насколько я понимаю, вы хотите сделать свою программу доступной для сценариев, позволяя пользователям передавать произвольный код для entity.handler, который должен быть функцией с арностью 2. Это все, что вам нужно?   -  person Raffaele    schedule 13.03.2013
comment
Да, ты прав. Изначально это не мой код. Основная цель — писать обработчики на JavaScript, не зная, как они на самом деле обрабатываются.   -  person Alexandr    schedule 14.03.2013


Ответы (1)


Мне удалось запустить ваш Javascript с помощью следующего кода:

public class Main {

    public static void main(String[] args) {
        new ContextFactory().call(new ContextAction(){

            @Override
            public Object run(Context ctx) {
                Scriptable scope = ctx.initStandardObjects();
                try {
                    Scriptable entity = ctx.newObject(scope);

                    scope.put("console", scope, Context.javaToJS(System.out, scope));
                    scope.put("entity", scope, entity);

                    ctx.evaluateReader(
                        scope,
                        new InputStreamReader(Main.class.getResourceAsStream("/handler.js")),
                        "handler.js", 1, null);

                    Function handler = (Function) entity.get("handler", entity);
                    Object result = handler.call(ctx, scope, scope, new Object[] {"Foo", 1234});

                    System.out.println("Handler returned " + result);
                } catch (Exception e) {
                    e.printStackTrace(System.err);
                }
                return null;
            }
        });

    }
}

Следующий скрипт должен быть доступен в handler.js вашего CLASSPATH:

entity.handler = function(arg1, arg2) {
    console.println("Hello world from the JS handler");
    return 42;
}
person Raffaele    schedule 13.03.2013