Oracle® Fusion Middleware Oracle WebLogic Server JMSアプリケーションの開発 12c (12.1.2) E48081-02 |
|
前 |
次 |
この章では、WebLogic JMSの付加価値機能を使用してJMSアプリケーションをプログラム的に管理する方法について説明します。
以下の節では、ロールバックまたはリカバリしたメッセージを管理する方法について説明します。
一時的または外部的な要因でアプリケーションがメッセージを正しく処理できない場合に、メッセージの再配信を遅延させることができます。これによって、アプリケーションは、現時点では処理できない「有害な」メッセージを一時的に受信できないようにすることができます。メッセージがロールバックまたはリカバリされる場合、再配信遅延は、メッセージが止められてから再配信が試行されるまでの間隔です。
JMSでメッセージをすぐに再配信すると、エラーの原因が解決されず、アプリケーションはメッセージを処理できないままの場合があります。ただし、アプリケーションが再配信遅延用に構成されている場合、メッセージがロールバックまたはリカバリされると、メッセージは再配信の遅延が過ぎるまで止められます。遅延の期間を過ぎた時点でメッセージを再配信できるようになります。
セッションによって消費された結果、ロールバックまたはリカバリしたすべてのメッセージは、ロールバックまたはリカバリ時にそのセッションの再配信遅延を受信します。単一のユーザー・トランザクションの一部として複数のセッションで消費されたメッセージは、個々のメッセージを消費したセッションの機能として異なる再配信遅延を受信します。意識的か、または失敗の結果、クライアントによる確認応答またはコミットされていないメッセージには、再配信遅延が割り当てられません。
セッションは、作成時に接続ファクトリから再配信遅延を継承します。接続ファクトリのRedeliveryDelay
属性は、管理コンソールで構成します。
詳細は、Oracle WebLogic Server管理コンソール・オンライン・ヘルプの接続ファクトリの構成に関する項を参照してください。
セッションを作成するアプリケーションは、javax.jms.Session
インタフェースに対するWebLogic固有の拡張を使用して接続ファクトリ設定をオーバーライドできます。セッション属性は動的なので、いつでも変更できます。セッションの再配信遅延を変更すると、メッセージが非恒久トピックを使用するセッション内にある場合を除いて、変更後にそのセッションで消費およびロールバック(またはリカバリ)されるすべてのメッセージに影響します。
注意: セッションで非恒久トピックを使用している場合、 |
セッションに対して再配信遅延を設定するメソッドは、javax.jms.Session
インタフェースの拡張であるweblogic.jms.extensions.WLSession
インタフェースを介して提供されます。セッションの再配信遅延を定義するには、以下のメソッドを使用します。
public void setRedeliveryDelay( long redeliveryDelay ) throws JMSException; public long getRedeliveryDelay( ) throws JMSException;
WLSession
クラスの詳細は、weblogic.jms.extensions.WLSession
のJavadocを参照してください。
再配信遅延がセッションで設定されているかどうかに関係なく、メッセージがロールバックまたはリカバリされる宛先で再配信遅延の設定をオーバーライドできます。メッセージの再配信に割り当てられた再配信遅延のオーバーライドは、メッセージがロールバックまたはリカバリされるときに有効になります。
宛先のRedeliveryDelayOverride
属性は、管理コンソールで構成します。詳細については、以下を参照してください。
Oracle WebLogic Server管理コンソール・オンライン・ヘルプのキューに関するメッセージ配信の失敗オプションの構成に関する項
Oracle WebLogic Server管理コンソール・オンライン・ヘルプのトピックに関するメッセージ配信の失敗オプションの構成に関する項
WebLogic JMSによるアプリケーションへのメッセージ再配信の試行回数に制限を設けることができます。宛先へのメッセージの再配信の失敗が指定した回数に達すると、そのメッセージ宛先に関連付けられたエラー宛先にメッセージをリダイレクトできます。再配信の制限が構成されていて、エラー宛先が構成されていない場合、永続メッセージまたは非永続メッセージは再配信の制限に達すると削除されます。
かわりに、メッセージ・プロデューサのsetメソッドを使用して、再配信の制限値を動的に設定できます(「メッセージ・プロデューサ属性の設定」を参照)。
宛先によるコンシューマへのメッセージ再配信の試行が指定した再配信制限に達すると、宛先はメッセージを配信不能にします。RedeliveryLimit
属性は、宛先で設定され、管理コンソールで構成できます。この設定は、メッセージのプロデューサ側で設定された再配信制限をオーバーライドします。詳細については、以下を参照してください。
Oracle WebLogic Server管理コンソール・オンライン・ヘルプのキューに関するメッセージ配信の失敗オプションの構成に関する項
Oracle WebLogic Server管理コンソール・オンライン・ヘルプのトピックに関するメッセージ配信の失敗オプションの構成に関する項
配信されなかったメッセージのエラー宛先がJMSサーバーに構成されている場合は、宛先に配信できないと判断されたメッセージが指定したエラー宛先にリダイレクトされます。エラー宛先はトピックまたはキューのいずれかですが、定義されている宛先と同じJMSサーバーに構成する必要があります。エラー宛先が構成されていない場合、配信されなかったメッセージは削除されます。
ErrorDestination
属性は、管理コンソールを使用して、スタンドアロンの宛先および共通分散宛先に構成します。詳細については、以下を参照してください。
Oracle WebLogic Server管理コンソール・オンライン・ヘルプのキューに関するメッセージ配信の失敗オプションの構成に関する項
Oracle WebLogic Server管理コンソール・オンライン・ヘルプのトピックに関するメッセージ配信の失敗オプションの構成に関する項
Oracle WebLogic Server管理コンソール・オンライン・ヘルプの共通分散キュー - 配信の失敗パラメータの構成に関する項
Oracle WebLogic Server管理コンソール・オンライン・ヘルプの共通分散トピック - 配信の失敗パラメータの構成に関する項
プロデューサからコンシューマに最初に配信されるすべてのメッセージは、作成された順序でコンシューマに届くことが保証されます。WebLogic JMSはこの要件を満たすだけでなく、さらに「メッセージの再配信の順序付け」機能を提供しています。この機能は、再配信メッセージについても正しい順序を保証します。
この保証を提供するために、WebLogic JMSでは特定の制約を課す必要があります。制約は次のとおりです。
単独のコンシューマ - 順序付き再配信は、単独のコンシューマが存在する場合にのみ保証されます。複数のコンシューマが存在する場合、個々のコンシューマがメッセージを受信する順序は保証されません。
注意: MDB (メッセージドリブンBean)については、コンシューマ数は、ある特定のMDB用にデプロイされたMDBインスタンス数の関数です。インスタンス数の初期値および最大値は1に設定する必要があります。そうでない場合、再配信メッセージに関する順序付けは保証できません。 |
ソート順序 - ある特定の宛先がソートの対象でJMS宛先キーが定義されている場合、別のメッセージが生成されて、そのメッセージが順序付けの先頭に置かれると、再配信される既存メッセージと配信される受信メッセージの間で順序の保証はできません。
メッセージの選択 - コンシューマがセレクタを使用している場合、再配信での順序付けは、再配信対象のメッセージと、そのセレクタの基準に一致する他のメッセージの間でのみ保証されます。セレクタに一致しないメッセージに関しては順序は保証されません。
再配信の遅延 - メッセージに再配信遅延期間が設定されており、リカバリまたはロールバックされた場合、そのメッセージはその期間にわたって使用できなくなります。この期間中は、他のメッセージを(遅延メッセージのあとに送信されたものであっても)先に配信できます。
リカバリを保留しているメッセージ - 順序付き再配信は、サーバーの障害やシステムの再起動が原因で、リカバリ状態を保留することになった再配信メッセージには適用されません。
WebLogicメッセージング・ブリッジまたはMDBを使用する非同期コンシューマやJMSアプリケーションでは、メッセージ・パイプラインのサイズを1に設定する必要があります。パイプラインのサイズは、受信側アプリケーションが使用するJMS接続ファクトリの「最大メッセージ数」属性を使用して設定します。1より大きい値は、再配信メッセージの前に追加の送信中メッセージがある可能性を示します。MDBアプリケーションでは、アプリケーションに固有のJMS接続ファクトリを定義し、その接続ファクトリの「最大メッセージ数」属性の値を1に設定する必要があります。さらに、MDBアプリケーションのEJB記述子で接続ファクトリを参照する必要があります。
EJBのプログラミングの詳細は、『Oracle WebLogic Server Enterprise JavaBeansバージョン2.1の開発』のメッセージドリブンEJBに関する項を参照してください。
WebLogic JMSには、アクティブなメッセージ有効期限ポリシーが用意されています。このポリシーでは、期限切れメッセージの検索方法と処理方法を設定できます。この機能では、単純に期限切れメッセージを破棄するか、期限切れメッセージを破棄してそれをログに記録するか、または期限切れメッセージをローカルJMSサーバーのエラー宛先に転送することによって期限切れメッセージが即座に消去できます。
アプリケーションへのメッセージ配信を、将来の指定した時間にスケジューリングできます。短い期間(秒や分など)の後でメッセージを配信することも、長い期間をおいた後で配信(数時間単位でバッチ処理する場合など)することもできます。その配信時間になって配信されるまでメッセージは表示されないため、将来の特定の時間に作業をスケジューリングできます。
メッセージが送信されるのは1回だけで、繰返し送信されることはありません。メッセージが繰返し送信されるようにするには、受信したスケジューリング済みのメッセージを元の送信先に戻す必要があります。一度のみというセマンティクスを保証するため、受信、送信、およびこれらに関連する作業は同じトランザクションのもとで行われます。
個々のプロデューサに対する配信時間の設定および取得のサポートは、javax.jms.MessageProducer
インタフェースの拡張であるweblogic.jms.extensions.WLMessageProducer
インタフェースを介して提供されます。個々のプロデューサに対して配信時間を定義するには、以下のメソッドを使用します。
public void setTimeToDeliver( long timeToDeliver ) throws JMSException; public long getTimeToDeliver( ) throws JMSException;
WLMessageProducer
クラスの詳細は、weblogic.jms.extensions.WLMessageProducer
のJavadocを参照してください。
DeliveryTime
は、メッセージを配信するのに最も早い絶対時間を定義できるJMSメッセージ・ヘッダーです。つまり、メッセージはメッセージング・システムによって保持され、その時間になるまでどのコンシューマにも配信されません。
DeliveryTime
は、JMSヘッダー・フィールドとして宛先でのメッセージのソート、またはメッセージの選択に使用できます。データ型変換の目的で、配信時間は長整数として保存されます。
注意: メッセージの配信時間の値を設定しても、このフィールドには影響しません。これは、メッセージが送信またはパブリッシュされるたびに、JMSがこの値をプロデューサの値でオーバーライドするためです。ここで説明するメッセージ配信時間の方法は、プロデューサによって設定される他のJMSメッセージ・フィールド(配信モード、優先度、配信時間、存続時間、再配信遅延、再配信制限など)と似ています。特に、これらのフィールドの設定はJMSプロバイダ(WebLogic JMSを含む)用に予約されます。 |
個々のメッセージに対する配信時間の設定および取得のサポートは、javax.jms.Message
インタフェースの拡張であるweblogic.jms.extensions.WLMessage
インタフェースを介して提供されます。メッセージの配信時間を定義するには、以下のメソッドを使用します。
public void setJMSDeliveryTime( long deliveryTime ) throws JMSException; public long getJMSDeliveryTime( ) throws JMSException;
WLMessage
クラスの詳細は、weblogic.jms.extensions.WLMessage
のJavadocを参照してください。
作成されたプロデューサは、接続の作成に使用する接続ファクトリ(プロデューサもそこに含まれます)からTimeToDeliver
属性(ミリ秒)を継承します。配信時間がプロデューサで設定されているかどうかに関係なく、メッセージが送信またはパブリッシュされる宛先で配信時間の設定をオーバーライドできます。管理者は、相対形式またはスケジューリング済み文字列形式のいずれかで宛先に対するTimeToDeliverOverride
属性を設定できます。
指定した存続時間の値(JMSExpiration
)が指定した配信時間と同じかそれより少ない場合、メッセージの配信は成功します。ただし、メッセージは通知されずに期限切れになります。
スケジューリング済みTimeToDeliverOverride
はweblogic.jms.extensions.Schedule
クラスを使用しても指定できます。このクラスでは、スケジュールを取得し、次回のメッセージ配信時間を戻すメソッドが提供されています。
表6-1 メッセージ配信スケジュール
例 | 説明 |
---|---|
0 0 0,30 * * * * |
次の最も近い30分 |
* * 0,30 4-5 * * * |
午前4時から午前5時までの任意の30分のうち最初の分 |
* * * 9-16 * * * |
午前9時と午後5時の間(9:00.00 A.M. - 4:59.59 P.M.) |
* * * * 8-14 * 2 |
その月の第2火曜日 |
* * * 13-16 * * 0 |
日曜日の午後1時と午後5時の間 |
* * * * * 31 * |
その月の最後の日 |
* * * * 15 4 1 |
次に日曜日になる4月15日 |
0 0 0 1 * * 2-6;0 0 0 2 * * 1,7 |
平日の午前1時および週末の午前2時 |
cronに似た文字列がスケジュールの定義に使用されます。書式は、次のBNF構文で定義されます。
schedule := millisecond second minute hour dayOfMonth month dayOfWeek
second
フィールドを指定するためのBNF構文は次のとおりです。
second := * | secondList secondList := secondItem [, secondList] secondItem := secondValue | secondRange SecondRange := secondValue - secondValue
ミリ秒、分、時、日、月、曜日に対する同様のBNF文を2番目の構文から取得できます。各フィールドの値は、以下の範囲の正の整数で指定します。
milliSecondValue := 0-999 milliSecondValue := 0-999 secondValue := 0-59 minuteValue := 0-59 hourValue := 0-23 dayOfMonthValue := 1-31 monthValue := 1-12 dayOfWeekValue := 1-7
注意: これらの値は、 |
この構文を使用すると、2つの時間の間のすべての時間を示す値の範囲で各フィールドを表すことができます。たとえば、dayOfWeek
フィールドの2-6
は、月曜から金曜まで(双方の曜日を含む)を示します。また、カンマ区切りのリストで各フィールドを指定することもできます。たとえば、分フィールドの0,15,30,45
は、1時間内の15分おきの値を示します。さらに、個々の値と値の範囲の組合せで各フィールドを定義することもできます。たとえば、時フィールドの9-17,0
は、午前9時と午後5時の間と深夜12時を示します。
補足のセマンティクスは以下のとおりです。
セミコロン(;)で区切って複数のスケジュールが指定されている場合、次のスケジュール時間は、最も早い値を戻すスケジュールを基に決定されます。この使い方としては、曜日を基に変更されるスケジュールを指定する場合などがあります(下記の最後の例を参照)。
dayOfWeek
の値1は日曜日。
値*は、そのフィールドのあらゆる時間を示します。たとえば、月フィールドの*は、毎月という意味です。時フィールドの*は、毎時という意味です。
値l
、つまりlast
(大文字と小文字の区別はない)は、そのフィールドで可能な値で最も大きな値を示します。
日に対して月の最大値を超える値を指定すると、その月の最大値が指定されます。たとえば、うるう年の2月に対して31を指定した場合、スケジューラは、29と見なしてスケジューリングします。これは、月フィールドを31に設定すると、その月の最後の日が指定されるということです。
ミリ秒が指定される場合、1秒内で最も近い50番目の値に丸められます。値は0、19、39、59、...、979、および999です。したがって、0 - 40は0 - 39に丸められ、50 - 999は39 - 999に丸められます。
注意: このクラスの静的メソッドのいずれか1つに対するメソッド・パラメータとしてCalendarが指定されない場合、使用されるカレンダは、デフォルトの |
weblogic.jms.extensions.schedule
クラスには、反復時間式に一致する次のスケジュール時間を戻すメソッドがあります。この式は、TimeToDeliverOverride
と同じ構文を使用します。ミリ秒で返される時間は、相対でも絶対でもかまいません。
Schedule
クラスの詳細は、weblogic.jms.extensions.Schedule
のJavadocを参照してください。
次のメソッドを使用すると、指定した時間の後の次のスケジュール時間を定義できます。
public static Calendar nextScheduledTime( String schedule, Calendar calendar ) throws ParseException {
次のメソッドを使用すると、現在の時間の後の次のスケジュール時間を定義できます。
public static Calendar nextScheduledTime( String schedule, ) throws ParseException {
次のメソッドを使用すると、指定した時間の後の次のスケジュール時間を絶対ミリ秒で定義できます。
public static long nextScheduledTimeInMillis( String schedule, long timeInMillis ) throws ParseException
次のメソッドを使用すると、指定した時間の後の次のスケジュール時間を相対ミリ秒で定義できます。
public static long nextScheduledTimeInMillisRelative( String schedule, long timeInMillis ) throws ParseException {
次のメソッドを使用すると、現在の時間の後の次のスケジュール時間を相対ミリ秒で定義できます。
public static long nextScheduledTimeInMillisRelative( String schedule ) throws ParseException {
以下の節では、接続を管理する方法について説明します。
例外リスナーは、接続に問題が発生するとアプリケーションに非同期的に通知します。このメカニズムは、通知されない限り接続がメッセージの消費を待ち続ける場合に役立ちます。
注意: 例外リスナーの目的は、接続によってスローされたすべての例外をモニターすることではなく、本来なら配信されない例外を配信することです。 |
接続に対する例外リスナーを定義するには、次のConnection
メソッドを使用します。
public void setExceptionListener( ExceptionListener listener ) throws JMSException
接続に対するExceptionListener
オブジェクトを指定しなければなりません。
JMSプロバイダは、接続の問題を発見すると、次のExceptionListener
メソッドを使用して例外リスナー(定義されている場合)に通知します。
public void onException( JMSException exception )
JMSプロバイダは、このメソッドを呼び出すときに、問題を説明する例外を指定します。
接続に対する例外リスナーにアクセスするには、次のConnectionメソッドを使用します。
public ExceptionListener getExceptionListener( ) throws JMSException
特定の接続に関連付けられているメタデータにアクセスするには、次のConnection
メソッドを使用します。
public ConnectionMetaData getMetaData( ) throws JMSException
このメソッドは、JMSメタデータへのアクセスに使用するConnectionMetaData
オブジェクトを返します。次の表に、JMSメタデータのタイプと、それらにアクセスするために使用できるgetメソッドを示します。
表6-2 JMSメタデータ
JMSメタデータ | getメソッド |
---|---|
バージョン |
public String getJMSVersion( ) throws JMSException |
メジャー・バージョン |
public int getJMSMajorVersion( ) throws JMSException |
マイナー・バージョン |
public int getJMSMinorVersion( ) throws JMSException |
プロバイダ名 |
public String getJMSProviderName( ) throws JMSException |
プロバイダ・バージョン |
public String getProviderVersion( ) throws JMSException |
プロバイダ・メジャー・バージョン |
public int getProviderMajorVersion( ) throws JMSException |
プロバイダ・マイナー・バージョン |
public int getProviderMinorVersion( ) throws JMSException |
JMSXプロパティ名 |
public Enumeration getJMSXPropertyNames( ) throws JMSException |
ConnectionMetaData
クラスの詳細は、javax.jms.ConnectionMetaData
のJavadoc(http://docs.oracle.com/javaee/6/api/javax/jms/ConnectionMetaData.html
)を参照してください。
メッセージのフローを制御するために、次のstart()
メソッドとstop()
メソッドをそれぞれ使用して、接続を一時的に開始および停止できます。
start()
メソッドとstop()
メソッドの詳細は以下のとおりです。
public void start( ) throws JMSException public void stop( ) throws JMSException
新しく作成された接続は停止しています。接続が開始されるまで、メッセージは受信されません。一般に、他のJMSオブジェクトは、「JMSアプリケーションの設定」で説明するとおり、接続が開始される前からメッセージを処理するよう設定されます。メッセージは、停止している接続上に作成することはできますが、停止している接続に届けることはできません。
接続が開始されていれば、stop()
メソッドを使用して接続を停止できます。このメソッドは、次の手順を実行します。
すべてのメッセージの配信を中断します。接続が再起動されるか、そのメッセージに関連付けられている存続時間に達するまで、メッセージの受信を待っているアプリケーションは何も返しません。
現在メッセージを処理しているすべてのメッセージ・リスナーが完了するまで待機します。
一般に、JMSプロバイダは接続を作成するときに大量のリソースを割り当てます。接続が使用されなくなったら、その接続をクローズしてリソースを解放する必要があります。接続をクローズするには、次のメソッドを使用します。
public void close( ) throws JMSException
このメソッドは、次の手順を実行して系統的にシャットダウンを行います。
保留中のすべてのメッセージの受信を終了させます。アプリケーションは、クローズ時にメッセージを受信できない場合はメッセージまたはnullを戻す場合があります。
現在メッセージを処理しているすべてのメッセージ・リスナーが完了するまで待機します。
処理中のトランザクションを、そのトランザクション・セッション上でロールバックします(こうしたトランザクションが外部JTAユーザー・トランザクションの一部である場合を除く)。JTAユーザー・トランザクションの詳細は、「JTAユーザー・トランザクションの使い方」を参照してください。
クライアントが確認応答を行うセッションの確認応答は強制しません。確認応答を強制しないことにより、キューおよび信頼性の高い処理が要求される恒久サブスクリプション用のメッセージが失われなくなります。
接続をクローズすると、関連付けられているすべてのオブジェクトがクローズされます。受信メッセージのacknowledge()
メソッドを除いて、接続で作成または受信されたメッセージ・オブジェクトは引続き使用できます。クローズされた接続をクローズしても影響はありません。
注意: クローズされた接続のセッションから受信したメッセージを確認応答しようとすると、 |
以下の節では、セッションを管理する方法について説明します。
例外リスナーは、セッションに問題が発生すると、クライアントに非同期的に通知します。これは、通知されない限りセッションがメッセージの消費を待ち続ける場合に役立ちます。
注意: 例外リスナーの目的は、セッションによってスローされたすべての例外をモニターすることではなく、本来なら通知されない例外を通知することです。 |
セッションに対する例外リスナーを定義するには、次のWLSession
メソッドを使用します。
public void setExceptionListener( ExceptionListener listener ) throws JMSException
セッションに対するExceptionListener
オブジェクトを指定しなければなりません。
JMSプロバイダは、セッションの問題を発見すると、次のExceptionListener
メソッドを使用して例外リスナー(定義されている場合)に通知します。
public void onException( JMSException exception )
JMSプロバイダは、このメソッドを呼び出すときに、問題を説明する例外を指定します。
セッションに対する例外リスナーにアクセスするには、次のWLSession
メソッドを使用します。
public ExceptionListener getExceptionListener( ) throws JMSException
注意: 1つのセッションに対して1つのスレッドしか存在しないので、例外リスナーとメッセージ・リスナー(非同期メッセージ配信用に使用される)を同時に実行することはできません。そのため、問題が発生したときにメッセージ・リスナーが実行されている場合、そのメッセージ・リスナーが実行を完了するまで例外リスナーはブロックされます。メッセージ・リスナーの詳細は、「メッセージの非同期受信」を参照してください。 |
接続と同じように、JMSプロバイダはセッションを作成するときに大量のリソースを割り当てます。セッションが使用されなくなったら、そのセッションをクローズしてリソースを解放することをお薦めします。セッションをクローズするには、次のSession
メソッドを使用します。
public void close( ) throws JMSException
注意:
|
このメソッドは、次の手順を実行して系統的にシャットダウンを行います。
保留中のすべてのメッセージの受信を終了させます。アプリケーションは、クローズ時にメッセージを受信できない場合はメッセージまたはnullを戻す場合があります。
現在メッセージを処理しているすべてのメッセージ・リスナーが完了するまで待機します。
処理中のトランザクションをロールバックします(こうしたトランザクションが外部JTAユーザー・トランザクションの一部である場合を除く)。JTAユーザー・トランザクションの詳細は、「JTAユーザー・トランザクションの使い方」を参照してください。
クライアントが確認応答を行うセッションの確認応答は強制しません。これにより、キューおよび信頼性の高い処理が要求される恒久サブスクリプション用のメッセージが失われなくなります。
セッションをクローズすると、関連付けられているすべてのプロデューサとコンシューマもクローズされます。
注意:
|
以下の節では、宛先の作成と削除の方法について説明します。
宛先を動的に作成する方法については、以下のトピックを参照してください。
宛先の動的作成に関する手順については、以降の節で説明します。
次のいずれかの方法を使用して、JMS宛先(キューまたはトピック)を動的に削除できます。
JMSModuleHelperクラス(第7章「JMSモジュール・ヘルパーを使用したアプリケーションの管理」を参照)
管理コンソール
ユーザー定義JMXアプリケーション
JMSサーバーは削除された宛先をリアル・タイムに削除します。従って、削除を有効にするためにJMSサーバーを再デプロイする必要はありません。宛先の動的削除に関する手順については、以降の節で説明します。
宛先の削除を正常に完了するには、次の事前条件が満たされている必要があります。
削除する宛先は分散宛先のメンバーであってはなりません。詳細は、第9章「分散宛先の使用」を参照してください。
削除する宛先は他の宛先のエラー宛先であってはなりません。詳細については、「配信されなかったメッセージに対するエラー宛先の構成」を参照してください。
これらの事前条件のいずれかが満たされていない場合、削除は実行できません。
宛先を削除する場合、以下の動作とセマンティクスが適用されます。
既存メッセージの物理的な削除 - 削除した宛先のすべての恒久サブスクライバが永続的に削除されます。削除した宛先に格納されているすべてのメッセージ(永続および非永続)が、メッセージング・システムから永続的に削除されます。
プロデューサ、コンシューマ、およびブラウザの作成不可 - 宛先の削除後に、削除した宛先のプロデューサ、コンシューマ、またはブラウザをアプリケーションで作成することはできません。作成しようとすると、宛先が存在しない場合と同様に、アプリケーションはInvalidDestinationException
を受け取ります。
コンシューマのクローズ - 削除した宛先の既存のコンシューマがすべてクローズされます。コンシューマのクローズによってConsumerClosedException
が生成され、親セッションのExceptionListener
(存在する場合)に配信されます。この例外には「Destination was deleted」と示されます。
コンシューマがクローズされた時点でコンシューマに未処理のreceive()
処理がある場合、その処理は取り消され、呼出し側はメッセージが存在しないことを示すnull
を受け取ります。アプリケーションでclose()
以外の実行を試みると、クローズされたコンシューマのIllegalStateException
が発生します。
ブラウザのクローズ - 削除した宛先のブラウザがすべてクローズされます。アプリケーションでclose()
以外の実行を試みると、クローズされたブラウザのIllegalStateException
が発生します。ブラウザのクローズにより、ブラウザに関連付けられたすべての列挙値が暗黙的にクローズされます。
列挙値のクローズ - 削除した宛先の列挙値がすべてクローズされます。列挙値がクローズされた後の動作は、列挙値のクローズ前に実行した最後の呼出しによって異なります。hasMoreElements()
の呼出しでtrueの値が返され、以降にnextElement()
を呼び出していない場合は、列挙により次の要素を列挙できることが保証されます。その結果、詳細が生成されます。クローズ前の最後の呼出しがhasMoreElements()
を呼び出し、返された値がtrueであった場合は、以下の動作が適用されます。
nextElement()
の最初の呼出しではメッセージが返されます。
以降のnextElement()
の呼出しではNoSuchElementException
がスローされます。
nextElement()
の呼出し前にhasMoreElements()
を呼び出すと、trueが返されます。
nextElement()
の最初の呼出し前にhasMoreElements()
を呼び出すと、falseが返されます。
ある特定の列挙値が一度も呼び出されていないか、クローズ前の最後の呼出しがnextElement()
を呼び出した場合、またはクローズ前の最後の呼出しがhasMoreElements()
を呼び出し、返された値がfalseであった場合には、以下の動作が適用されます。
hasMoreElements()
の呼出しではfalseが返されます。
nextElement()
の呼出しではNoSuchElementException
がスローされます。
送信ブロック処理の取消し - 削除した宛先に対して送信された送信ブロック処理がすべて取り消されます。割当てを待機している送信処理はResourceAllocationException
を受け取ります。
コミットしていないトランザクションには影響しない - 宛先を削除しても、コミットしていない既存のトランザクションには影響しません。削除した宛先に関連付けられたコミットしていない作業は、トランザクションの一部として完了できます。ただし、宛先は削除されているため、すべての処理(ロールバック、コミットなど)で実際に実行されるのは関連付けられたメッセージの削除です。
永続メッセージがある宛先が、削除されてからすぐに再作成され、そのときJMSサーバーが動作中でなかった場合、JMSサーバーは宛先のバージョン番号(構成ファイルconfig.xml
のCreationTime
フィールドを使用)と永続メッセージ内の宛先バージョン番号を比較します。この場合、古い宛先に残っている永続メッセージのバージョン番号は、config.xml
ファイルにある再作成された宛先のバージョン番号よりも古い番号になります。JMSサーバーが再起動すると、残っている永続メッセージは破棄されます。
ただし、永続メッセージのバージョン番号が、再作成された宛先のconfig.xmlにあるバージョン番号よりも新しい場合は、宛先が削除されてから(JMSサーバーが動作中でない状態で)再作成されたときにシステム・クロックがロールバックされたか、異なるconfig.xml
が使用されています。この場合、JMSサーバーの起動が失敗します。永続メッセージを保存するために、永続メッセージ内のバージョン番号に一致するバージョン番号(
CreationTime
フィールド)をconfig.xml
に設定できます。または、config.xml
のバージョン番号を、永続メッセージ内のバージョン番号よりも新しい番号に変更できます。このようにすると、JMSサーバーは再起動時にメッセージを削除できます。
一時的な宛先を使用することで、サーバー定義の宛先の構成と作成に伴うシステム管理のオーバーヘッドを発生させずに、必要に応じてアプリケーションで宛先を作成できます。
JMSアプリケーションでは、JMSReplyTo
ヘッダー・フィールドを使用して、リクエストにレスポンスを戻すことができます。送信側アプリケーションでは、オプションとして、メッセージのJMSReplyTo
ヘッダー・フィールドをその一時的な宛先の名前に設定することで、使用している一時的な宛先を別のアプリケーションに対して公開できます。
一時的な宛先は、「一時的な宛先の削除」の説明のとおりにdelete()
メソッドを使用して削除されない限り、現在の接続が継続している間だけ存在します。
サーバーが再起動すると、メッセージは使用できなくなるので、すべてのPERSISTENT
メッセージは自動的にNON_PERSISTENT
メッセージになります。そのため、一時的な宛先は、再起動によるデータの消失が許されないビジネス・ロジックには適していません。
注意: 一時的な宛先は、JMSサーバーの「 |
以降の節では、一時的なキュー(PTP)または一時的なトピック(Pub/Sub)の作成方法について説明します。
次のQueueSession
メソッドを使用して、一時的なキューを作成できます。
public TemporaryQueue createTemporaryQueue( ) throws JMSException
たとえば、現在の接続が継続している間だけ存在するTemporaryQueue
への参照を作成するには、次のメソッド呼出しを使用します。
QueueSender = Session.createTemporaryQueue();
次のTopicSession
メソッドを使用して、一時的なトピックを作成できます。
public TemporaryTopic createTemporaryTopic( ) throws JMSException
たとえば、現在の接続が継続している間だけ存在する一時的なトピックへの参照を作成するには、次のメソッド呼出しを使用します。
TopicPublisher = Session.createTemporaryTopic();
一時的な宛先の使用が終了したら、次のTemporaryQueue
メソッドまたはTemporaryTopic
メソッドを使用して宛先を削除し、関連リソースを解放できます。
public void delete( ) throws JMSException
WebLogic JMSでは、恒久サブスクリプションおよび非恒久サブスクリプションがサポートされています。
恒久サブスクリプションの場合、WebLogic JMSでは、メッセージはサブスクライバに配信されるか、または期限切れになるまで永続ファイルまたはデータベースに格納されます。この場合、メッセージの配信時にサブスクライバがアクティブな状態でなくてもかまいません。サブスクライバを表すJavaオブジェクトが存在していれば、サブスクライバはアクティブであるとみなされます。恒久サブスクリプションは、Pub/Subメッセージングのみでサポートされています。
注意: 恒久サブスクリプションは、分散トピックに対しては作成できません。ただし、分散トピックのメンバーに対して恒久サブスクリプションを作成することはできます。こうすると、他のトピック・メンバーは、恒久サブスクリプションを持つメンバーにメッセージを転送します。分散トピックの使用方法については、第9章「分散宛先の使用」を参照してください。 |
非恒久サブスクリプションの場合、WebLogic JMSでは、メッセージはアクティブ・セッションを持つアプリケーションにのみ配信されます。アプリケーションがリスニングしていない間にトピックへ送信されたメッセージは、二度とそのアプリケーションに配信されません。つまり、非恒久サブスクリプションは、そのサブスクライバ・オブジェクトが存在している間だけ存続します。デフォルトでは、サブスクライバは非恒久です。
以降の節で説明する内容は、次のとおりです。
メッセージがサブスクライバに配信されるか、または期限切れになるまでWebLogic JMSがそのメッセージを保持できるようにするためには、永続ファイルまたはデータベース・ストアを構成してJMSサーバーに割り当てる必要があります。
「ストア」ノードを使用して、JMSファイル・ストアまたはJMS JDBCバッキング・ストアを作成します。
「JMSサーバー」>「構成」>「全般」タブのストア・フィールドのドロップダウン・リストから構成済みのストアを選択してJMSサーバーに割り当てます。
注意: 2つのJMSサーバーで同じバッキング・ストアを使用することはできません。 |
クライアントIDポリシーは、1つ以上のJMS接続がクラスタ内で同一のクライアントIDを使用できるかどうかを指定します。このポリシーの有効な値は次のとおりです。
RESTRICTED
: デフォルトです。このポリシーを使用する接続は、クラスタ内で特定のクライアントIDの所定の時間に1つのみ存在できます(接続が所定のクライアントIDを使用してすでに存在する場合、このポリシーを同一クライアントIDと併用して新しい接続を作成しようとする試行は、例外を表示して失敗します)。
UNRESTRICTED
: このポリシーを使用して作成された接続は、他の制限/無制限接続がすでに同一クライアントIDを使用する場合でも、任意のクライアントIDを指定できます。恒久サブスクリプションが無制限クライアントIDを使用して作成されるとき、そのサブスクリプションはweblogic.jms.extensions.WLSession.unsubscribe(Topic topic, String name)
を使用してのみクリーンアップできます。『Oracle WebLogic Server JMSアプリケーションの開発』の恒久サブスクリプションの管理に関する項を参照してください。
(使用するアプリケーションのアーキテクチャに排他的クライアントIDが必要にならないかぎり)特にサブスクリプション(恒久/非恒久)を共有する場合は、新しいアプリケーションに対してはクライアントIDポリシーをUnrestricted
を設定することをお薦めします。異なるクライアントIDポリシーを使用して作成されたサブスクリプションは、常に単独のサブスクリプションとして扱われます。Oracle WebLogic Server MBeanリファレンスのClientIdPolicyに関する項を参照してください。
WebLogicコンソールを使用して接続ファクトリ上で「クライアントIDポリシー」を設定する場合、Oracle WebLogic Server管理コンソール・オンライン・ヘルプの同一クライアントIDを使用した複数接続の構成に関する項を参照してください。接続ファクトリ設定は、Oracle WebLogic Server Java APIリファレンスの
WLConnection
インタフェースのsetClientIDPolicy
メソッドを使用して、プログラム的にオーバーライドできます。
高可用性アプリケーションの設計に必要な、高度な概念および共通分散トピック(UDT)の機能の詳細は、「共有サブスクリプションおよびクライアントIDポリシー」を参照してください。
恒久サブスクリプションをサポートするには、接続に対してクライアントIDを定義する必要があります。
注意: JMSクライアントIDは、WebLogicセキュリティ・レルムでのユーザー認証で使用されるWebLogic Serverユーザー名とは必ずしも一致しません。JMSアプリケーションに適合していれば、JMSクライアントIDをWebLogic Serverユーザー名に設定することは当然可能です。 |
クライアントIDは、以下の2つの方法で設定できます。
最初の方法は、クライアントIDを使用する接続ファクトリを構成することです。WebLogic JMSでは、この方法は各クライアントIDの構成時に別々の接続ファクトリの定義を追加することになります。アプリケーションでは、JNDIでそれ自身のトピック接続ファクトリがルックアップされ、それを使用して自身のクライアントIDを含む接続が作成されます。詳細は、Oracle WebLogic Server管理コンソール・オンライン・ヘルプを参照してください。
または、望ましい方法として、接続を作成してからアプリケーションで次のConnectionメソッドを呼び出して、接続にクライアントIDを設定する方法もあります。
public void setClientID( String clientID ) throws JMSException
この代替方法を使用する場合は、デフォルトの接続ファクトリを使用すると(アプリケーションに適合している場合)、構成情報を変更する必要がありません。ただし、恒久サブスクリプションに対応しているアプリケーションの場合は、トピック接続を作成したらすぐにsetClientID()
を呼び出すようにする必要があります。
クライアントIDが接続に対してすでに定義されている場合は、IllegalStateException
がスローされます。指定したクライアントIDが別の接続に対してすでに定義されている場合は、InvalidClientIDException
がスローされます。
注意:
|
クライアントIDを表示し、クライアントIDがすでに定義されているかどうかをテストするには、次のConnectionメソッドを使用します。
public String getClientID( ) throws JMSException
注意: 恒久サブスクリプションのサポートは、Pub/Subメッセージング・モデル固有の機能なので、クライアントIDはトピック接続でしか使用できません。キュー接続にもクライアントIDがありますが、JMSでは使用されません。 恒久サブスクリプションは、一時的なトピックに対しては作成しないでください。一時的なトピックは、現在の接続が継続している間だけ存在するように設計されているからです。 |
サブスクリプション共有ポリシーは、サブスクライバがサブスクリプションを同一接続上の他のサブスクリプションを共有できるかどうかを指定します。このポリシーの有効な値は次のとおりです。
Exclusive
: デフォルトです。この接続ファクトリを使用して作成されるすべてのサブスクライバは、サブスクリプションを他のサブスクリプションと共有できません。このポリシーを使用してWebLogic Server 10.3.4.0以前の機能を保持できます。
Sharable:
この接続ファクトリを使用して作成されたサブスクライバは、サブスクライバが同一の接続ファクトリまたは異なる接続ファクトリのどちらを使用して作成されたかに関係なく、サブスクリプションを他のサブスクライバと共有できるようになります。コンシューマは、同一のクライアントIDおよびクライアントIDポリシーを持つ場合にのみ非永続サブスクリプションを共有できます。また、同一のクライアントID、クライアントIDポリシー、およびサブスクリプション名を持つ場合にのみ永続スクリプトを共有できます。
WebLogic JMSアプリケーションは、javax.jms.Connection
インスタンスをweblogic.jms.extension.WLConnection
にキャストしてsetSubscriptionSharingPolicy(String)
を呼び出すことによって、接続ファクトリ構成上で指定されるサブスクリプション共有ポリシーをオーバーライドできます。
共有可能なサブスクリプション共有ポリシーを使用する大半のアプリケーションは、同一クライアントIDを使用する複数の接続が存続できることを保証するために無制限クライアントIDポリシーも使用できます。
同一クライアントIDおよびサブスクリプション名を持つ2つの恒久サブスクリプションは、異なるクライアントIDポリシーを持つ場合、2種類の独自のサブスクリプションとして扱われます。同様に、同一クライアントIDを持つ2つの共有可能な非恒久サブスクリプションは、異なるクライアントIDポリシーを持つ場合、2種類の独自のサブスクリプションとして扱われます。
サブスクリプション共有ポリシーを使用する方法の詳細は、次を参照してください。
Oracle WebLogic Server管理コンソール・オンライン・ヘルプの接続ファクトリ・サブスクリプション共有ポリシーの構成に関する項。
以下のTopicSession
メソッドを使用して、恒久サブスクリプション用のサブスクライバを作成できます。
public TopicSubscriber createDurableSubscriber( Topic topic, String name ) throws JMSException public TopicSubscriber createDurableSubscriber( Topic topic, String name, String messageSelector, boolean noLocal ) throws JMSException
サブスクライバを作成するトピックの名前と恒久サブスクリプションの名前を指定する必要があります。
注意: 恒久サブスクリプションの名前に含めることのできない文字は、カンマ(,)、等号(=)、コロン(:)、アスタリスク(*)、パーセント記号(%)、および疑問符(?)です。 |
また、メッセージをフィルタ処理するためのメッセージ・セレクタ、およびnoLocal
フラグ(この節で後述)を指定することもできます。メッセージ・セレクタの詳細は、「メッセージのフィルタ処理」を参照してください。messageSelector
を指定しない場合、デフォルトではすべてのメッセージが検索されます。
アプリケーションでは、JMS接続を使用して同じトピックに対してパブリッシュとサブスクライブの両方を実行できます。トピック・メッセージはすべてのサブスクライバに配信されるので、アプリケーションは自身がパブリッシュしたメッセージを受信する可能性があります。これを防ぐために、JMSアプリケーションはnoLocal
フラグをtrue
に設定できます。noLocal
値は、デフォルトではfalse
になっています。恒久サブスクリプションはファイルまたはデータベース内に格納されます。
問題が発生したJMS接続については、ベスト・プラクティスとして、アプリケーションでJVMガベージ・コレクションを使用してクリーンアップするのではなく、JMSクライアントで常にclose()
メソッドを呼び出してクリーンアップすることをお薦めします。これは、JMS自動再接続機能では、問題が発生したJMS接続への参照が保持されるため、恒久サブスクリプションのClientIDに関しては特に重要です。したがって、常にconnection.close()
を使用して接続をクリーンアップします。また、接続リソースを確実にクリーンアップするため、finally
ブロックを使用することも検討してください。このようにしない場合、接続を使用可能な状態に維持するためにシステム・リソースが割り当てられてしまいます。
次のコード・スニペットでは、close()
およびfinally
をJMSクライアントで使用して問題が発生した接続リソースをクリーンアップする例を示しています。
JMSConnection con = null; try { con = cf.createConnection(); con.setClientID("Fred"); // Do some I/O stuff; } finally { if (con != null) con.close(); }
JMS自動再接続機能の詳細は、「JMSクライアントの自動フェイルオーバー」を参照してください。
恒久サブスクリプションを削除するには、次のTopicSession
メソッドを使用します。
public void unsubscribe( String name ) throws JMSException
削除する恒久サブスクリプションの名前を指定する必要があります。
以下の条件のいずれかに当てはまる場合は、恒久サブスクリプションを削除できません:
TopicSubscriber
がセッションでまだアクティブです。
恒久サブスクリプションで受信したメッセージがトランザクションの一部であるか、またはセッションでまだ確認応答されていません。
恒久サブスクリプションを変更するには、次のステップを実行します:
必要に応じて、「恒久サブスクリプションの削除」の手順に従って恒久サブスクリプションを削除します。
この手順は省略可能です。この手順が明示的に実行されない場合は、次の手順で恒久サブスクリプションが再作成されるときに暗黙的に削除が行われます。
「恒久サブスクリプション用のサブスクライバの作成」で説明されているメソッドを使用して、同じ名前の恒久サブスクリプションを再作成します。ただし、トピック名、メッセージ・セレクタ、noLocal
のいずれかには異なる値を指定します。
新しい値に基づいて、恒久サブスクリプションが再作成されます。
注意: 恒久サブスクリプションを再作成する場合には、重複した名前を持つ恒久サブスクリプションを作成しないよう注意してください。たとえば、使用できないJMSサーバーから恒久サブスクリプションを削除しようとすると、削除は失敗します。続いて、別のJMSサーバーで同じ名前の恒久サブスクリプションを作成すると、最初のJMSサーバーが使用可能になったときに予期しない結果が生じることがあります。元の恒久サブスクリプションが削除されていないため、最初のJMSサーバーが再び使用可能になると、重複した名前の2つの恒久サブスクリプションが存在することになります。 |
管理コンソールまたはパブリックな実行時APIを使用して、恒久トピック・サブスクライバをモニターおよび管理できます。恒久サブスクライバ上のすべてのメッセージを表示、参照したり、ほとんどのメッセージを操作したりすることもできます。こうした管理機能には、メッセージの参照(ソート目的)、メッセージの操作(移動、削除など)、メッセージのインポートとエクスポートなどがあります。詳細は、『Oracle WebLogic Server JMSリソースの管理』のJMSメッセージの管理に関する項を参照してください。
WebLogic JMSには、メッセージの識別および転送を定義できる一連の標準ヘッダー・フィールドが用意されています。さらに、プロパティ・フィールドを使用すると、標準セットを拡張した、アプリケーション固有のヘッダー・フィールドをメッセージ内に含めることができます。メッセージ・ヘッダー・フィールドおよびメッセージ・プロパティ・フィールドを使用して、通信しているプロセス間で情報をやり取りできます。
データをメッセージ本文ではなくプロパティ・フィールドに含める主要な理由は、メッセージ・セレクタを使用したメッセージのフィルタ処理をサポートするためです。XMLメッセージ拡張機能以外では、メッセージ・セレクタからメッセージ本文のデータにアクセスすることはできません。たとえば、プロパティ・フィールドを使用して、あるメッセージに高い優先度を割り当てると仮定します。その場合、このプロパティ・フィールドにアクセスし、至急の優先度が指定されたメッセージだけを選択するメッセージ・セレクタを含むメッセージ・コンシューマを作成できます。セレクタの詳細は、「メッセージのフィルタ処理」を参照してください。
JMSメッセージには、常にメッセージと共に送信されるヘッダー・フィールドの標準セットが含まれます。これらはメッセージを受信するメッセージ・コンシューマで利用でき、また、一部のフィールドはメッセージを送信するメッセージ・プロデューサで設定できます。メッセージを受信したら、ヘッダー・フィールドの値は変更できます。
ヘッダー・フィールドの値を変更(オーバーライド)する際は、メッセージ・フィールドがJMSサブシステムによってオーバーライドされる場合があることを考慮に入れる必要があります。たとえば、プロデューサで優先度を設定するとメッセージの優先度に影響しますが、send()
メソッドに提供された値はプロデューサの設定をオーバーライドします。同様に、宛先で設定した値は、プロデューサによって設定された値や、send()
メソッドに提供された値をオーバーライドします。ヘッダー・フィールドの値を検証するには、send()
メソッドの後にメッセージに対して問合せを実行するしかありません。
標準メッセージ・ヘッダー・フィールドの詳細は、「メッセージ・ヘッダー・フィールド」を参照してください。
次の表に、Messageクラスのsetメソッドとgetメソッドを、サポートされているデータ型ごとに示します。
注意:
|
表6-3 JMSヘッダー・フィールド・メソッド
ヘッダー・フィールド | setメソッド | getメソッド |
---|---|---|
JMSCorrelationID |
public void setJMSCorrelationID( String correlationID ) throws JMSException |
public String getJMSCorrelationID( ) throws JMSException public byte[] getJMSCorrelationIDAsBytes( ) throws JMSException |
JMSDestinationFoot 1 |
public void setJMSDestination( Destination destination ) throws JMSException |
public Destination getJMSDestination( ) throws JMSException |
JMSDeliveryMode1 |
public void setJMSDeliveryMode( int deliveryMode ) throws JMSException |
public int getJMSDeliveryMode( ) throws JMSException |
JMSDeliveryTime1 |
public void setJMSDeliveryTime( long deliveryTime ) throws JMSException |
public long getJMSDeliveryTime( ) throws JMSException |
JMSDeliveryMode1 |
public void setJMSDeliveryMode( int deliveryMode ) throws JMSException |
public int getJMSDeliveryMode( ) throws JMSException |
JMSMessageID1 |
public void setJMSMessageID( String id ) throws JMSException 注意: setメソッドだけでなく、 public void oldJMSMessageIDToNew( String id, long timeStamp ) throws JMSException public void newJMSMessageIDToOld( String id, long timeStamp ) throws JMSException |
public String getJMSMessageID( ) throws JMSException |
JMSPriority1 |
public void setJMSPriority( int priority ) throws JMSException |
public int getJMSPriority( ) throws JMSException |
JMSRedelivered1 |
public void setJMSRedelivered( boolean redelivered ) throws JMSException |
public boolean getJMSRedelivered( ) throws JMSException |
JMSRedeliveryLimit1 |
public void setJMSRedeliveryLimit( int redelivered ) throws JMSException |
public int getJMSRedeliveryLimit( ) throws JMSException |
JMSReplyTo |
public void setJMSReplyTo( Destination replyTo ) throws JMSException |
public Destination getJMSReplyTo( ) throws JMSException |
JMSTimeStamp1 |
public void setJMSTimeStamp( long timestamp ) throws JMSException |
public long getJMSTimeStamp( ) throws JMSException |
JMSType |
public void setJMSType( String type ) throws JMSException |
public String getJMSType( ) throws JMSException |
脚注 1 send()
メソッドが実行されている場合、対応するset()
メソッドは、メッセージ・ヘッダー・フィールドに影響を与えません。ヘッダー・フィールド値が設定されている場合は、send()
メソッドの処理中に、このヘッダー・フィールド値がオーバーライドされます。
EXAMPLES_HOME
\wl_server\examples\src\examples\jms\sender
ディレクトリにあるWebLogic Server付属のexamples.jms.sender.SenderServlet
例(EXAMPLES_HOME
は、WebLogic Serverのサンプル・コードが構成されるディレクトリを表す)は、送信するメッセージのヘッダー・フィールドを設定する方法、および送信後にメッセージのヘッダー・フィールドを表示する方法を示します。
たとえば、send()
メソッドの後に置く次のコードは、WebLogic JMSによってメッセージに割り当てられたメッセージIDを表示します。
System.out.println("Sent message " + msg.getJMSMessageID() + " to " + msg.getJMSDestination());
プロパティ・フィールドを設定するには、適切なsetメソッドを呼び出して、プロパティ名と値を指定します。プロパティ・フィールドを参照するには、適切なgetメソッドを呼び出して、プロパティ名を指定します。
送信側アプリケーションはメッセージにプロパティを設定でき、受信側アプリケーションはそのプロパティを表示できます。受信側アプリケーションがプロパティを変更するには、まず次のclearProperties()
メソッドを使用してプロパティを消去する必要があります。
public void clearProperties( ) throws JMSException
このメソッドは、メッセージ・ヘッダー・フィールドおよびメッセージ本文は消去しません。
注意: JMS用に プロバイダ固有のプロパティ用に |
プロパティ・フィールドは、boolean、byte、double、float、int、long、short、stringの各データ型のいずれかに設定できます。次の表に、Messageクラスのsetメソッドとgetメソッドを、サポートされているデータ型ごとに示します。
表6-4 メッセージ・プロパティのデータ型ごとのsetメソッドおよびgetメソッド
データ型 | setメソッド | getメソッド |
---|---|---|
boolean |
public void setBooleanProperty( String name, boolean value ) throws JMSException |
public boolean getBooleanProperty( String name ) throws JMSException |
byte |
public void setByteProperty( String name, byte value ) throws JMSException |
public byte getByteProperty( String name ) throws JMSException |
double |
public void setDoubleProperty( String name, double value ) throws JMSException |
public double getDoubleProperty( String name ) throws JMSException |
float |
public void setFloatProperty( String name, float value ) throws JMSException |
public float getFloatProperty( String name ) throws JMSException |
int |
public void setIntProperty( String name, int value ) throws JMSException |
public int getIntProperty( String name ) throws JMSException |
long |
public void setLongProperty( String name, long value) throws JMSException |
public long getLongProperty( String name ) throws JMSException |
short |
public void setShortProperty( String name, short value ) throws JMSException |
public short getShortProperty( String name ) throws JMSException |
String |
public void setStringProperty( String name, String value ) throws JMSException |
public String getStringProperty( String name ) throws JMSException |
上記の表で説明したsetメソッドおよびgetメソッド以外にも、setObjectProperty()
メソッドおよびgetObjectProperty()
メソッドを使用して、プロパティのデータ型の具体的なプリミティブ値を使用できます。具体的な値が使用されている場合、プロパティのデータ型はコンパイル時ではなく、実行時に決定されます。有効なオブジェクトのデータ型は、boolean、byte、double、float、int、long、short、およびstringです。
次のMessageメソッドを使用して、すべてのプロパティ・フィールド名にアクセスできます。
public Enumeration getPropertyNames( ) throws JMSException
このメソッドは、すべてのプロパティ・フィールド名を列挙して返します。その後、プロパティ・フィールドのデータ型に基づいて、上記の表で説明されている適切なgetメソッドにプロパティ・フィールド名を渡すことで、各プロパティ・フィールドの値を取り出すことができます。
表6-5は、メッセージ・プロパティの変換チャートです。この表から、読込み可能なデータ型を、書き込まれたデータ型に基づいて識別できます。左端以外の列のいずれかに挿入されている「可」は、左端の列にリストされている、メッセージが書き込まれたプロパティの各データ型に対して、各列の一番上にリストされているデータ型としてメッセージを読み込むことができるということを意味しています。
表6-5 メッセージ・プロパティの変換チャート
書き込まれたプロパティのデータ型 | boolean | byte | double | float | int | long | short | String |
---|---|---|---|---|---|---|---|---|
boolean |
はい |
いいえ |
いいえ |
いいえ |
いいえ |
いいえ |
いいえ |
はい |
byte |
いいえ |
はい |
いいえ |
いいえ |
はい |
はい |
はい |
はい |
double |
いいえ |
いいえ |
はい |
いいえ |
いいえ |
いいえ |
いいえ |
はい |
float |
いいえ |
いいえ |
はい |
はい |
いいえ |
いいえ |
いいえ |
はい |
int |
いいえ |
いいえ |
いいえ |
いいえ |
はい |
はい |
いいえ |
はい |
long |
いいえ |
いいえ |
いいえ |
いいえ |
いいえ |
はい |
いいえ |
はい |
Object |
はい |
はい |
はい |
はい |
はい |
はい |
はい |
はい |
short |
いいえ |
いいえ |
いいえ |
いいえ |
はい |
はい |
はい |
はい |
String |
はい |
はい |
はい |
はい |
はい |
はい |
はい |
はい |
次のMessage
メソッドを使用して、プロパティの値が設定されているかどうかをテストできます。
public boolean propertyExists( String name ) throws JMSException
プロパティ名を指定すると、メソッドはそのプロパティが存在するかどうかを示すブール値を返します。
たとえば、次のコードは、2種類のStringプロパティと1種類のintプロパティを設定します。
msg.setStringProperty("User", user); msg.setStringProperty("Category", category); msg.setIntProperty("Rating", rating);
メッセージ・プロパティ・フィールドの詳細は、「メッセージ・プロパティ・フィールド」またはjavax.jms.Message
のJavadoc(http://docs.oracle.com/javaee/6/api/javax/jms/Message.html
)を参照してください。
注意: 参照できるのは、キューのメッセージ・ヘッダー・フィールドおよびメッセージ・プロパティ・フィールドだけです。トピックのメッセージ・ヘッダー・フィールドおよびメッセージ・プロパティ・フィールドは参照できません。 |
以下のQueueSession
メソッドを使用して、キューにあるメッセージのヘッダー・フィールドおよびプロパティ・フィールドを参照できます。
public QueueBrowser createBrowser( Queue queue ) throws JMSException public QueueBrowser createBrowser( Queue queue, String messageSelector ) throws JMSException
参照するキューを指定する必要があります。また、参照するメッセージをフィルタ処理するメッセージ・セレクタを指定することもできます。メッセージ・セレクタの詳細は、「メッセージのフィルタ処理」を参照してください。
キューを定義すると、以下のQueueBrowser
メソッドを使用して、キュー・ブラウザに関連付けられたキュー名およびメッセージ・セレクタにアクセスできるようになります。
public Queue getQueue( ) throws JMSException public String getMessageSelector( ) throws JMSException
さらに、次のQueueBrowser
メソッドを使用して、メッセージを参照するための列挙値にアクセスできます。
public Enumeration getEnumeration( ) throws JMSException
EXAMPLES_HOME
\wl_server\examples\src\examples\jms\queue
ディレクトリにあるWebLogic Server付属のexamples.jms.queue.QueueBrowser
例(EXAMPLES_HOME
は、WebLogic Serverのサンプル・コードが構成されるディレクトリを表す)は、受信したメッセージのヘッダー・フィールドにアクセスする方法を示します。
たとえば、次のQueueBrowser
の例からの引用コードでは、QueueBrowser
オブジェクトを作成します。
qbrowser = qsession.createBrowser(queue);
次のコードは、QueueBrowser
サンプルで定義されているdisplayQueue()
メソッドからの引用です。この例では、QueueBrowser
オブジェクトを使用して、キューのメッセージをスキャンする場合に使用される列挙値を取得します。
public void displayQueue( ) throws JMSException { Enumeration e = qbrowser.getEnumeration(); Message m = null; if (! e.hasMoreElements()) { System.out.println("There are no messages on this queue."); } else { System.out.println("Queued JMS Messages: "); while (e.hasMoreElements()) { m = (Message) e.nextElement(); System.out.println("Message ID " + m.getJMSMessageID() + " delivered " + new Date(m.getJMSTimestamp()) " to " + m.getJMSDestination()); } }
キュー・ブラウザが使用されていない場合は、キュー・ブラウザをクローズしてリソースを解放する必要があります。詳細については、「オブジェクト・リソースの解放」を参照してください。
QueueBrowser
クラスの詳細は、javax.jms.QueueBrowser
のJavadoc(http://docs.oracle.com/javaee/6/api/javax/jms/QueueBrowser.html
)を参照してください。
多くの場合、アプリケーションでは、配信されるすべてのメッセージが通知される必要はありません。メッセージ・セレクタを使用すると、不要なメッセージをフィルタ処理できるので、ネットワーク・トラフィックへの影響が最小限になり、パフォーマンスが向上します。
メッセージ・セレクタは、以下のように動作します。
送信側アプリケーションでは、標準化された方法でメッセージを説明したり分類したりするためのメッセージ・ヘッダー・フィールドおよびメッセージ・プロパティ・フィールドが設定されます。
受信側アプリケーションでは、単純な問合せ文字列を指定することで、アプリケーションで受信するメッセージがフィルタ処理されます。
メッセージ・セレクタはメッセージの内容(本文)を参照することができないため、情報の一部をメッセージ・プロパティ・フィールドに複製することもできます(XMLメッセージの場合を除く)。
キュー・レシーバまたはトピック・サブスクライバの作成時に、それぞれQueueSession.createReceiver()
メソッドまたはTopicSession.createSubscriber()
メソッドの引数としてセレクタを指定します。キュー・レシーバおよびトピック・サブスクライバの作成については、「ステップ5: メッセージ・プロデューサとメッセージ・コンシューマを作成する」を参照してください。
WebLogic JMSは、状態または現在の処理状態を処理中のメッセージに割り当てます。このような状態をセレクタとして使用できます。有効なメッセージ状態の詳細は、Oracle WebLogic Server Java APIリファレンスのweblogic.jms.extensions.JMSMessageInfoに関する項を参照してください。
以降の節では、SQL文とXMLセレクタ・メソッドを使用してメッセージ・セレクタを定義する方法、およびメッセージ・セレクタを更新する方法について説明します。ヘッダー・フィールドおよびプロパティ・フィールドの設定の詳細は、それぞれ「メッセージ・ヘッダー・フィールドおよびメッセージ・プロパティ・フィールドの設定と参照」、「メッセージ・プロパティ・フィールドの設定」を参照してください。
メッセージ・セレクタはブール式です。これは、SQL select
文のwhere
句と類似した構文を含む文字列から構成されます。
次の引用は、セレクタ式の例を示します。
salary > 64000 and dept in ('eng','qa') (product like 'WebLogic%' or product like '%T3') and version > 3.0 hireyear between 1990 and 1992 or fireyear is not null fireyear - hireyear > 4
次の例では、キュー・レシーバの作成時に、優先度が6未満のメッセージをフィルタで除外するセレクタを設定する方法を示します。
String selector = "JMSPriority >= 6"; qsession.createReceiver(queue, selector);
次の例では、トピック・サブスクライバの作成時に、同様のセレクタを設定する方法を示します。
String selector = "JMSPriority >= 6"; qsession.createSubscriber(topic, selector);
メッセージ・セレクタ構文の詳細は、javax.jms.Message
のJavadoc(http://docs.oracle.com/javaee/6/api/javax/jms/Message.html
)を参照してください。
XMLメッセージ・タイプの場合、メッセージ・セレクタの定義には、前節で説明したSQLセレクタ式だけでなく、次のメソッドを使用することもできます。
String JMS_BEA_SELECT(String type, String expression)
JMS_BEA_SELECT
は、WebLogic JMS SQL構文の組込み関数です。構文タイプとXPath式を指定します。構文タイプは、xpath
(XML Path Language)に設定する必要があります。XML Path Languageは、XML Path Language (XPath)のドキュメントで定義されており、XML Path LanguageのWebサイトhttp://www.w3.org/TR/xpath
で入手できます。
注意: XMLメッセージの構文には十分注意してください。不正なXMLメッセージ(終了タグの欠落など)はどのXMLセレクタとも一致しません。 |
以下の環境では、メソッドはnull値を返します。
メッセージによって解析されない場合
メッセージによって解析されるが、要素がない場合
メッセージによって解析され、要素も存在するが、メッセージに値が含まれていない場合(例: <order></order>
)
たとえば、次のようなXMLの引用があります。
<order> <item> <id>007</id> <name>Hand-held Power Drill</name> <description>Compact, assorted colors.</description> <price>$34.99</price> </item> <item> <id>123</id> <name>Mitre Saw</name> <description>Three blades sizes.</description> <price>$69.99</price> </item> <item> <id>66</id> <name>Socket Wrench Set</name> <description>Set of 10.</description> <price>$19.99</price> </item> </order>
次の例では、上記の引用にある2番目の項目の名前を取り出す方法を示します。メソッド呼出しは、Mitre Saw
という文字列を返します。
String sel = "JMS_BEA_SELECT('xpath', '/order/item[2]/name/text()') = 'Mitre Saw'";
二重引用符と単一引用符、およびスペースの使い方に注意してください。xpath
、XMLタブ、および文字列値が単一引用符で囲まれていることに注意してください。
次の例では、上記の引用にある3番目の項目のIDを取り出す方法を示します。メソッド呼出しは、66
という文字列を返します。
String sel = "JMS_BEA_SELECT('xpath', '/order/item[3]/id/text()') = '66'";
次のMessageConsumer
メソッドを使用して、メッセージ・セレクタを表示できます。
public String getMessageSelector( ) throws JMSException
このメソッドは、現在定義されているメッセージ・セレクタ、またはメッセージ・セレクタが定義されていない場合はnullのいずれかを返します。
アプリケーションの一部のクラスでは、WebLogic JMSでトピック・サブスクライバのメッセージ・セレクタに索引を付けることで最適化できます。通常、それらのアプリケーションはサブスクライバ数が多く、各サブスクライバに一意の識別子(ユーザー名など)が設定されています。また、単独のサブスクライバまたはサブスクライバのリストへメッセージを迅速に送信できる必要があります。一般的な例としては、各サブスクライバが異なるユーザーに対応し、各メッセージに1つまたは複数のターゲット・ユーザーのリストが含まれるインスタント・メッセージング・アプリケーションがあります。
最適化されたサブスクライバのメッセージ・セレクタをアクティブ化するには、サブスクライバはセレクタに以下の構文を使用する必要があります。
"identifier IS NOT NULL"
identifier
は、あらかじめ定義されたJMSメッセージ・プロパティではない任意の文字列です(たとえば、JMSCorrelationID
でもJMSType
でもない文字列)。複数のサブスクライバが同じ識別子を共有できます。
WebLogic JMSでは、このメッセージ・セレクタ構文を、内部サブスクライバ索引を構築するためのヒントとして使用します。構文に従っていないメッセージ・セレクタ、または追加のOR
句およびAND
句を含むメッセージ・セレクタも受け付けられますが、最適化はアクティブ化されません。
このメッセージ・セレクタ構文を使用してサブスクライバを登録すると、トピックにパブリッシュされるメッセージは、1つまたは複数の識別子をメッセージのユーザー・プロパティに追加することにより、特定のサブスクライバをターゲットにすることができます。次に例を示します。
// Set up a named subscriber, where "wilma" is the name of // the subscriber and subscriberSession is a JMS TopicSession. // Note that the selector syntax used activates the optimization. TopicSubscriber topicSubscriber = subscriberSession.createSubscriber( (Topic)context.lookup("IMTopic"), "Wilma IS NOT NULL", /* noLocal= */ true); // Send a message to subscribers "Fred" and "Wilma", // where publisherSession is a JMS TopicSession. Subscribers // with message selector expressions "Wilma IS NOT NULL" // or "Fred IS NOT NULL" will receive this message. TopicPublisher topicPublisher = publisherSession.createPublisher( (Topic)context.lookup("IMTopic"); TextMessage msg = publisherSession.createTextMessage("Hi there!"); msg.setBooleanProperty("Fred", true); msg.setBooleanProperty("Wilma", true); topicPublisher.publish(msg);
注意: 最適化されたメッセージ・セレクタとメッセージ構文は、標準のJMS APIに基づいています。そのため、この構文を使用したアプリケーションは、最適化されたメッセージ・セレクタがないWebLogic JMSのバージョンや、WebLogic JMS以外の製品でも動作します。ただし、これらのバージョンの場合、この拡張機能を備えたバージョンに比べてパフォーマンスは劣ります。 メッセージ・セレクタを最適化しても、 |
注意: このリリースでは、ストリーミングはサポートされていません。サポートされるのは、XMLドキュメントのテキスト表現とDOM表現のみです。 |
WebLogic Server JMS APIでは、XMLメッセージを送信するためのドキュメント・オブジェクト・モデル(DOM)のネイティブ・サポートも提供されています。
以下の節では、XMLメッセージの拡張サポートを提供するWebLogic JMS APIの拡張機能について説明します。
String
表現とDOM
表現の間のXML変換には、以下のWebLogic XML APIを使用できます。
XMLMessage
- XMLコンテンツを含むメッセージの送信に使用します。
WLSession.createXMLMessage
- XMLメッセージの作成に使用します。
XMLMessage
のペイロードは、あるXML表現を使用して設定し、別の表現を使用して取得できます。たとえば、XMLMessageの本文をString
表現を使用して設定し、DOM表現を使用して取得することも可能です。
string
型を使用してXMLメッセージをパブリッシュするには、次の手順に従います。
XMLをStringWriter
にシリアライズします。
StringWriter
のtoString
を呼び出し、それをmessage.setText
に渡します。
メッセージをパブリッシュします。
XMLメッセージをDOM表現を使用して送信すると、String
としてメッセージを送信する場合に比べパフォーマンスがかなり向上します。DOM表現を使用してXMLメッセージをパブリッシュするには、次の手順に従います。
必要に応じて、XMLソースからDOMドキュメントを生成します。
DOMドキュメントをXMLMessage.setDocument
に渡します。
メッセージをパブリッシュします。