【コラム】

Java API、使ってますか?

34 スクリプト言語とJavaを結びつけるJSR 223

34/60

JSR 223: Scripting for the Java Platform

現在、Javaプラットフォームではスクリプト言語のサポートが急速に進められている。同時に、Java VM上で動作するさまざまなスクリプト言語の実装が登場しており、JavaプラットフォームはすでにJava言語という枠を飛び越え、マルチ言語環境に進化しようとしている。本連載第31回で紹介したBeanShellも、Javaベースのスクリプト言語のひとつだ。

今回取り上げるのは、そのようなさまざまなスクリプト言語とJavaを結びつける役割を果たす「JSR 223: Scripting for the Java Platform」だ。ご存知のように同APIはJava SE 6よりJavaの標準クラスライブラリとして統合されている。JSR 223ではJavaプログラム内で各種スクリプトを実行する、およびスクリプト側からJavaプログラムにアクセスするための標準的な方法が提供される。

JDK 6にはJavaで実装されたJavaScriptエンジンであるRhinoがバンドルされており、標準で利用できるようになっている。その他のスクリプト言語についても対応が進められていて、scripting.dev.java.netで公開されている最新の参照実装には各種エンジンが搭載されている。

最新の参照実装でいろいろなスクリプトを実行する

まず、JDK 6でJavaScriptを利用する方法をおさらいしておこう。スクリプトの実行にはjavax.script.ScriptEngineクラスを利用する。まずファクトリクラスであるjavax.script.ScriptEngineManagerのインスタンスを生成し、そこからScriptEngineを取得してeval()メソッドでスクリプトを実行すればよい。具体的にはリスト1のようになる。

リスト1 ScriptingForJavaScript.java - JavaプログラムでJavaScriptを実行

package apisample;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class ScriptingForJavaScript {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("js");

        try {
            engine.eval("print(\"Hello, JavaScript!\")");
        } catch (ScriptException ex) {
            ex.printStackTrace();
        }
    }
}

JavaScriptは標準でサポートされているので、ScriptingForJavaScript.javaは通常通りコンパイル/実行できる。

さて、JavaScript以外のスクリプト言語を利用するには別途JSR 223の参照実装を入手しなければならない。最新の実装は前述のプロジェクトサイトにあるドキュメント&ファイルセクションからダウンロードできる。jsr223-engines.zipまたは jsr223-engines.tar.gzを任意の場所 (ここでは[JSR223-ENGINES]と記載する) に解凍して使用する。

配布ファイルにはサポートされるスクリプトエンジン用のフォルダが含まれており、各フォルダ毎に以下の3つのフォルダが用意されている。

  • bin - コマンドライン環境実行用のシェルスクリプトまたはbatファイルを格納
  • build - JSR 223対応のエンジンを格納
  • lib - 各スクリプトの実装を格納

そのうちbinとbuildについてはすでに用意されているが、libに格納する実装だけはそれぞれのプロジェクトサイトから別途ダウンロードしてこなければならない。必要とするバージョンについてはREADME.TXTに記載されている。

ここではBeanShellを使用してみる。BeanShellの場合はバージョン2.0 Beta5が必要と書かれているが、BeanShellの公式サイトで配布されている最新版は2.0 Beta4なのでこれを使う。このページよりbsh-2.0b4.jarをダウンロードし、[JSR223-ENGINES]\beanshell\libに配置する。

このbsh-2.0b4.jarとbuildフォルダのbsh-engine.jarをクラスパスに含めることで、JavaプログラムからBeanShellを利用できるようになる。ためしにJDK 6付属のjrunscriptコマンドを使ってみよう。jrunscriptコマンドはqオプションで利用可能なスクリプト言語を調べることができ、lオプションでコマンドラインモードでスクリプトを実行できる(プロンプト1)。

プロンプト1 jrunscriptコマンドでBeanShellを利用する

> jrunscript -cp [JSR223-ENGINES]/build/bsh-engine.jar;[JSR223-ENGINES]/lib/bsh-2.0b4.jar -q
Language BeanShell 2.0b5 implemention "BeanShell Engine" 1.0
Language ECMAScript 1.6 implemention "Mozilla Rhino" 1.6 release 2

> jrunscript -cp [JSR223-ENGINES]/build/bsh-engine.jar;[JSR223-ENGINES]/lib/bsh-2.0b4.jar -l bsh
beanshell>

