待ち望まれていたJava EE 7がついに、JMS 2.0とともにリリースされた。これは10年以上使われてきたJMSに対する最初のアップグレードになる。
最新のJMS仕様で最も注目すべきところは、Oracleが"Simplified" APIと呼んでいるスリムな表現だ。たとえば、メッセージを送受信するための新しいAPIを使うことで、多くのボイラープレートコードを取り除くことができ、必要なコード量を劇的に削減することができる。アプリケーションサーバで動かしているなら、新しいAPIはリソースインジェクションをサポートしている。アプリケーションサーバはJMSオブジェクトを管理できるようになり、アプリケーションはさらにシンプルになる。
フレームワークは完全に後方互換性があり、レガシーコードを使い続けたまま、新規コードにSimplified APIを使うことができる。古いAPIが非サポートになる予定はない。
JMS 2.0はJava EE 7プラットフォームの一部だが、スタンドアロンのJava SEプラットフォームでも使うことができる。ただし、すべての機能がどちらでも使えるわけではない。
サンプルコードを使って、新旧APIを比較してみよう。
リスト1. メッセージを送信するJMS 1.0構文
1 public void sendMessage(ConnectionFactory factory, Queue queue, String message) { 2 try { 3 Connection connection = factory.createConnection(); 4 try { 5 Session session = connection.createSession( false, Session.AUTO_ACKNOWLEDGE); 6 MessageProducer messageProducer = session.createProducer(queue); 7 TextMessage textMessage = session.createTextMessage(message); 8 9 messageProducer.send(textMessage); 10 11 } finally { 12 connection.close(); 13 } 14 } catch (JMSException e) { 15 // handle exception 16 } 17 }
リスト2. 同じメッセージを送信するJMS 2.0構文
18 public void sendMessage(ConnectionFactory factory, Queue queue, String message) { 19 try (JMSContext context = factory.createContext()) { 20 21 context.createProducer().send(queue, message); 22 23 } catch (JMSRuntimeException e) { 24 // handle exception 25 } 26 }
変更を見ていこう。まず最初は、19行目にあるJava 7の"try-with-resources"の利用だ。これまでのConnectionクラスとSessionクラスを新しいAutoCloseable JMSContextで置き換えている。これをtry節(19行目)に入れることで、もとの"try"にあったセットアップコード(4、11、12、13行目)は不要になる。メッセージ生成も暗黙のうちに行われ、コードは以前よりもずっとスリムになる。
また、古いチェックされるJMSExceptionはチェックされないJMSRuntimeExceptionに置き換えられ、明示的に捕捉する必要はなくなる。
これがメッセージ送信側のコードだ。メッセージ受信側のコードも同様にシンプルになる。
Simplified APIは新しいJMS 2.0 APIの一部にすぎない。他にも新しいセマンティックス強化がいくつかある。次のような機能がサポートされる。
- 非同期送信モード - サーバからACKが返ってくるまでブロックする従来の同期モードに対して、非同期モードの場合はブロックせずに即座に返ってくる。そしてACKを受信すると、非同期コールバックが呼び出される。非同期モードは新しいJMSProducerとレガシーなMessageProducerの両方でサポートされる。たとえば、次のようなインターフェイスでCompletionListenerを定義することができる。
public interface CompletionListener { void onCompletion(Message message); void onException(Message message, Exception exception); }
メッセージを送信するときには、次のように呼び出す。
messageProducer.send(message,completionListener);
- 遅延メッセージ配信 - JMSクライアントはメッセージ配信をスケジュールすることができる。これにより、一日の終わりに配信するといった遅延処理をサポートすることができる。アプリケーションでは、消費者に配信する前にシステムがメッセージを保持すべき最小時間を、ミリ秒で設定することができる。
MessageProducerとJMSProducerとで、APIはよく似ている。
MessageProducerの場合:public void setDeliveryDelay(long deliveryDelay)
JMSProducerの場合:public JMSProducer setDeliveryDelay(long deliveryDelay)
- 同じトピックサブスクリプションを共有することで、トピックサブスクリプションからのメッセージ消費をスケール可能にする。
非永続サブスクリプションのための新しいメソッドが提供される。
MessageConsumer messageConsumer = session. createSharedConsumer(topic,sharedSubscriptionName);
既存のメソッドは永続サブスクリプションに使われる。
MessageConsumer messageConsumer = session. createDurableConsumer(topic,durableSubscriptionName);
これらは数ある新機能のほんの一部にすぎない。すべての新機能に関するサンプルコード付きの詳しいチュートリアルが、OTNの記事"What's New in JMS 2.0"にある。