Совместное использование объектов Java в Rhino Javascript

Позвольте мне начать с признания, что я нуб в JavaScript. Таким образом, вопрос может быть не очень разумным в основе и может не хватать достаточно информации, чтобы помочь мне.

Задний план

В моей организации есть внутренняя среда разработки для JavaScript на основе Eclipse. Все, что нам нужно сделать, это написать скрипты на JavaScript и напрямую их выполнить. Я предполагаю, что он использует Rhino, так как я видел его в трассировке стека некоторых исключений.

Мой код работает с 3 файлами ".js".

Сценарий-1: объявить глобальные переменные и создать их как объекты Java.

importClass(java.util.HashMap);
var hmTCResult = new HashMap();

Script-2: Выполните некоторые действия, используя глобальные переменные из Script-1.

Script-2.prototype.run = function() {
hmTCResult.put("Result", "Fail");
};

changeStatus = function(strStatus){
hmTCResult.put("Result", strStatus);
};

Script-3: функция вызова в Script-2, которая использует глобальные переменные

changeStatus("Pass") 

Определение проблемы

Когда из Script-3 я вызываю функцию в Script-2, кажется, что переменные экземпляра не выбираются, и моя функция дает сбой, т. Е. Я получаю исключение «hmTCResult не установлен для экземпляра объекта». Обратите внимание, что эта же переменная hmTCResult хорошо работает в Скрипте 1.

Я кое-что прочитал о Scope и Context в JavaScript, но не смог разобраться в этом, так как я не вижу его явно в IDE.

Я буду рад предоставить дополнительную информацию, если это необходимо.


person wanderlust    schedule 21.10.2012    source источник
comment
Я не думаю, что есть какие-либо общие объекты Java, которые важны для вас. Пожалуйста, покажите нам соответствующие части вашего кода, то есть объявление этой функции в сценарии 2, вызов в сценарии 3 и укажите переменные, которые вы хотите использовать, но которые не   -  person Bergi    schedule 21.10.2012
comment
Не могли бы вы предоставить нам код?   -  person Aadit M Shah    schedule 21.10.2012
comment
Вопрос обновлен с кодом. Извините, я не могу предоставить полный код. Заранее спасибо за помощь.   -  person wanderlust    schedule 21.10.2012
comment
У меня нет опыта работы с Java/Rhino, но Script-2 не является допустимым идентификатором JavaScript. Назовите его Script2 или Script_2.   -  person J. K.    schedule 21.10.2012
comment
Спасибо, Ян, но упомянутые имена скриптов приведены только для иллюстрации. Фактические имена сценариев очень действительны.   -  person wanderlust    schedule 21.10.2012
comment
Похоже, что hmTCResult на самом деле не является глобальной переменной, как changeStatus. Возможно, ваша среда сценариев (я не знаю, как запускаются ваши три файла сценариев) выполняет все в масштабе всего файла. Попробуйте удалить ключевое слово var или явно назначить hmTCResult вашему глобальному объекту.   -  person Bergi    schedule 21.10.2012
comment
Спасибо Берги за ответ. Я попытался удалить ключевое слово var, но безуспешно. Я погуглил и обнаружил, что могу использовать window.hmTCResult, чтобы явно добавить его в глобальный объект. Однако, поскольку это не JavaScript, который можно выполнить в браузере, я не уверен, что это сработает. Каким-либо другим способом я могу назначить его для назначения глобальному объекту?   -  person wanderlust    schedule 21.10.2012


Ответы (3)


Чтобы оценить сценарий js на Java, можно выполнить следующую операцию.

ScriptEngine engine = new ScriptEngineManager().getEngineByMimeType( "text/javascript" );
Bindings bindings = engine.getBindings( ScriptContext.GLOBAL_SCOPE );
bindings.put( "varname", ... );
bindings.put( ... );
engine.put( ScriptEngine.FILENAME, script.toString());
engine.eval( new FileReader( script ));

Если 3 скрипта загружаются в один и тот же движок/привязки, все в порядке, но если движок заново выделен для выполнения script3, контекст очищается.

Этот пост на самом деле не ответ, но слишком длинный, чтобы быть комментарием.

person Aubin    schedule 22.10.2012
comment
Спасибо, Обин. Как я уже упоминал, мой инструмент, хотя и основан на Eclipse, больше похож на JavaScript IDE. Я не вижу кода Java в инструменте. - person wanderlust; 23.10.2012
comment
Хорошо, я этого не понимаю. Я изменил ваш вопрос, удалив Java, поскольку он не применяется. - person Aubin; 23.10.2012
comment
Обин, я не согласен. Если вы видите мой вопрос, я использую классы Java в JavaScript. Так что тег Java актуален. - person wanderlust; 23.10.2012

Я предполагаю, что без дополнительной информации и при условии, что ваши измененные стенограммы абсолютно верны, ваши сценарии выполняются в отдельных областях, все с глобальной областью в качестве родителя.

Таким образом, я предполагаю, что причина, по которой changeStatus работает в третьем скрипте, заключается в том, что для него нет объявления var. Таким образом, при отсутствии другой конфигурации это будет определено как переменная в области верхнего уровня или глобальной области, которая является общей для трех сценариев.

Я предполагаю, что причина, по которой hmTCResult не работает, заключается в том, что она объявлена ​​с ключевым словом var, указывающим на локальную переменную. Если бы все сценарии выполнялись в области верхнего уровня, это определило бы переменную в глобальном объекте. Но если каждый сценарий выполняется в своей области, это будет определять переменную только в области действия сценария 1. Вы не увидите проблемы в области действия сценария 2, потому что никто не выполняет код в сценарии 2 до сценария 3. выполняет.

person David P. Caldwell    schedule 21.11.2012

Это прекрасно работает, просто жонглируйте своими областями и настройте поиск прототипа:

Context cx = Context.enter();
try {
    // Cache and reuse:
    ScriptableObject sealedSharedScope = cx.initStandardObjects(null,
            true);
    // Force the LiveConnect stuff to be loaded.
    String loadMe = "RegExp; getClass; java; Packages; JavaAdapter;";
    cx.evaluateString(sealedSharedScope, loadMe, "preLoadLazyLoad", 0,
            null);

    cx.evaluateString(sealedSharedScope, "varInRoot = 'blah';",
            "setVarInRoot", 0, null);

    // here you can put more cx.evaluateString calls to set up your
    // environment (eg. hmTCResult)

    // now connect a throw-away new scope into the hierarchy, with local
    // vars:
    Scriptable scope = cx.newObject(sealedSharedScope);
    // ensure that definitions in the root scope are found
    scope.setPrototype(sealedSharedScope);
    // ensure that new global variables are created in this scope (don't
    // use
    // var for them!)
    scope.setParentScope(null);

    cx.evaluateString(scope, "localVar = varInRoot;", "mySource", 0,
            null);
    assertEquals("blah", scope.get("localVar", scope).toString());
    // new var not in root:
    assertEquals(ScriptableObject.NOT_FOUND,
            sealedSharedScope.get("localVar", scope));
} finally {
    Context.exit();
}

Остерегайтесь, что scope.get не ищет цепочку прототипов — сделайте это сами!

Области не зависят от контекста и переживают Context.exit().

person Georg    schedule 27.11.2012