JBoss ASでbsh(BeanShell)デプロイヤを利用する
JBoss ASにはbsh(BeanShell)というスクリプト言語で記述されたコードをデプロイするbshデプロイヤサービスが標準で用意されている。BeanShellの構文はJavaと一緒なので習得のコストはゼロ。使うには.bshという拡張子のファイルを.warや.earなどの通常のアプリケーションと同じようにデプロイするだけ。
まずは一番簡単なサンプル。
print("hello world");
型指定が必要ないので、コンテナ内でEJB, JMS, JDBCなんかテストするのにすごく便利。catch構文なども型不要でcatch (ex) { }でおっけー。例えばEchoというパラメータを単にリターンするだけのEJB3を書いて、その呼び出しを行いたい場合はこんな感じ。echo()メソッドの呼び出しにキャストは必要ない。
print(new javax.naming.InitialContext("Echo/local").echo("hello world"));
ついでにJMSでQueueに一つメッセージを送信する例。
context = new javax.naming.InitialContext(); cf = context.lookup("ConnectionFactory"); destination = context.lookup("queue/TestQueue"); conn = cf.createQueueConnection(); session = conn.createQueueSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE); sender = session.createSender(destination); sender.send(session.createTextMessage("hello world")); sender.close(); session.close(); conn.close();
bshスクリプト自身はRunnableインタフェースを実装していることになっているので、別スレッドの処理を実装するのにも重宝する。また、start()/stop()メソッドがあるとJBoss ASのServiceMBeanとして認識されるので、この2つを組み合わせてメモリ量を定期的にダンプするようなサービスなら一瞬で書ける。
finished = false; interval = 10000; run() { while (!finished) { r = Runtime.getRuntime(); System.out.println("total: " + r.totalMemory() + ", free: " + r.freeMemory() + ", used:" + (r.totalMemory() - r.freeMemory())); Thread.sleep(interval); } } objectName() { return "bsh:service=PrintMemory"; } start() { finished = false; new Thread(this).start(); } stop() { finished = true; }
BeanShellでJBoss ASのServiceMBeanを記述する方法なんかはWikiにも載っている。
http://community.jboss.org/wiki/BSHDeployer
BeanShellの良いところはJava 1.4までの構文をそのまま解釈できるところ。型指定があってもなくてもどちらでも動作する。なので、ちょっとしたコード片の動作を確認したいときはそのまま.bshにコピペしてしまえば良い。
良くないところは細かい点でいくつかある。まず、今はもうメンテされていないということ。上にわざわざJava 1.4と書いたので、もう気づいている人もいるかもしれないが、Java 5で拡張されたGenericsや拡張for文などの構文は解釈できないし、恐らく今後も期待できない。あと、.bshファイル内では新しいクラスやインタフェースは定義できない。同じようにbshでServiceMBeanを記述したときにfoo()などの独自メソッドを用意しても、MBeanインタフェースに定義されたオペレーションとは認識されないのでJMX経由ではその定義したfoo()は呼び出せない。このような場合にはいつも通りJavaで記述してクラスファイルを作成する必要がある。これらの点についてはそこまでするのなら普通にJavaで書いたらいいじゃん、という程度のものなので、あまり気にはならないのだけど。
そうそう、構文エラーのあるBeanSellをデプロイしたときに、たまに何もエラー報告されずに静かに終了するパターンがあるので気をつけましょう。print文とかはさめば大体すぐわかるよ!