続いてJavaプログラムからBeanShellスクリプトを実行してみよう。手順はJavaScriptの場合とまったく同じで、リスト2のようにする。ここでは簡単なウィンドウを表示させるスクリプトを実行している(第31回参照)。

リスト2 ScriptingForBeanShell.java- JavaプログラムからBeanShellスクリプトを実行

package apisample;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class ScriptingForBeanShell {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("bsh");

        try {
            engine.eval(
                    "import javax.swing.*;" + 
                    "f = new JFrame(\"BeanShell Sample\");" + 
                    "f.getContentPane().setLayout(new FlowLayout());" + 
                    "button1 = new JButton(\"Hello\");" + 
                    "button2 = new JButton(\"BeanShell!\");" + 
                    "f.getContentPane().add(button1);" + 
                    "f.getContentPane().add(button2);" + 
                    "f.setSize(300, 200);" + 
                    "f.setVisible(true);"
            );
        } catch (ScriptException ex) {
            ex.printStackTrace();
        }
    }
}

コンパイルおよび実行は、スクリプトエンジンのJARファイルをクラスパスに含めてプロンプト2のように行う。実行するとBeanSehllスクリプトによって図1のようなウィンドウが表示されるはずだ。

プロンプト2 リスト2を実行

> javac -cp ./;[JSR223-ENGINES]/build/bsh-engine.jar;[JSR223-ENGINES]/lib/bsh-2.0b4.jar apisample\ScriptingForBeanShell.java
> java -cp ./;[JSR223-ENGINES]/build/bsh-engine.jar;[JSR223-ENGINES]/lib/bsh-2.0b4.jar apisample.ScriptingForBeanShell

図1 BeanShellスクリプトによって生成されたウィンドウ

次に、Javaプログラムからスクリプトのメソッドをコールしてみよう。メソッドのコールには、スクリプトエンジン(ScriptEngine実装)がjavax.script.Invocableインタフェースをimplementsしている必要がある。しかしBeanShellのエンジンはこれをimplementsしていないので(TODOということになっている)、今回はInvocableをサポートしているGroovyを使って試してみることにする。

README.TXTによればGroovyを使うには1.1-beta-2が必要とのことなので、公式サイトのリポジトリより「groovy-all-1.1-beta-2.jar」をダウンロードして[JSR223-ENGINES]\groovy\libに配置する。

プログラムはリスト3のようになる。ここではGroovyスクリプトでadd()メソッドを定義し、それをJavaプログラムからInvocableのinvokeFunction()を利用して呼び出している。

リスト3 ScriptingForGroovy.java - JavaプログラムからGroovyのメソッドを呼び出す

package apisample;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class ScriptingForGroovy {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("groovy");

        String script = "def add(x, y) { x + y }";
        try {
            engine.eval(script);
            Invocable invocable = (Invocable)engine;
            Object[] params = { new Integer(50), new Integer(100) };
            Object result = invocable.invokeFunction("add", params);
            System.out.println(result);
        } catch (ScriptException ex) {
            ex.printStackTrace();
        }
    }

}

コンパイルおよび実行は、Groovyのスクリプトエンジンをクラスパスに含めてプロンプト3のように行う。

プロンプト3 リスト3の実行

> javac -cp ./;[JSR223-ENGINES]/build/groovy-engine.jar;[JSR223-ENGINES]/lib/groovy-all-1.1-beta-2.jar apisample\ScriptingForGroovy.java
> java -cp ./;[JSR223-ENGINES]/build/groovy-engine.jar;[JSR223-ENGINES]/lib/groovy-all-1.1-beta-2.jar apisample.ScriptingForGroovy
150

JSR 223を使用すれば、JavaScriptだけでなくさまざまなスクリプト言語を共通の方法で利用できる。今回はBeanShellとGroovyを取り上げたが、ぜひ他のスクリプト言語も試してみてほしい。なお、Java SE 7ではJavaScriptに加えてBeanShellやGroovy、JRubyなどといったスクリプト言語の標準サポートが検討されている。

34/60

インデックス

