Nashorn の GlobalScope にやられたので、帳票クリエータを Java8 + Rhino で動かしてみる

こんにちは、開発担当の Masa です。

前回に引き続き Nashorn のグローバルスコープに関する話題です。

現在発売されている「シーオーリポーツ 帳票クリエータ Ver.3 for Java」は Java8 では動作しません。
Java8 で標準搭載されているスクリプトエンジンがそれまでの Rhino から Nashorn へと変更され、
しかも Rhino と Nashorn は 100% の互換性を保っていないことが理由です。

今回のブログは、何とか Rhino との互換性を保とうとするプログラマの苦悩と、
いっそ Java8 + Rhino で動かしてしまえと言う開き直りについてお送りします。

第1章:苦悩
Nashorn では eval した変数や関数は特定のエンジンスコープに関連付けられます。
グローバルスコープの変数を別々のエンジンスコープを指定した eval で変更した場合、
変更内容は共有されません。

つまり、以下のプログラムを実行すると、Nashorn は 0、Rhino は 150 という出力結果が得られます。

public static void main(String[] args) {
  ScriptEngineManager manager = new ScriptEngineManager();
  manager.put("sum", 0);
        
  ScriptEngine engine = manager.getEngineByExtension("js");
  engine.eval("sum = 150;");
  engine.eval("print(sum);", engine.createBindings());
}

Nashorn の出力結果を Rhino と同様にしたい場合、"--global-per-engine" オプションを使用します。
"ScriptEngineManager#getEngine~" する前に System.setProperty("nashorn.args", "--global-per-engine") することで Rhino と同じ結果になりました。

ん~、コレだとクリエータ以外にも影響出ますよね。。。と、いうわけで別の方法を。

  NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
  ScriptEngine engine = factory.getScriptEngine(new String[] { "--global-per-engine" });

この方法だと影響範囲を生成したエンジンのみに固定できます。
ただし、"jdk.nashorn.api.scripting" パッケージに依存するので Java7 で実行すると
該当パッケージを使用したクラスがロードされた瞬間にエラーとなります
。。。

他にもイロイロ(本当にイロイロ)あるのですが、こんな感じで苦悩しながら1つ1つ対応中です。
ココロが折れそう。。。

 
第2章:Java8 + Rhino という選択
スクリプトエンジンにはこだわってないからとにかく Java8 でクリエータを動かしたい!という人には、Java8 + Rhino という選択もあります。

環境の構築方法はコチラで教えてくれてますね。

  • mozillaのサイトから "js.jar" をダウンロード(下の方にダウンロードリンクがあります)
  • "https://svn.java.net/svn/scripting~svn" からスクリプトエンジンの実装をチェックアウト
  • "任意の場所/trunk/engines/javascript/lib/js.jar" を ダウンロードした "js.jar" に置き換え
  • "任意の場所/trunk/engines/javascript/make/build.xml" を "ant clean all" で実行

ダウンロードした "js.jar" と コンパイルした "任意の場所/trunk/engines/javascript/build/js-engine.jar" を
クラスパスの通るディレクトリに置いて「シーオーリポーツ 帳票クリエータ Ver.3 for Java」を実行します。

筆者はデベロッパーズマニュアルの単票出力サンプルで試しましたが、正常に出力されました。
 
 
「シーオーリポーツ 帳票クリエータ Ver.3 for Java」は現在 Java8 に対応中です。
Nashorn のまま実行したい方は今しばらくお待ちください。