4.2. プログラミング・開発ガイド
JMSを利用するアプリケーションのプログラミング方法について説明します。JMSアプリケーションを作成するには次のAPIを利用します。
- JMS 2.0
- JNDI
- WebOTX JMQ拡張インタフェース
各APIの詳細は、[ リファレンス > APIリファレンス ] を参照してください。以降では、次のプログラミング内容について、Javaスタンドアロンアプリケーションをベースにして説明します。
-
アプリケーションプログラムを開発する前に
アプリケーションプログラムを開発する際に必要となる知識などについて説明しています。
-
QUEUEを使用したPTPプログラムの開発
Point-To-Pointメッセージングモデルを使用したアプリケーションのプログラミングについて説明しています。
-
TOPICを使用したPub/Subプログラムの開発
Publisher/Subscriberメッセージングモデルを使用したアプリケーションのプログラミングについて説明しています。
-
メッセージの非同期受信機能を使用したプログラムの開発
メッセージを非同期受信するためのプログラミングについて説明しています。
-
その他の機能を使用したプログラムの開発
JMSで提供されている、より高度な機能を使用したアプリケーションのプログラミングについて説明しています。
4.2.1. アプリケーションプログラムを開発する前に
4.2.1.1. インポートが必要なパッケージ
WebOTX JMQアプリケーションでは次のパッケージをインポートする必要があります。
表7.2.1.1-1
パッケージ
|
説明
|
javax.jms |
JMS APIパッケージ |
javax.naming |
コネクションファクトリ、および送信先のルックアップに必要なJNDIパッケージ |
4.2.1.2. アプリケーションプログラム作成の流れ
WebOTX JMQを利用したアプリケーションプログラム作成の流れを説明します。
- メッセージングモデルを決定する。
- 使用するメッセージのタイプおよびメッセージの永続性を決定する。
- コンシューマのメッセージ受信形態を決定する。
- アプリケーションをコーディングする。
- Java コンパイラでアプリケーションをコンパイルする。
- アプリケーションを実行する。
4.2.1.3.
メッセージングモデル
JMSでサポートされている2つのメッセージングモデルについて説明します。
ポイントツーポイント
ポイントツーポイント (PTP) メッセージングモデルでは、メッセージキューを介して1対1でメッセージの送受信をおこないます。PTPメッセージングモデルでは、QueueReceiverがJMSに接続していない状態でQueueSenderから送信されたメッセージは、QueueReceiverが接続されるか、またはメッセージが期限切れになるまでJMSで保持されます。
PTPアプリケーションではJMSで提供されている次のクラスを利用する必要があります。
表7.2.1.3-1
クラス名
|
説明
|
QueueConnectionFactory |
ポイントツーポイントJMSプロバイダを保持するQueueConnectionオブジェクトを作成するためのファクトリクラスです。JNDIから、登録したファクトリ名でルックアップします。 |
QueueConnection |
ポイントツーポイントJMSプロバイダへのアクティブなコネクションを提供するクラスです。QueueConnectionFactory.createQueueConnection() メソッドで生成します。 |
QueueSession |
QueueReceiver、QueueSender、QueueBrowser、およびTemporaryQueueオブジェクトを作成するためのクラスです。QueueConnection.createQueueSession() メソッドで生成します。 |
QueueSender |
メッセージをキューに送信するためのクラスです。QueueSession.createSender() メソッドで生成します。 |
QueueReceiver |
キューに配信されたメッセージを受信するためのクラスです。QueueSession.createReceiver() メソッドで生成します。 |
Queue |
プロバイダ固有のキュー名をカプセル化したクラスです。JNDIから、登録したキュー名でルックアップします。 |
パブリッシュ/サブスクライブ (Pub/Sub)
パブリッシュ/サブスクライブ (Pub/Sub) メッセージングモデルでは、トピックを介して複数のサブスクライバが同じメッセージを受信することができます。メッセージは、すべてのサブスクライバがメッセージを受信するまで保持されます。
Pub/Subメッセージングモデルでは、TopicPublisherがメッセージを送信した時点でJMSに接続しているTopicSubscriberに対してのみ配信されます。未接続のTopicSubscriberに対しても接続後にメッセージを配信するために、持続性サブスクライバがサポートされています。持続性サブスクライバを使用したプログラムの開発については、「
持続性サブスクライバを使用したプログラム」を参照してください。
Pub/SubアプリケーションではJMSで提供されている次のクラスを利用する必要があります。
表7.2.1.3-2
クラス名
|
説明
|
TopicConnectionFactory |
パブリッシュ/サブスクライブJMSプロバイダを保持するTopicConnectionオブジェクトを作成するためのファクトリクラスです。JNDIから、登録したファクトリ名でルックアップします。 |
TopicConnection |
パブリッシュ/サブスクライブJMSプロバイダへのアクティブなコネクションを提供するクラスです。TopicConnectionFactory.createTopicConnection() メソッドで生成します。 |
TopicSession |
TopicPublisher、TopicSubscriber、およびTemporaryTopicオブジェクトを作成するためのクラスです。TopicConnection.createTopicSession() メソッドで生成します。 |
TopicPublisher |
メッセージをトピックに送信するためのクラスです。TopicSession.createPublisher() メソッドで生成します。 |
TopicSubscriber |
トピックに配信されたメッセージを受信するためのクラスです。TopicSession.createSubscriber() メソッドでサブスクライバを生成し、TopicSession.createDurableSubscriber() メソッドで持続性サブスクライバを生成します。 |
Topic |
プロバイダ固有のトピック名をカプセル化したクラスです。JNDIから、登録したトピック名でルックアップします。 |
統合タイプ
JMS1.1から、2つのメッセージングモデルを統合した形のインタフェースが追加されています。これにより、JMSクライアントは同じコネクション、もしくは同じセッション上で2つのモデルを共存させることも可能になりました。
表7.2.1.3-3
クラス名
|
説明
|
ConnectionFactory |
Connectionオブジェクトを作成するためのファクトリクラスです。JNDIから、登録したファクトリ名でルックアップします。 |
Connection |
JMSプロバイダへのアクティブなコネクションを提供するクラスです。ConnectionFactory.createConnection() メソッドで生成します。 |
Session |
Destinationのタイプを特定せず、MessageProducer、MessageConsumer、TopicSubscriberおよびTemporaryQueueやTemporaryTopicオブジェクトを作成するためのクラスです。Connection.createSession() メソッドで生成します。 |
MessageProducer |
メッセージをDestinationに送信するためのクラスです。Session.createProducer() メソッドで生成します。 |
MessageConsumer |
Destinationに配信されたメッセージを受信するためのクラスです。Session.createConsumer() メソッドで生成します。Topicの持続性サブスクライバの生成には、Session.createDurableSubscriber() メソッドがあります。 |
Destination |
プロバイダ固有の情報をカプセル化したクラスです。JNDIから、登録したトピック名でルックアップします。 |
4.2.1.4. メッセージ
JMSで定義されているメッセージについて説明します。
JMSで定義されているメッセージタイプについて説明します。すべてのメッセージタイプは、javax.jms.Messageクラスを継承しています。
表7.2.1.4-1
メッセージタイプ
|
説明
|
javax.jms.Message |
すべてのJMSメッセージのルートインタフェースです。このインタフェースは、すべてのメッセージで使用されるメッセージヘッダおよびacknowledge() メソッドを定義します。 |
javax.jms.BytesMessage |
未解釈のバイトストリームを含むメッセージの送信に使用されます。メッセージの受信者は、バイト列に格納されているメッセージ本文を解釈する必要があります。 |
javax.jms.MapMessage |
名前と値のペアをセットとするメッセージの送信に使用されます。名前はStringオブジェクトで、値はJavaプログラミング言語のプリミティブデータ型です。エントリには名前でシーケンシャルまたはランダムにアクセスできます。エントリの順序は定義されていません。 |
javax.jms.ObjectMessage |
Javaプログラミング言語 (Javaオブジェクト) の直列化可能なオブジェクトを含むメッセージの送信に使用されます。使用できるのは、Serializable Javaオブジェクトだけです。 |
javax.jms.StreamMessage |
Javaプログラミング言語のプリミティブ値を含むストリームの送信に使用されます。書き込みおよび読み取りは連続して行われます。 |
javax.jms.TextMessage |
java.lang.Stringを含むメッセージの送信に使用されます。 |
メッセージの構成要素
・メッセージヘッダフィールド
すべてのJMSメッセージは、同一のヘッダフィールドセットをサポートします。ヘッダフィールドには、クライアントとプロバイダの両方がメッセージの識別および配信に使用する値が含まれます。メッセージヘッダで定義されているフィールドと、フィールドに値を設定するメソッドについて説明します。
表7.2.1.4-2
フィールド
|
説明
|
JMSDestination |
メッセージが配信される送信先 (キューまたはトピック) を指定します。メッセージが送信されるときには、この値は無視されます。メッセージが受信されるとき、その送信先の値は送信時に割り当てられた値と同じになります。 |
JMSDeliveryMode |
PERSISTENTまたはNON_PERSISTENTを指定します。JMSDeliveryModeは、メッセージ送信時に指定します。メッセージが送信されるときには、この値は無視されます。メッセージが受信されるときには、送信側のメソッドで指定された値が格納されています。 |
JMSExpiration |
メッセージの有効期限を指定します。JMSExpirationは、メッセージ送信メソッドで指定された存在時間と、WebOTX JMQがメッセージを受け付けた時点でのGMTを元に計算されます。アプリケーションで存続時間に0を指定した場合、JMSExpirationは0に設定され、メッセージは無期限になります。有効期限の切れたメッセージは、WebOTX JMQによって削除されます。また、設定により、転送先の送信先に転送することも可能です。 |
JMSPriority |
優先順位のレベルを指定します。JMSでは、0-9の10段階で優先順位が定義されています (0が最低の、9が最高の優先順位)。レベル0-4は通常の優先順位として、レベル5-9は至急の優先順位として順序付けられています。 |
JMSMessageID |
WebOTX JMQによって、送信される各メッセージをユニークに識別する文字列値が格納されます。すべてのJMSMessageIDはID:というプレフィックスで始まるように生成されます。メッセージが送信されるときには、この値は無視されます。メッセージが受信されるときには、WebOTX JMQが割り当てた値が格納されています。 |
JMSTimeStamp |
メッセージが送信されたときの時刻が格納されます。JMSTimeStampは、アプリケーションでメッセージが送信されたときではなく、WebOTX JMQで配信用にメッセージが受け付けられたときにメッセージに書き込まれます。このフィールドには、Javaのミリ時間の値が格納されます。 |
JMSCorrelationID |
WebOTX JMQのMessageID、アプリケーション固有の文字列、またはbyte配列のいずれかを指定します。JMSCorrelationIDはメッセージを相互に関連させるために使用します。アプリケーション固有の文字列を指定する場合は、文字列の先頭にプレフィクスID:を付けてはいけません。 |
JMSReplyTo |
応答メッセージが送信される送信先 (キューまたはトピック) を指定します。 |
JMSType |
送信時にアプリケーションで設定されたメッセージタイプ識別子が格納されます。 |
JMSRedelivered |
確認応答がないためメッセージを再配信するときに、WebOTX JMQでフラグを設定します。JMSReceliverdフラグが設定されている場合、何らかの理由で同じメッセージが以前に配信されている可能性があります。 |
・メッセージプロパティフィールド
各メッセージに含まれる組み込み機能は、アプリケーションで定義されたプロパティ値をサポートします。プロパティにより、アプリケーション定義のメッセージフィルタ機能をサポートする効率的な機構が提供されます。
・メッセージ本体
メッセージ本体は、javax.jms.Messageを継承した、各メッセージタイプで定義されています。メッセージタイプについては、「
メッセージタイプ」を参照してください。
メッセージの永続性
メッセージは、送信メソッド (javax.jms.QueueSender.send() または、javax.jms.TopicPublisher.publish()) にDeliveryModeパラメータを指定することによって、永続的か非永続的かを指定することができます。
永続メッセージは、少なくとも1回は確実にコンシューマに配信されます。永続メッセージは、WebOTX JMQによってデータストアに書き込まれます。永続化されたメッセージは、コンシューマからの確認応答によって、データストアから削除されます。
非永続メッセージは、データストアに書き込まれません。メッセージは最低1回は配信が保証されますが、システム障害等によって失われる可能性があります。
メッセージの確認応答
非トランザクションセッションで、確認応答モードがCLIENT_ACKNOWLEDGEに設定されている場合、コンシューマはメッセージを受信した際に確認応答をおこなう必要があります。受信したメッセージに対して確認応答をおこなうためには、javax.jms.Message.acknowledge() メソッドを呼び出します。
acknowledge() メソッドは、コンシューマが最後に確認応答したメッセージから現在のメッセージまでのすべてのメッセージに対して確認応答をおこないます。確認応答されていないメッセージは、再配信の対象となります。
4.2.1.5. 同期受信と非同期受信
メッセージの同期受信
メッセージを同期受信するには、javax.jms.MessageConsumer.receive() または、javax.jms.MessageConsumer.receiveNoWait() メソッドを呼び出します。
receive() メソッドを引数なしで呼び出した場合、メッセージを受信するまで呼び出しがブロックされます。タイムアウト値を指定して呼び出した場合、メッセージを受信するか、またはタイムアウトによって呼び出しが終了します。タイムアウト値に0を指定した場合、引数無しで呼び出した場合と同様の動作となります。
receiveNoWait() メソッドでは、メッセージを受信した場合は受信したメッセージを、メッセージを受信できなかった場合はnullを返却し、呼び出しはブロックされません。
メッセージの非同期受信
メッセージを非同期受信するには、MessageConsumer.setMessageListener() メソッドを呼び出して、javax.jms.MessageListenerインタフェースを実装した非同期メッセージリスナを登録する必要があります。MessageConsumerクラスのメソッドは、QueueReceiverおよび、TopicSubscriberクラスに継承されています。
非同期メッセージリスナでは、onMessage() メソッドを実装します。onMessage() メソッドの実装例については、「
メッセージの非同期受信機能を使用したプログラムの開発」を参照してください。
プロデューサから送信されたメッセージがonMessage() メソッドの引数に設定されて呼び出されます。
4.2.1.6. 非同期受信での例外通知
コネクション切断時の例外の受信
メッセージを非同期受信する場合、ネットワーク障害やJMSサーバの停止によってアプリケーションとJMSサーバとのコネクションが切断した際に例外を認識することができません。アプリケーションで例外を認識するには、Connection.setExceptionListener() メソッドを呼び出して、javax.jms.ExceptionListenerインタフェースを実装した例外リスナを登録する必要があります。Connectionクラスのメソッドは、QueueConnectionおよび、TopicConnectionクラスに継承されています。
例外リスナでは、onException() メソッドを実装します。onException() メソッドの実装例については、「
その他の機能を使用したプログラムの開発」の「
JMSの例外リスナを使用したプログラム」を参照してください。
発生したJMS例外がonException() メソッドの引数に設定されて呼び出されます。
4.2.2. QUEUEを使用したPTPプログラムの開発
PTPプログラムでは、Queueを利用するためのJMSクラスを使用します。PTPプログラムで使用するJMSクラスについては、「
メッセージングモデル」を参照してください。以降では、TextMessageを送受信するための、プロデューサおよび同期型コンシューマプログラムの記述例を示します。
4.2.2.1. 共通部分のプログラミング
ここでは、MessageProducerと、MessageConsumerに共通な処理について説明します。
JMSサーバと接続し、QueueSenderまたはQueueReceiverオブジェクトを生成するためには、QueueConnectionオブジェクトおよび、QueueSessionオブジェクトを利用します。これらのオブジェクトを入手するためには、QueueConnectionFactory、QueueConnection、QueueSessionの順にオブジェクトを取得する必要があります。
ConnectionFactoryオブジェクトの取得
QueueConnectionオブジェクトを取得するために、QueueConnectionFactoryオブジェクトをJNDIからルックアップします。
javax.naming.InitialContext context;
javax.jms.QueueConnectionFactory queueConnectionFactory;
try {
context = new
InitialContext();
queueConnectionFactory =
(javax.jms.QueueConnectionFactory)context.lookup("MyQCF");
} catch (Exception e) {
}
Connectionオブジェクトの生成
QueueSessionオブジェクトを取得するために、QueueConnectionオブジェクトを取得します。
javax.jms.QueueConnectionFactory queueConnectionFactory;
javax.jms.QueueConnection queueConnection;
try {
queueConnection = queueConnectionFactory.createQueueConnection();
} catch (Exception e) {
}
Sessionオブジェクトの生成
QueueSenderオブジェクト、QueueReceiverオブジェクトを取得するために、QueueSessionオブジェクトを取得します。
javax.jms.QueueConnection queueConnection;
javax.jms.QueueSession queueSession;
try {
queueSession = queueConnection.createQueueSession(false,
javax.jms.Session.CLIENT_ACKNOWLEDGE);
} catch (Exception e) {
}
4.2.2.2. MessageProducer固有部分のプログラミング
Queueにメッセージを送信するために、QueueSenderオブジェクトを取得します。QueueSenderオブジェクト取得時に指定するQueueオブジェクトは、JNDIからルックアップしてください。
Senderオブジェクトの生成
QueueSenderオブジェクトをQueueSessionオブジェクトから取得します。
java.lang.String queueName = "MyQueue";
javax.naming.InitialContext context;
javax.jms.QueueSession queueSession;
javax.jms.QueueSender queueSender;
javax.jms.Queue queue;
try {
queue = (javax.jms.Queue)context.lookup(queueName);
queueSender = queueSession.createSender(queue);
} catch (Exception e) {
}
Messageの生成
送信するTextMessageオブジェクトをQueueSessionオブジェクトから生成します。
javax.jms.QueueSession queueSession;
javax.jms.TextMessage message;
try {
message = queueSession.createTextMessage("SampleMessage");
} catch (Exception e) {
}
Messageの送信
QueueSenderオブジェクトのsend() メソッドを呼び出して、TextMessageオブジェクトを送信します。
javax.jms.QueueSender queueSender;
javax.jms.TextMessage message;
try {
queueSender.send(message);
} catch (Exception e) {
}
4.2.2.3. MessageConsumer固有部分のプログラミング
Queueからメッセージを受信するために、QueueReceiverオブジェクトを取得します。QueueReceiverオブジェクト取得時に指定するQueueオブジェクトは、JNDIからルックアップしてください。
Receiverオブジェクトの生成
QueueReceiverオブジェクトをQueueSessionオブジェクトから取得します。
java.lang.String queueName = "MyQueue";
javax.naming.InitialContext context;
javax.jms.QueueSession queueSession;
javax.jms.QueueReceiver queueReceiver;
javax.jms.Queue queue;
try {
queue = (javax.jms.Queue)context.lookup(queueName);
queueReceiver = queueSession.createReceiver(queue);
} catch (Exception e) {
}
Connectionの開始
Queueからのメッセージを受信するために、QueueConnectionオブジェクトを開始します。
javax.jms.QueueConnection queueConnection;
try {
queueConnection.start();
} catch (Exception e) {
}
Messageの受信
QueueReceiverオブジェクトのreceive() メソッドを呼び出して、Queueからメッセージを受信します。
javax.jms.QueueReceiver queueReceiver;
javax.jms.Message message;
try {
message = queueReceiver.receive();
if (message instanceof javax.jms.TextMessage) {
System.out.println("Received message : " +
((javax.jms.TextMessage)message).getText());
} else {
// ignore
}
} catch (Exception e) {
}
確認応答の送信
受信したMessageのacknowledge() メソッドを呼び出して、確認応答します。
javax.jms.Message message;
try {
message.acknowledge();
} catch (Exception e) {
}
Connectionの停止
プログラム終了時には、JMSサーバ側の資源を解放するために、QueueConnectionオブジェクトのclose() メソッドを呼び出してください。
javax.jms.QueueConnection queueConnection;
if (queueConnection != null) {
try {
queueConnection.close();
} catch (Exception e) {
}
}
4.2.3. TOPICを使用したPub/Subプログラムの開発
Pub/Subプログラムでは、Topicを利用するためのJMSクラスを使用します。Pub/Subプログラムで使用するJMSクラスについては、「
メッセージングモデル」を参照してください。以降では、TextMessageを送受信するための、プロデューサおよび同期型コンシューマプログラムの記述例を示します。
4.2.3.1. 共通部分のプログラミング
ここでは、MessageProducerと、MessageConsumerに共通な処理について説明します。
JMSサーバと接続し、TopicPublisherまたはTopicSubscriberオブジェクトを生成するためには、TopicConnectionオブジェクトおよび、TopicSessionオブジェクトを利用します。これらのオブジェクトを入手するためには、TopicConnectionFactory、TopicConnection、TopicSessionの順にオブジェクトを取得する必要があります。
ConnectionFactoryオブジェクトの取得
TopicConnectionオブジェクトを取得するために、TopicConnectionFactoryオブジェクトをJNDIからルックアップします。
javax.naming.InitialContext context;
javax.jms.TopicConnectionFactory topicConnectionFactory;
try {
context = new InitialContext();
topicConnectionFactory =
(javax.jms.TopicConnectionFactory) context.lookup("MyTCF");
} catch (Exception e) {
}
Connectionオブジェクトの生成
TopicSessionオブジェクトを取得するために、TopicConnectionオブジェクトを取得します。
javax.jms.TopicConnectionFactory topicConnectionFactory;
javax.jms.TopicConnection topicConnection;
try {
topicConnection = topicConnectionFactory.createTopicConnection();
} catch (Exception e) {
}
Sessionオブジェクトの生成
TopicPublisherオブジェクト、TopicSubscriberオブジェクトを取得するために、TopicSessionオブジェクトを取得します。
javax.jms.TopicConnection topicConnection;
javax.jms.TopicSession topicSession;
try {
topicSession = topicConnection.createTopicSession(false,
javax.jms.Session.CLIENT_ACKNOWLEDGE);
} catch (Exception e) {
}
4.2.3.2. MessageProducer固有部分のプログラミング
Topicにメッセージを送信するために、TopicPublisherオブジェクトを取得します。TopicPublisherオブジェクト取得時に指定するTopicオブジェクトは、JNDIからルックアップしてください。
Publisherオブジェクトの生成
TopicPublisherオブジェクトをTopicSessionオブジェクトから取得します。
java.lang.String topicName = "MyTopic";
javax.naming.InitialContext context;
javax.jms.TopicSession topicSession;
javax.jms.TopicPublisher topicPublisher;
javax.jms.Topic topic;
try {
topic = (javax.jms.Topic) context.lookup(topicName);
topicPublisher = topicSession.createPublisher(topic);
} catch (Exception e) {
}
Messageの生成
送信するTextMessageオブジェクトをTopicSessionオブジェクトから生成します。
javax.jms.TopicSession topicSession;
javax.jms.TextMessage message;
try {
message = topicSession.createTextMessage("SampleMessage");
} catch (Exception e) {
}
Messageの送信
TopicPublisherオブジェクトのpublish() メソッドを呼び出して、TextMessageオブジェクトを送信します。
javax.jms.TopicPublisher topicPublisher;
javax.jms.TextMessage message;
try {
topicPublisher.publish(message);
} catch (Exception e) {
}
4.2.3.3. MessageConsumer固有部分のプログラミング
Topicからメッセージを受信するために、TopicSubscriberオブジェクトを取得します。TopicSubscriberオブジェクト取得時に指定するTopicオブジェクトは、JNDIからルックアップしてください。
Subscriberオブジェクトの生成
TopicSubscriberオブジェクトをTopicSessionオブジェクトから取得します。
java.lang.String topicName = "MyTopic";
javax.naming.InitialContext context;
javax.jms.TopicSession topicSession;
javax.jms.TopicSubscriber topicSubscriber;
javax.jms.Topic topic;
try {
topic = (javax.jms.Topic) context.lookup(topicName);
topicSubscriber = topicSession.createSubscriber(topic);
} catch (Exception e) {
}
Connectionの開始
Topicからのメッセージを受信するために、TopicConnectionオブジェクトを開始します。
javax.jms.TopicConnection topicConnection;
try {
topicConnection.start();
} catch (Exception e) {
}
Messageの受信
TopicSubscriberオブジェクトのreceive() メソッドを呼び出して、Topicからメッセージを受信します。
javax.jms.TopicSubscriber topicSubscriber;
javax.jms.Message message;
try {
message = topicSubscriber.receive();
if (message instanceof javax.jms.TextMessage) {
System.out.println("Received message : " +
((javax.jms.TextMessage) message).getText());
} else {
// ignore
}
} catch (Exception e) {
}
確認応答の送信
TopicSessionオブジェクト生成時に、Session.CLIENT_ACKNOWLEDGEを指定した場合、受信したMessageのacknowledge() メソッドを呼び出して、確認応答します。
javax.jms.Message message;
try {
message.acknowledge();
} catch (Exception e) {
}
Connectionの停止
プログラム終了時には、JMSサーバ側の資源を解放するために、TopicConnectionオブジェクトのclose() メソッドを呼び出してください。
javax.jms.TopicConnection topicConnection;
if( topicConnection != null) {
try {
topicConnection.close();
} catch (Exception e){
}
}
4.2.4. メッセージの非同期受信機能を使用したプログラムの開発
非同期受信プログラムでは、MessageListenerインタフェースを実装し、MessageConsumerオブジェクトに登録する必要があります。以降では、PTPプログラムでTextMessageを受信するための、非同期型コンシューマプログラムの記述例を示します。
4.2.4.1. 共通部分のプログラミング
QueueSessionを取得するまでの処理内容は、PTPプログラムと同じです。共通部分のプログラミングについては、「
QUEUEを使用したPTPプログラムの開発」の「
共通部分のプログラミング」を参照してください。
4.2.4.2. MessageConsumer固有部分のプログラミング
Queueからメッセージを非同期に受信するために、MessageListenerインタフェースを実装したクラスのインスタンスを生成して、QueueReceiverオブジェクトに登録します。QueueReceiverオブジェクト取得時に指定するQueueオブジェクトは、JNDIからルックアップしてください。
Receiverオブジェクトの生成
QueueReceiverオブジェクトをQueueSessionオブジェクトから取得します。
java.lang.String queueName = "MyQueue";
javax.naming.InitialContext context;
javax.jms.QueueSession queueSession;
javax.jms.QueueReceiver queueReceiver;
javax.jms.Queue queue;
try {
queue = (javax.jms.Queue) context.lookup(queueName);
queueReceiver = queueSession.createReceiver(queue);
} catch (Exception e) {
}
MessageListenerインタフェースの実装
MessageListenerインタフェースを実装します。
public static class TextListener implements javax.jms.MessageListener
{
public void onMessage(javax.jms.Message message)
{
try {
if (message instanceof javax.jms.TextMessage) {
System.out.println("Received message : "
+ ((javax.jms.TextMessage) message).getText());
} else {
// ignore
}
} catch (Exception e) {
}
}
}
MessageListenerの登録
TextListenerクラスのインスタンスを生成してQueueReceiverに登録します。
javax.jms.QueueReceiver queueReceiver;
TextListener textListener;
try {
textListener = new TextListener();
queueReceiver.setMessageListener(textListener);
} catch (Exception e) {
}
Connectionの開始
Queueからのメッセージを受信するために、QueueConnectionオブジェクトを開始します。
javax.jms.QueueConnection queueConnection;
try {
queueConnection.start();
} catch (Exception e) {
}
Messageの受信
受信するメッセージを引数として、登録したTextListenerのonMessage() メソッドが呼ばれます。
確認応答の送信
TopicSessionオブジェクト生成時に、Session.CLIENT_ACKNOWLEDGEを指定した場合、受信したMessageのacknowledge() メソッドを呼び出して、確認応答します。
javax.jms.Message message;
try {
message.acknowledge();
} catch (Exception e) {
}
Connectionの停止
プログラム終了時には、JMSサーバ側の資源を解放するために、QueueConnectionオブジェクトのclose() メソッドを呼び出してください。
javax.jms.QueueConnection queueConnection;
if (queueConnection != null) {
try {
queueConnection.close();
} catch (Exception e) {
}
}
4.2.5. その他の機能を使用したプログラムの開発
4.2.5.1. 持続性サブスクライバを使用したプログラム
JMSサーバと接続し、TopicSubscriberオブジェクトを生成するためには、TopicConnectionオブジェクトおよび、TopicSessionオブジェクトを利用します。これらのオブジェクトを入手するためには、TopicConnectionFactory、TopicConnection、TopicSessionの順にオブジェクトを取得する必要があります。
TopicSessionを取得するまでの処理内容は、Pub/Subプログラムと共通です。共通部分のプログラミングについては、「
TOPICを使用したPub/Subプログラムの開発」の「
共通部分のプログラミング」を参照してください。
持続性サブスクリプション用サブスクライバの生成
持続性のあるTopicSubscriberオブジェクトをTopicSessionから取得します。
java.lang.String topicName = "MyTopic";
java.lang.String DurSubName = "TestSubscriberName";
javax.naming.InitialContext context;
javax.jms.TopicSession topicSession;
javax.jms.TopicSubscriber topicSubscriber;
javax.jms.Topic topic;
try {
topic = (javax.jms.Topic) context.lookup(topicName);
topicSubscriber = topicSession.createDurableSubscriber(topic, DurSubName);
} catch (Exception e) {
}
Connectionの開始
Topicからのメッセージを受信するために、TopicConnectionオブジェクトを開始します。
javax.jms.TopicConnection topicConnection;
try {
topicConnection.start();
} catch (Exception e) {
}
サブスクライバの停止
メッセージ受信終了時には、TopicSubscriberオブジェクトのclose() メソッドを呼び出してください。
javax.jms.TopicSubscriber topicSubscriber;
try {
topicSubscriber.close();
} catch (Exception e) {
}
持続性サブスクリプションの解除
持続性サブスクリプションの機能を停止し、JMSサーバが保持している状態を解除するために、TopicSessionオブジェクトのunsubscribe() メソッドを呼び出してください。
java.lang.String DurSubName = "TestSubscriberName";
javax.jms.TopicSession topicSession;
try {
topicSession.unsubscribe(DurSubName);
} catch (Exception e) {
}
Connectionの停止
JMSサーバ側の資源を解放するために、TopicConnectionオブジェクトのclose() メソッドを呼び出してください。
javax.jms.TopicConnection topicConnection;
if (topicConnection != null) {
try {
topicConnection.close();
} catch (Exception e) {
}
}
4.2.5.2. メッセージのフィルタリングを使用したプログラム
MessageConsumer (QueueReceiverオブジェクト、TopicSubscriberオブジェクト、DurableSubscriberオブジェクト) を取得する際に、メッセージセレクタを指定することで、メッセージのヘッダフィールドおよびプロパティを利用して受信したいメッセージのみを選択的に受信することができます。ここでは、メッセージセレクタを利用したメッセージのフィルタリングをおこなうプログラムについて説明します。
ここでは、メッセージのフィルタリングをおこなうPub/Subプログラムの記述例を示します。共通部分のプログラミングについては、「
TOPICを使用したPub/Subプログラムの開発」の「
共通部分のプログラミング」を参照してください。メッセージセレクタの記述については、javax.jms.Messageのメッセージセレクタの説明を参照してください。
メッセージセレクタを指定したSubscriberオブジェクトの生成
Topicからメッセージを受信するために、TopicSubscriberオブジェクトを取得します。TopicSubscriberオブジェクト取得時に指定するTopicオブジェクトは、JNDIからルックアップしてください。
プログラム例では、メッセージの優先順位 (ヘッダフィールドの「JMSPriority」の値) が「6」以上のメッセージのみを受信します。
java.lang.String MySelector = "JMSPriority >= 6";
java.lang.String topicName = "MyTopic";
javax.naming.InitialContext context;
javax.jms.TopicSession topicSession;
javax.jms.TopicSubscriber topicSubscriber;
javax.jms.Topic topic;
try {
topic = (javax.jms.Topic) context.lookup(topicName);
topicSubscriber = topicSession.createSubscriber(topic, MySelector, false);
} catch (Exception e) {
}
4.2.5.3. JMSのトランザクション機能を使用したプログラム
セッションオブジェクト生成時に、transactedパラメータにtrueを指定することで、セッションオブジェクトをトランザクションセッションとして生成することができます。トランザクションセッションを使用することで、メッセージの送受信をトランザクションとして実行することができます。トランザクションセッションでは、確認応答モードの指定は無視されます。ここでは、JMSのトランザクション機能を利用したプログラムについて説明します。
ここでは、JMSのトランザクション機能を利用したPTPプログラムの記述例を示します。共通部分のプログラミングについては、「
QUEUEを使用したPTPプログラムの開発」の「
共通部分のプログラミング」を参照してください。
トランザクションセッションの取得
QueueSessionオブジェクトを、トランザクションセッションとして取得します。
javax.jms.QueueConnection queueConnection;
javax.jms.QueueSession queueSession;
try {
queueSession = queueConnection.createQueueSession(true,
javax.jms.Session.SESSION_TRANSACTED);
} catch (Exception e) {
}
メッセージ送信でのトランザクションの終了
プロデューサプログラムで、メッセージを送信後トランザクションを終了します。トランザクションがコミットされた場合、トランザクション中 (前回のコミット後) に送信されたメッセージの送信処理が確定され、コンシューマへの配信が開始されます。トランザクションがロールバックされた場合、トランザクション中に送信されたメッセージは破棄されます。トランザクションの終了後は、自動的に次のトランザクションが開始されます。
プログラム例では、トランザクションをコミットします。
javax.jms.QueueSession queueSession;
javax.jms.QueueSender queueSender;
javax.jms.TextMessage message;
try {
queueSender.send(message);
queueSession.commit();
} catch (Exception e) {
}
メッセージ受信でのトランザクションの終了
コンシューマプログラムでメッセージ受信後、トランザクションを終了します。トランザクションがコミットされた場合、トランザクション中 (前回のコミット後) に受信したメッセージに対してJMSで確認応答され、永続情報が削除されます。トランザクションがロールバックされた場合、トランザクション中に受信したメッセージは、コンシューマでコミットされるか、再送回数に達するまで再送されます。トランザクションの終了後は、自動的に次のトランザクションが開始されます。
プログラム例では、トランザクションをコミットします。
javax.jms.QueueSession queueSession;
javax.jms.QueueReceiver queueReceiver;
javax.jms.Message message;
try {
message = queueReceiver.receive();
if (message instanceof javax.jms.TextMessage) {
System.out.println("Received message : " +
((javax.jms.TextMessage) message).getText());
} else {
// ignore
}
queueSession.commit();
} catch (Exception e) {
}
4.2.5.4. JMSの例外リスナを使用したプログラム
メッセージを非同期受信するコンシューマでは、ネットワーク障害やJMSサーバの停止によってJMSサーバとのコネクションが切断されたことを検出することができません。例外リスナを使用することでコネクション切断等のコネクションオブジェクトからの例外通知を受信や、JMSサーバとのコネクション切断を検出した際の再接続処理をプログラムすることができます。ここでは、JMSの例外リスナを利用したプログラムについて説明します。
ここでは、JMSの例外リスナを利用したPTPプログラムの記述例を示します。共通部分のプログラミングについては、「
QUEUEを使用したPTPプログラムの開発」の「
共通部分のプログラミング」を参照してください。
ExceptionListenerインタフェースの実装
ExceptionListenerインタフェースを実装します。プログラム例では、受信した例外を標準出力に出力後、QueueAsynchConsumerクラスのreconnectメソッドを呼び出して再接続処理を実行しています。
public class QueueAsynchConsumer {
private static void reconnect() {
// 再接続処理
}
public static class ExcpListener implements javax.jms.ExceptionListener {
public void onException(javax.jms.JMSException excp) {
System.out.println("Received JMSException : " + excp);
try {
QueueAsynchConsumer.reconnect();
} catch (Exception e) {
}
}
}
}
ExceptionListenerの登録
ExcpListenerクラスのインスタンスを生成してQueueConnectionに登録します。登録した例外リスナの登録を解除するためには、setExceptionListenerメソッドにnullを指定して呼び出します。
javax.jms.QueueConnection queueConnection;
ExcpListener excpListener;
try {
excpListener = new ExcpListener();
queueConnection.setExceptionListener(excpListener);
} catch (Exception e) {
}
4.2.5.5. JMSのイベント通知を使用したプログラム
コネクションイベントリスナや、コンシューマイベントリスナを使用することによって、コネクション切断/再接続や、送信先に対するコンシューマの存在に関するイベントを受信することができます。ここでは、イベントリスナの実装と、各イベントリスナの登録方法について示します。各インタフェースの詳細については、[ リファレンス >
APIリファレンス >
JMS >
拡張インタフェース ] を参照してください。
EventListenerインタフェースの実装
EventListenerインタフェースを実装します。コネクションイベントリスナの場合も、コンシューマイベントリスナの場合も実装するインタフェースは同じです。
public class AppEventListener implements com.nec.webotx.messaging.jms.notification.EventListener {
:
boolean consumerReady = false;
:
public void onEvent(com.nec.webotx.messaging.jms.notification.Event event) {
String eventCode = event.getEventCode();
if (com.nec.webotx.messaging.jms.notification.ConsumerEvent.CONSUMER_READY.equals(eventCode)) {
// CONSUMER_READYに対する処理
consumerReady = true;
} else if (com.nec.webotx.messaging.jms.notification.ConsumerEvent.CONSUMER_NOT_READY.equals(eventCode)) {
// CONSUMER_NOT_READYに対する処理
consumerReady = false;
} else if (com.nec.webotx.messaging.jms.notification.ConnectionClosedEvent.CONNECTION_CLOSED_LOST_CONNECTION.equals(eventCode)) {
// CONNECTION_CLOSED_LOST_CONNECTIONに対する処理
System.out.println("CONNECTION_CLOSED_LOST_CONNECTION : " + event.getEventMessage());
:
}
}
}
コネクションイベントリスナの登録
EventListener実装クラスのインスタンスを生成して、コネクションに登録します。イベントリスナを登録する際、コネクションオブジェクトは、com.nec.webotx.messaging.jms.Connection にキャストする必要があります。
なお、コネクションに対して、コネクションイベントリスナと、JMS例外リスナの両方を登録していた場合、呼び出される順番は、コネクションイベントリスナ、例外リスナの順になります。
javax.jms.Connection connection;
AppEventListener connEventListener;
:
try {
connEventListener = new AppEventListener();
((com.nec.webotx.messaging.jms.Connection) connection).setEventListener(connEventListener);
} catch (Exception e) {
// 例外処理
}
コンシューマイベントリスナの登録と削除
EventListener実装クラスのインスタンスを生成し、対象となる送信先を指定して、コネクションに登録します。イベントリスナの登録や削除をする際、コネクションオブジェクトは、com.nec.webotx.messaging.jms.Connection に、また、送信先オブジェクトは、com.nec.webotx.messaging.Destination にキャストする必要があります。
javax.jms.Connection connection;
javax.jms.Queue queue;
AppEventListener consumerEventListener;
try {
consumerEventListener = new AppEventListener();
// コンシューマイベントリスナ登録
((com.nec.webotx.messaging.jms.Connection) connection).setConsumerEventListener(
(com.nec.webotx.messaging.Destination) queue, consumerEventListener);
:
// コンシューマイベントリスナ削除
((com.nec.webotx.messaging.jms.Connection) connection).removeConsumerEventListener((com.nec.webotx.messaging.Destination) queue);
} catch (Exception e) {
// 例外処理
}
4.2.6. 注意事項
4.2.6.1. アプリケーションプログラム作成時の注意事項
コンシューマプログラムでの注意
- コンシューマプログラムでは、Connectionオブジェクトのstart() メソッドを呼び出すまでメッセージが配信されません。メッセージ受信開始時には、必ずstart() メソッドを呼び出してください。
持続性サブスクリプション解除時の注意
- 持続性サブスクリプションを解除する際、次の条件のいずれかに当てはまる場合は解除できません。
- TopicSubscriberがセッション中でアクティブな場合
- 持続性サブスクリプションで受信したメッセージがトランザクションの一部であるか、またはセッション中でまだ確認応答されていない場合
4.2.6.2. アプリケーションプログラム実行時の注意事項
Java実行環境に関する注意
- システム中に異なるバージョンのJava実行環境が存在する場合、JNDIサーバとJMSアプリケーションで使用するJVMが同一バージョンとなるように注意してください。異なるバージョンのJVMで実行した場合、予期せぬエラーが発生する可能性があります。