連載目次
第60回 どうなる? 今後のJavaプラットフォーム(Java SE編)
第59回 どうなる? 今後のJavaプラットフォーム(Java EE編)
第58回 Java SE 7の要注目機能"クロージャ"はどうなるのか その6
第57回 Java SE 7の要注目機能"クロージャ"はどうなるのか その5
第56回 Java SE 7の要注目機能"クロージャ"はどうなるのか その4
第55回 Java SE 7の要注目機能"クロージャ"はどうなるのか その3
第54回 Java SE 7の要注目機能"クロージャ"はどうなるのか その2
第53回 Java SE 7の要注目機能"クロージャ"はどうなるのか
第52回 Early Draftが公開されたJSF 2.0
第51回 EJBから独立したJava Persistence 2.0
第50回 モバイルJavaの新しい潮流となるか - MSA 2.0のドラフト公開
第49回 やっぱり基本はServlet - Servlet 3.0のEarly Draftを読む
第48回 JOGLで3Dプログラミング その4
第47回 JOGLで3Dプログラミング その3
第46回 JOGLで3Dプログラミング その2
第45回 JOGLで3Dプログラミング
第44回 JARファイルを効率的にネットワーク転送するためのPack200形式
第43回 Early Draftで把握するEJB 3.1の新機能
第42回 次世代の携帯端末向けJava仕様"MIDP 3.0"はどうなるか その2
第41回 次世代の携帯端末向けJava仕様"MIDP 3.0"はどうなるか その1
第40回 リソースアダプタによる接続の仕組み
第39回 JCAを利用したシステム間接続
第38回 Java EEと外部システムの接続性を支えるJCAがバージョンアップ
第37回 Javaのモジュラリティ強化を担う"スーパーパッケージ"とは
第36回 JSR 308対応のコンパイラを試す
第35回 公開されたJSR 308のEarly Draftを検証する
第34回 スクリプト言語とJavaを結びつけるJSR 223
第33回 Java EE環境に統一されたコンポーネントモデルを提供するJSR 299 その2
第32回 Java EE環境に統一されたコンポーネントモデルを提供するJSR 299 その1
第31回 Javaの文法がそのまま使えるスクリプト言語"BeanShell"
第30回 Javaアプリケーションにオブジェクトのキャッシュ機構を提供するJCache API
第29回 Javaアプリケーションからのリソース管理を可能にするJSR 284
第28回 XMLデータソースへの問い合わせはJSR 225で
第27回 Portlet Specification 2.0をもっと手軽に利用する
第26回 次期Javaポートレット仕様となるJSR 286
第25回 JSFとポートレットをつなげるJSR 301
第24回 Webサービス向けのポートレット仕様「WSRP」
第23回 高い相互運用性を実現するポートレットAPI - JSR 168
第22回 Java EE環境でタスクのスケジューリングを可能にするJSR 236
第21回 Java EE環境でのスレッドプログラミングを可能にするJSR 237
第20回 音声認識/合成のためのAPI - Java Speech APIとJSR 113
第19回 JSR 291でJavaプラットフォームにダイナミックコンポーネントモデルを導入
第18回 JAX-RSで簡単RESTful - JSR 311
第17回 待望のServlet 3.0がJSRに登場 - JSR 315
第16回 アノテーションを使ってバグ退治 - JSR 305
第15回 アノテーションをさらに広い範囲で利用可能にするJSR 308
第14回 Webアプリケーション開発の要となるか - JSF 2.0がJSRに登場
第13回 Webサービス経由でのJMX Agentへの接続を可能にするJSR 262
第12回 Javaアプリケーションのモジュール化をサポートするJava Module System
第11回 "NIO.2"がやってきた - JSR 203: More New I/O APIs for the Java Platform
第10回 JSR 295: Beans Bindingの参照実装を試す
第9回 けっこう便利! 単位を扱うAPI -- JSR 275: Units Specification
第8回 アノテーションでバリデーション - JSR 303: Bean Validator
第7回 Swing開発の救世主となるか - Swing Application Framework
第6回 JavaBeansのプロパティを同期させるバインディングAPI
第5回 誰よりも早く"Java SE 7"を睨む
第4回 日時情報の取り扱いを改善する JSR 310: Date and Time API
第3回 古いAPIも進化している!? - JSR 919: JavaMail 1.4
第2回 JSR 1 リアルタイムJava仕様
第1回 JCPによって進められるJava関連技術の標準化

もっと見る

提供:マイナビ

会員登録はこちら

大学・大学院・短大・専門学生向けの就職情報サイト「マイナビ2010」「マイナビ2009」に今すぐ登録しよう!  大手企業からベンチャー企業までの約13,000社の企業情報を公開、エントリーが可能です。2010年卒予定の方は「マイナビ2010」に、2009年卒予定の方は「マイナビ2009」に登録してください。

毎日コミュニケーションズはプライバシーマークを取得しています。



人気記事

一覧

イチオシ記事

新着記事