この章では、Oracle Streams Advanced Queuing(AQ)に対するOracle Java Message Service(JMS)インタフェースを説明します。
内容は次のとおりです。
内容は次のとおりです。
内容は次のとおりです。
ConnectionFactory
は、管理者によって定義された接続構成パラメータの集合をカプセル化します。クライアントはこれを使用してJMSプロバイダとの接続を確立します。この場合、Oracle Databaseの一部であるOracle JMSがJMSプロバイダです。
ConnectionFactory
オブジェクトには、次の3種類があります。
ConnectionFactory
QueueConnectionFactory
TopicConnectionFactory
AQjmsFactory
クラスを使用して、ConnectionFactory
、QueueConnectionFactory
またはTopicConnectionFactory
オブジェクトに対するハンドルを取得できます。
Point-to-Point操作とパブリッシュ・サブスクライブ操作の両方をサポートしているConnectionFactory
を取得するには、AQjmsFactory.getConnectionFactory()
を使用します。QueueConnectionFactory
を取得するには、AQjmsFactory.getQueueConnectionFactory()
を使用します。TopicConnectionFactory
を取得するには、AQjmsFactory.getTopicConnectionFactory()
を使用します。
ConnectionFactory
、QueueConnectionFactory
またはTopicConnectionFactory
は、ホスト名、ポート番号、SIDドライバまたはJDBC URLおよびプロパティを使用して作成できます。
JMS管理者は、Lightweight Directory Access Protocol(LDAP)サーバーにConnectionFactory
オブジェクトを登録できます。JMSでJava Naming and Directory Interface(JNDI)の検索を使用可能にするには、次の設定が必要です。
データベースの登録
Oracle Databaseサーバーのインストール時にデータベースをLDAPサーバーに登録する必要があります。登録にはDatabase Configuration Assistant(DBCA)を使用します。図11-1は、LDAPサーバー内のOracle Streams AQエントリの構造を示しています。ConnectionFactory>
情報は、<cn=OracleDBConnections>
に格納されています。トピックおよびキューは、<cn=OracleDBQueues>
に格納されています。
パラメータGLOBAL_TOPIC_ENABLED
の設定
データベースのGLOBAL_TOPIC_ENABLED
システム・パラメータをTRUE
に設定する必要があります。これによって、Oracle Streams AQで作成されたすべてのキューおよびトピックが自動的にLDAPサーバーに登録されます。このパラメータは、ALTER SYSTEM SET GLOBAL_TOPIC_ENABLED = TRUE
を使用して設定できます。
ConnectionFactory
オブジェクトの登録
データベースを設定してLDAPサーバーが使用できるようになると、JMS管理者はAQjmsFactory.registerConnectionFactory()
を使用して、LDAPにConnectionFactory
、QueueConnectionFactory
およびTopicConnectionFactory
の各オブジェクトを登録できます。
登録には次のいずれかの方法を使用します。
直接LDAPサーバーに接続
LDAPにコネクション・ファクトリを登録するには、ユーザーにGLOBAL_AQ_USER_ROLE
が必要です。
LDAPに直接接続するには、registerConnectionFactory
メソッドのパラメータに、LDAPコンテキスト、ConnectionFactory
の名前、QueueConnectionFactory
の名前、TopicConnectionFactory
の名前、ホスト名、データベースSID、ポート番号、JDBCドライバ(ThinまたはOCI8)およびファクトリ・タイプ(キューまたはトピック)を含める必要があります。
データベース・サーバーを介してLDAPに接続
ユーザーはOracle Databaseにログインしてから、データベースによるLDAPエントリの更新ができます。ユーザーが、データベースにログインしてこの操作を実行するには、AQ_ADMINISTRATOR_ROLE
を取得する必要があります。
データベースを介してLDAPに接続するには、registerConnectionFactory
メソッドのパラメータに、AQ_ADMINISTRATOR_ROLE
を持つユーザーへのJDBCコネクション、ConnectionFactory
の名前、QueueConnectionFactory
の名前、TopicConnectionFactory
の名前、ホスト名、データベースSID、ポート番号、JDBCドライバ(ThinまたはOCI8)およびファクトリ・タイプ(キューまたはトピック)を含める必要があります。
JMSコネクション
は、クライアントとJMSプロバイダの間のアクティブなコネクションを表します。JMSコネクション
によって、次に示すいくつかの重要なサービスが実行されます。
JMSプロバイダとのオープン・コネクションまたはコネクション・プールのいずれかをカプセル化します。
クライアントとプロバイダのサービス・デーモン間のオープンなTCP/IPソケットを表します。
コネクション確立時に、クライアントを認証するための構造を提供します。
Sessions
を作成します。
コネクション・メタデータを提供します。
オプションのExceptionListener
をサポートします。
データベースへのJMSコネクション
は、createConnection()
、createQueueConnection()
またはcreateTopicConnection()
を起動し、ConnectionFactory
オブジェクト、QueueConnectionFactory
オブジェクトまたはTopicConnectionFactory
オブジェクトにそれぞれパラメータusername
およびpassword
を渡して作成できます。
次に、Connection
オブジェクトでサポートされているメソッドのいくつかを示します。
start()
このメソッドは、着信メッセージの配信を開始または再開します。
stop()
このメソッドは、着信メッセージの配信を一時停止します。Connection
オブジェクトが停止すると、すべてのメッセージ・コンシューマへの配信は禁止されます。また、同期受信のブロックおよびメッセージは、メッセージ・リスナーに配信されません。
close()
このメソッドは、JMSセッションをクローズして、関連付けられたすべてのリソースを解放します。
createSession(true, 0)
このメソッドは、JMS Connection
インスタンスを使用してJMS Session
を作成します。
createQueueSession(true,
0)
このメソッドはQueueSession
を作成します。
createTopicSession(true,
0
)
このメソッドはTopicSession
を作成します。
setExceptionListener(ExceptionListener)
このメソッドは、Connection
の例外リスナーを設定します。問題が非同期でクライアントに通知されます。メッセージを処理するのみのConnection
の場合、その失敗を確認する他の方法はありません。
getExceptionListener()
このメソッドは、このConnection
のExceptionListener
を取得します。
JMSクライアントは、通常1つのConnection
、1つのSession
、多数のMessageProducer
およびMessageConsumer
オブジェクトを作成します。現在のバージョンでは、次の場合を除いて、1つのConnection
につき1つのオープンSession
のみが許可されています。
JDBC OCI8ドライバを使用してJMSコネクションを作成する場合
ユーザーが、JMSコネクションの作成時にOracleOCIConnectionPool
インスタンスを提供する場合
Connection
は、作成時は停止モードです。この状態では、メッセージをコネクションに配信できません。通常、設定が完了するまで、Connection
は停止モードのままです。設定が完了した時点で、Connection
のstart()
メソッドがコールされ、メッセージがConnection
コンシューマに到着し始めます。この設定規則によって、設定処理中であっても、メッセージが非同期配信されることによって発生するクライアントの混乱を最小限に抑えることができます。
Connection
を起動し、続けて設定を実行できます。これを実行するクライアントは、設定処理中に非同期メッセージの配信処理の準備をする必要があります。MessageProducer
は、Connection
が停止中でもメッセージを送信できます。
JMS Session
は、メッセージの作成および処理用の単一スレッドのコンテキストです。これは、Java Virtual Machine(JVM)の外でプロバイダ・リソースを割り当てますが、軽量なJMSオブジェクトとみなされます。
Session
には、次の役割があります。
MessageProducer
およびMessageConsumer
オブジェクトのファクトリを構成します。
宛先オブジェクト(キュー/トピック)に対するハンドルの取得方法を提供します。
プロバイダが最適化したメッセージ・ファクトリを提供します。
セッションのMessageProducer
およびMessageConsumer
オブジェクトにまたがる作業を組み合せる一連のトランザクションをサポートし、これらを単位に構成します。
セッションが処理および作成するメッセージのシリアル順序を定義します。
セッションに登録されたMessageListener
オブジェクトの実行をシリアル化します。
Oracle Database 10gでは、JDBC thinまたはJDBC thick(OCI)ドライバのいずれかを使用すると、単一のJMS Connection
を使用して、リソースが許すかぎり多くのJMS Session
を作成できます。
プロバイダが、JVM外のSession
のためのリソースを割り当てることができるため、クライアントはリソースが必要ないときはこれらを閉じる必要があります。ガベージ・コレクションによる最終的なリソースの解放を待つ必要はありません。Session
が作成したMessageProducer
およびMessageConsumer
オブジェクトについても同様です。
Session
オブジェクトのメソッドには、次のものが含まれます。
commit()
このメソッドは、トランザクションで実行されるすべてのメッセージをコミットして、現在保持されているロックを解放します。
rollback()
このメソッドは、トランザクションで実行されたすべてのメッセージをロールバックして、現在保持されているロックを解放します。
close()
このメソッドはSession
をクローズします。
getDBConnection()
このメソッドは、基礎となるJDBCコネクションに対するハンドルを取得します。このハンドルを使用して、他のSQL DML操作を同じSession
の一部として実行できます。このメソッドは、Oracle JMSに固有です。
acknowledge()
このメソッドは、非トランザクション・セッションでメッセージの受信を承認します。
recover()
このメソッドは、非トランザクション・セッションでメッセージの配信を再開します。セッション中に配信された一連のメッセージは、最後に承認されたメッセージの後でリセットされます。
Oracle JMSの拡張例は、次のとおりです。
createQueueTable()
このメソッドはキュー表を作成します。
getQueueTable()
このメソッドは既存のキュー表に対するハンドルを取得します。
createQueue()
このメソッドはキューを作成します。
getQueue()
このメソッドは既存のキューに対するハンドルを取得します。
createTopic()
このメソッドはトピックを作成します。
getTopic()
このメソッドは既存のトピックに対するハンドルを取得します。
どの拡張機能を使用する場合も、Session
オブジェクトをAQjmsSession
にキャストする必要があります。
注意: JMS仕様では、開始されていないJMSConnection インスタンスで受信が完了したとき、プロバイダによりNULLメッセージが返されることを要求します。
|
Destination
は、クライアントがメッセージの送信先および受信元の指定に使用するオブジェクトです。Destination
オブジェクトはQueue
またはTopic
に指定できます。Oracle Streams AQでは、特定のデータベースのschema.queue
にマップされます。Queue
は単一コンシューマ・キューに、Topic
はマルチ・コンシューマ・キューにマップします。
Destination
オブジェクトは、Session
オブジェクトからドメイン固有の次のSession
メソッドを使用して作成されます。
AQjmsSession.getQueue(queue_owner, queue_name)
このメソッドはJMSキューに対するハンドルを取得します。
AQjmsSession.getTopic(topic_owner, topic_name)
このメソッドはJMSトピックに対するハンドルを取得します。
LDAPサーバーにスキーマ・オブジェクトを登録するようにデータベースを設定できます。データベースがLDAPを使用できるように設定され、GLOBAL_TOPIC_ENABLEDパラメータがTRUEに設定されている場合、すべてのJMSキューおよびトピックは、作成時に自動的にLDAPサーバーに登録されます。また、管理者は、LDAPに登録されているキューおよびトピックの別名を作成することもできます。LDAPに登録されているキューおよびトピックは、キュー/トピック名またはその別名を使用してJNDIを介して検索できます。
Destination
オブジェクトのメソッドには、次のものが含まれます。
alter()
このメソッドはキュー
またはトピック
を変更します。
schedulePropagation()
このメソッドは、ソースから宛先への伝播をスケジューリングします。
unschedulePropagation()
このメソッドは、スケジュール済伝播のスケジュールを解除します。
enablePropagationSchedule()
このメソッドは、伝播スケジュールを有効化します。
disablePropagationSchedule()
このメソッドは、伝播スケジュールを無効化します。
start()
このメソッドはキュー
またはトピック
を開始します。キューは、エンキューまたはデキューを可能にするために開始されます。トピックは、パブリッシュまたはサブスクライブを可能にするために開始できます。
stop()
このメソッドはキュー
またはトピック
を停止します。キューは、エンキューまたはデキューを実行不可にするために停止できます。トピックは、パブリッシュまたはサブスクライブを実行不可にするために停止できます。
drop()
このメソッドはキュー
またはトピック
を削除します。
Oracle8i以上では、すべてのキューイング操作に対してシステム・レベルのアクセス制御をサポートします。この機能によって、アプリケーション設計者またはDBAは、ユーザーをキュー管理者にできます。キュー管理者は、データベースのどのキューに対してもJMSインタフェース(管理および操作)を起動できます。これによって、データベース上のキュー全体に対するすべての管理スクリプトを1つのスキーマで管理できるため、管理作業が容易になります。
メッセージが宛先キューに届くと、ソース・キューのスキーマ名に基づいたセッションによって、新しく届いたメッセージが宛先キューにエンキューされます。つまり、ソース・キューのスキーマに宛先キューに対するエンキュー権限を付与する必要があります。
リモートの宛先キューに伝播するために、エージェント構造体のアドレス・フィールドのデータベース・リンクに指定されたログイン・ユーザーには、ENQUEUE_ANY
権限を付与するか、または宛先キューに対するエンキュー権限を付与する必要があります。ただし、データベース・リンクのログイン・ユーザーが宛先のキュー表を所有している場合はどのような明示的な権限も付与する必要はありません。
Oracle8i以上では、エンキューおよびデキュー操作に対してキュー・レベルまたはトピック・レベルのアクセス制御をサポートしています。この機能によって、アプリケーション設計者は、あるスキーマに作成されたキューおよびトピックを他のスキーマで実行中のアプリケーションから保護できます。そのキューまたはトピックが属するスキーマの外で実行しているアプリケーションには、最小限のアクセス権限のみを付与できます。キューまたはトピックに対するアクセス権限として、ENQUEUE
、DEQUEUE
およびALL
がサポートされています。
メッセージは、相互に関連していることがよくあります。たとえば、あるメッセージを処理した結果として他のメッセージが生成された場合、両者は関連付けられています。アプリケーション設計者としては、そのような関連を追跡することが必要な場合があります。Oracle Streams AQでは、ユーザーがメッセージをキュー表に保持し、分析のためにSQLで問合せできます。
保存機能およびメッセージ識別子とともに、メッセージ・ジャーナルがOracle Streams AQによって自動作成され、追跡ジャーナルまたはイベント・ジャーナルをコールできます。保存、メッセージ識別子およびSQL問合せの協調によって、強力なメッセージ・ウェアハウスを構築できます。
Oracle Real Application Clusters(RAC)を使用すると、異なるキューを別々のインスタンスによって管理できるようにすることでOracle Streams AQパフォーマンスを改善できます。このためには、キューを格納するキュー表に様々なインスタンス・アフィニティ(作業環境)を指定します。これによって、様々なキュー/トピックに対するキュー操作(エンキューまたはデキュー)またはトピック操作(パブリッシュ・サブスクライブ)を並行して行うことができるようになります。
Oracle Streams AQのキュー・モニター・プロセスは、キュー表のインスタンス・アフィニティを継続的に監視します。キュー・モニターは指定されたプライマリ・インスタンスが使用可能な場合はそれにキュー表の所有権を割り当て、失敗した場合は指定されたセカンダリ・インスタンスに割り当てます。
キュー表を所有しているインスタンスが終了すると、キュー・モニターはセカンダリ・インスタンスなどの適切なインスタンスに所有者を変更します。
Oracle Streams AQの伝播はReal Application Clustersでも使用できますが、これはユーザーにとっては透過的です。伝播スケジュールのジョブ・アフィニティは、それぞれのキュー表のアフィニティと同じ値に設定されます。このように、キュー表を所有するインスタンスに対応付けられたジョブ・キュー・プロセスは、そのキュー表に格納されているキューからの伝播を処理し、ping操作を最小限に抑えます。
JMSメッセージは、ヘッダー、プロパティおよび本体で構成されています。
ヘッダーは、クライアントおよびプロバイダの両方でメッセージの識別およびルーティングに使用される値が含まれるヘッダー・フィールドで構成されています。すべてのメッセージは、同じ一連のヘッダー・フィールドをサポートしています。
プロパティは、オプションのヘッダー・フィールドです。JMSによって定義された標準プロパティの他に、プロバイダ固有およびアプリケーション固有のプロパティを含めることもできます。
本体はメッセージ・ペイロードです。JMSは、様々な型のメッセージ・ペイロードおよびJMSで指定されたメッセージ型のJMSメッセージを格納できる型を定義します。
内容は次のとおりです。
JMSメッセージ・ヘッダーには、次のフィールドが含まれます。
JMSDestination
このフィールドにはメッセージの送信先が含まれます。Oracle Streams AQでは、宛先キュー/トピックに対応します。これは、Send
メソッドの完了後にJMSによって設定されたDestination
型です。
JMSDeliveryMode
このフィールドは、メッセージ・ログを作成するかどうかを決定します。JMSでは、PERSISTENT
配信(メッセージが決まった記憶域に記録される)およびNONPERSISTENT
配信(メッセージは記録されない)をサポートしています。これは、Send
メソッドの完了後にJMSによって設定されたINTEGER
型です。JMSでは、クライアントがJMSDeliveryMode
に指定した値を管理者がオーバーライドするようにJMSを構成できます。
JMSMessageID
このフィールドは、プロバイダのメッセージを一意に識別します。すべてのメッセージIDは、ID:
で始まる必要があります。これは、Send
メソッドの完了後にJMSによって設定されたString
型です。
JMSTimeStamp
このフィールドには、メッセージが送信先のプロバイダに手渡された時刻が含まれます。これは、Oracle Streams AQのメッセージのエンキュー時刻に対応します。これは、Send
メソッドの完了後にJMSによって設定されたLong
型です。
JMSCorrelationID
このフィールドを使用して、クライアントはあるメッセージを別のメッセージにリンクできます。これはJMSクライアントによって設定されたString
型です。
JMSReplyTo
このフィールドには、メッセージ送信時にクライアントが指定するDestination
型が含まれます。クライアントはoracle.jms.AQjmsAgent
、javax.jms.Queue
またはjavax.jms.Topic
を使用できます。
JMSType
このフィールドには、送信時にクライアントが指定するメッセージ型識別子が含まれます。これはString
型です。移植性の観点から、JMSType
を記号値にすることをお薦めします。
JMSExpiration
このフィールドは、エンキュー時刻および非J2EE準拠モードのTimeToLive
の合計です。準拠モードでは、デキューされたメッセージのJMSExpiration
ヘッダー値は、メッセージがエンキューされたときのJMSTimeStamp
(グリニッジ標準時で1000分の1秒単位)とTimeToLive
(1000分の1秒単位)の合計になります。これは、Send
メソッドの完了後にJMSによって設定されたLong
型です。JMSでは、クライアントがJMSExpiration
に指定した値を管理者がオーバーライドするようにJMSを構成できます。
JMSPriority
このフィールドにはメッセージの優先順位が含まれます。これは、Send
メソッドの完了後にJMSによって設定されたINTEGER
型です。J2EE準拠モードで指定できる優先順位の値は0
–9
です。Sun社のJMS 1.1標準に準拠した場合、9
が最も高い優先順位で、4
がデフォルトです。デフォルトは非準拠モードです。管理者は、クライアントがJMSPriority
に指定した値がオーバーライドされるようにJMSを構成できます。
JMSRedelivered
このフィールドは、JMSプロバイダによって設定されたブールです。
JMSプロパティは、クライアントによって明示的に設定されるか、またはJMSプロバイダによって自動的に設定されます(通常、これらは読取り専用です)。JMSプロパティには、Send
およびReceive
操作に指定されたパラメータを使用して設定されるものもあります。
プロパティで、メッセージにオプションのヘッダー・フィールドを追加できます。プロパティによって、クライアントは、messageSelector
を使用して、クライアントのかわりにJMSプロバイダにアプリケーション固有基準を使用してメッセージを選択させることができます。プロパティ名は文字列で、サポートされている値はBoolean
、Byte
、Short
、Integer
、Long
、Float
、Double
およびString
です。
JMS定義のプロパティは、すべてJMSX
で始まります。次のものがあります。
JMSXUserID
このフィールドは、メッセージを送信するユーザーの識別情報です。これは、Send
メソッドの完了後にJMSによって設定されたString
型です。
JMSXAppID
このフィールドは、メッセージを送信するアプリケーションの識別情報です。これは、Send
メソッドの完了後にJMSによって設定されたString
型です。
JMSXDeliveryCount
このフィールドは、メッセージ配信の試行回数です。これは、Send
メソッドの完了後にJMSによって設定されたInteger
型です。
JMSXGroupid
このフィールドは、このメッセージが属すメッセージ・グループの識別情報です。これはJMSクライアントによって設定されたString
型です。
JMSXGroupSeq
このフィールドは、グループ内のメッセージの順序番号です。これはJMSクライアントによって設定されたInteger
型です。
JMSXRcvTimeStamp
このフィールドは、メッセージがコンシューマに配信された時刻(デキュー時刻)です。これは、Receive
メソッドの完了後にJMSによって設定されたString
型です。
JMSXState
このフィールドは、プロバイダによって設定されたメッセージ状態です。メッセージ状態は、WAITING
、READY
、EXPIRED
またはRETAINED
です。
Oracle固有のJMSプロパティは、すべてJMS_Oracle
で始まります。次のものがあります。
JMS_OracleExcpQ
このフィールドは、メッセージを元の宛先に配信できない場合に、そのメッセージの送信先となるキュー名です。これはJMSクライアントによって設定されたString
型です。JMS_OracleExcpQ
プロパティに指定できる宛先キューのタイプは、EXCEPTION
のみです。
JMS_OracleDelay
このフィールドは、メッセージ配信の遅延秒数です。これはJMSクライアントによって設定されたInteger
型です。これはメッセージが配信されるときの順序に影響します。
JMS_OracleOriginalMessageId
メッセージがある宛先から他の宛先に伝播される場合、このフィールドはソース内のメッセージのメッセージIDに設定されます。これはJMSプロバイダによって設定されたString
型です。メッセージが伝播されない場合、このプロパティはJMSMessageId
と同じ値になります。
クライアントは、プロパティを定義することによって、メッセージにヘッダー・フィールドを追加できます。これらのプロパティをmessageSelector
で使用して特定のメッセージを選択できます。
JMSでは、次の5つのフォーマットのメッセージ本体が提供されます。
StreamMessage
オブジェクトは、Java基本データ型の値をストリームとして送信する場合に使用します。このメッセージ本体には順次書込み/読込みが可能です。StreamMessage
はMessage
から拡張され、StreamMessage
本体を追加します。このメソッドは、主にjava.io.DataInputStream
およびjava.io.DataOutputStream
のメソッドに基づいています。
基本データ型の値は、それぞれの型のメソッドを使用して、明示的に読込みまたは書込みできます。抽象的なオブジェクトとして読込みまたは書込みすることもできます。StreamMessage
オブジェクトを使用するには、SYS.AQ$_JMS_STREAM_MESSAGE
またはAQ$_JMS_MESSAGE
ペイロード型を持つキュー表を作成します。
StreamMessage
オブジェクトは、表11-1に示す変換をサポートします。行の型として書き込まれる値は、列の型として読み込むことができます。
表11-1 StreamMessageの変換
Input | Boolean | Byte | Short | Char | Int | Long | Float | Double | String | byte[] |
---|---|---|---|---|---|---|---|---|---|---|
Boolean
|
X | - | - | - | - | - | - | - | X | - |
Byte
|
- | X | X | - | X | X | - | - | X | - |
Short
|
- | - | X | - | X | X | - | - | X | - |
Char
|
- | - | - | X | - | - | - | - | X | - |
Int
|
- | - | - | - | X | X | - | - | X | - |
Long
|
- | - | - | - | - | X | - | - | X | - |
Float
|
- | - | - | - | - | - | X | X | X | - |
Double
|
- | - | - | - | - | - | - | X | X | - |
String
|
X | X | X | X | X | X | X | X | X | - |
Byte[]
|
- | - | - | - | - | - | - | - | - | X |
BytesMessage
オブジェクトは、1つの未解釈バイトのストリームを含むメッセージを送信する場合に使用します。BytesMessage
はMessage
から拡張され、BytesMessage
本体を追加します。メッセージの受信者が、そのバイト列を解析します。このメソッドは、主にjava.io.DataInputStream
およびjava.io.DataOutputStream
のメソッドに基づいています。
これは、クライアントが既存のメッセージ・フォーマットをコード化するためのメッセージ型です。可能であれば、かわりに他の自己定義メッセージ型を使用してください。
Javaの基本データ型の値は、それぞれの型のメソッドを使用して、明示的に書込みができます。また、抽象的なオブジェクトとして書き込むこともできます。BytesMessage
オブジェクトを使用するには、SYS.AQ$_JMS_BYTES_MESSAGE
またはAQ$_JMS_MESSAGE
ペイロード型を持つキュー表を作成します。
MapMessage
オブジェクトは、名前がString
型で値がJava基本データ型である名前/値ペアの集合を送信する場合に使用します。エントリには、名前で順次またはランダムにアクセスできます。エントリの順序は未定義です。MapMessage
はMessage
から拡張され、MapMessage
本体を追加します。基本データ型の値は、それぞれの型のメソッドを使用して、明示的に読込みまたは書込みできます。抽象的なオブジェクトとして読込みまたは書込みすることもできます。
MapMessage
オブジェクトを使用するには、SYS.AQ$_JMS_MAP_MESSAGE
またはAQ$_JMS_MESSAGE
ペイロード型を持つキュー表を作成します。MapMessage
オブジェクトは、表11-2に示す変換をサポートします。この表の「X」は、行の型として書き込まれる値を列の型として読み取ることができることを意味します。
表11-2 MapMessageの変換
Input | Boolean | Byte | Short | Char | Int | Long | Float | Double | String | byte[] |
---|---|---|---|---|---|---|---|---|---|---|
Boolean
|
X | - | - | - | - | - | - | - | X | - |
Byte
|
- | X | X | - | X | X | - | - | X | - |
Short
|
- | - | X | - | X | X | - | - | X | - |
Char
|
- | - | - | X | - | - | - | - | X | - |
Int
|
- | - | - | - | X | X | - | - | X | - |
Long
|
- | - | - | - | - | X | - | - | X | - |
Float
|
- | - | - | - | - | - | X | X | X | - |
Double
|
- | - | - | - | - | - | - | X | X | - |
String
|
X | X | X | X | X | X | X | X | X | - |
Byte[]
|
- | - | - | - | - | - | - | - | - | X |
TextMessage
オブジェクトは、java.lang.StringBuffer
を含むメッセージを送信する場合に使用します。TextMessage
はMessage
から拡張され、TextMessage
本体を追加します。テキスト情報は、getText()
およびsetText(
...)
メソッドを使用して読込みまたは書込みができます。TextMessage
オブジェクトを使用するには、SYS.AQ$_JMS_TEXT_MESSAGE
またはAQ$_JMS_MESSAGE
ペイロード型を持つキュー表を作成します。
ObjectMessage
オブジェクトは、シリアル化可能なJavaオブジェクトを含むメッセージを送信する場合に使用します。ObjectMessageは、Messageから拡張され、単一のJavaオブジェクトへの参照を含む本体を追加します。シリアル化可能なJavaオブジェクトのみを使用できます。Javaオブジェクトのコレクションの送信が必要な場合は、JDK 1.4で提供されたコレクション・クラスの1つを使用できます。このオブジェクトは、getObject()
およびsetObject(
...)
メソッドを使用して読込みまたは書込みができます。ObjectMessage
オブジェクトを使用するには、ペイロード型SYS.AQ$_JMS_OBJECT_MESSAGE
またはAQ$_JMS_MESSAGE
を持つキュー表を作成します。
AdtMessage
オブジェクトは、Oracleのオブジェクト型に対応するJavaオブジェクトを含むメッセージを送信する場合に使用します。これらのオブジェクトはMessage
から継承され、CustomDatum
またはORAData
インタフェースを実装するJavaオブジェクトを含む本体を追加します。
関連項目: CustomDatum インタフェースおよびORAData インタフェースの詳細は、『Oracle Database Java開発者ガイド』を参照してください。
|
AdtMessage
オブジェクトを使用するには、Oracleのオブジェクト型としてのペイロード型を持つキュー表を作成します。AdtMessage
のペイロードは、getAdtPayload
およびsetAdtPayload
メソッドを使用して、読取りおよび書込みができます。
AdtMessage
オブジェクトを使用してSYS.XMLType
型のキューへメッセージを送信することもできます。oracle.xdb.XMLType
クラスを使用してメッセージを作成する必要があります。
AdtMessage
オブジェクトの場合、クライアントが次を取得できます。
JMSXDeliveryCount
JMSXRecvTimeStamp
JMSXState
JMS_OracleExcpQ
JMS_OracleDelay
次のメッセージ・プロパティは、クライアントがsetProperty
コールを使用して設定できます。StreamMessage
、BytesMessage
、ObjectMessage
、TextMessage
およびMapMessage
オブジェクトの場合、クライアントによって次の設定ができます。
JMSXAppID
JMSXGroupID
JMSXGroupSeq
JMS_OracleExcpQ
JMS_OracleDelay
AdtMessage
オブジェクトの場合、クライアントによって次の設定ができます。
JMS_OracleExcpQ
JMS_OracleDelay
次のメッセージ・プロパティは、クライアントがgetProperty
コールを使用して取得できます。StreamMessage
、BytesMessage
、ObjectMessage
、TextMessage
およびMapMessage
オブジェクトの場合、クライアントが次を取得できます。
JMSXuserID
JMSXAppID
JMSXDeliveryCount
JMSXGroupID
JMSXGroupSeq
JMSXRecvTimeStamp
JMSXState
JMS_OracleExcpQ
JMS_OracleDelay
JMS_OracleOriginalMessageID
メッセージの送信時にdeliveryMode
としてNON_PERSISTENT
を指定すると、非永続JMSメッセージを送信できます。JMS非永続メッセージは決まった記憶域に記録する必要がないため、JMSシステム障害が発生すると消失する可能性があります。JMS非永続メッセージはOracle Streams AQで使用可能になったバッファ済メッセージに類似していますが、両者には重要な相違点も存在します。
注意: Oracle JMSの非永続メッセージを、Oracle Database 10gリリース2(10.2)で廃止になったOracle Streams AQの非永続キューと混同しないでください。 |
トランザクションのコミットとクライアントの確認
JMSのdeliveryMode
は、メッセージのトランザクション属性と直交します。JMS非永続メッセージは、処理済セッションまたは非処理済セッションで送受信できます。JMS非永続メッセージを処理済セッションで送受信する場合、JMS操作の効果は処理済セッションのコミット後にのみ参照可能です。CLIENT_ACKNOWLEDGE
確認モードの非処理済セッションで受信する場合、このメッセージの受信による効果は、クライアントがメッセージを確認した後にのみ参照可能です。確認されない場合、メッセージは削除されず、クライアントがSession.recover
をコールすると再配信されます。
これに対して、Oracle Streams AQのバッファ済メッセージでは、このようなトランザクションまたは確認の概念はサポートされません。バッファ済メッセージの送受信は、どちらもIMMEDIATE
可視性モードで実行する必要があります。したがって、セッションがコミットされたかどうかやメッセージが確認されたかどうかは関係なく、ユーザーは送受信操作の効果を即時に参照できます。
各種API
通常のJMS送信およびパブリッシュ・メソッドを使用して送信されたメッセージは、Oracle Streams AQで永続メッセージとして処理されます。通常のJMS受信メソッドは、AQ永続メッセージのみを受信します。 バッファ済メッセージを送受信するには、Oracle拡張APIであるbufferSend
、bufferPublish
およびbufferReceive
を使用する必要があります。
関連項目: bufferSend 、bufferPublish およびbufferReceive の詳細は、『Oracle Streams Advanced Queuing Java API Reference』を参照してください。
|
ペイロード制限
バッファ済メッセージのOracle Streams AQ実装では、LOB
属性はサポートされていません。このため、5種類の標準JMSメッセージのペイロードには次の制限が適用されます。
JMS TextMessage
のペイロードは4000バイト以内です。
Oracle JMSのキャラクタ・セット変換時には、テキスト・ペイロードをデータベースに格納するためにVARCHAR
のかわりにCLOB
を使用するように控え目な選択が必要になる場合があるため、データベース・キャラクタ・セットによってはこの上限値がさらに低くなる場合があります。
JMS BytesMessage
のペイロードは2000バイト以内です。
JavaでシリアライズされたJMS ObjectMessage
、StreamMessage
およびMapMessage
データは、2000バイト以内である必要があります。
他のすべてのOracle JMS ADTメッセージの場合、対応するOracleデータベースADTにLOB
属性を含めることはできません。
各種定数
表11-3に示すように、Oracle Streams AQとOracle JMSのAPIでは、バッファ済メッセージと永続メッセージの指定に使用される数値が異なります。
Point-to-Pointモデルでは、クライアントは、1つのポイントから別のポイントへメッセージを交換します。メッセージのプロデューサとコンシューマは、シングル・コンシューマ・キューを使用してメッセージを送受信します。管理者は、AQjmsSession
のcreateQueue
メソッドを使用して、シングル・コンシューマ・キューを作成します。キューを使用する前に、AQjmsDestination
でstart
コールを使用して、キューをエンキュー/デキューに対して有効にする必要があります。クライアントは、AQjmsSession
のgetQueue
メソッドを使用して事前に作成されたキューに対するハンドルを取得します。
シングル・コンシューマ・キューの場合、メッセージは1つのコンシューマが1度のみ処理できます。同じキューから同時にデキューするプロセスまたはオペレーティング・システム・スレッドが複数存在する場合、各プロセスはキューの先頭にあるロックされていない最初のメッセージをデキューします。ロックを作成したプロセス以外のプロセスは、ロックされたメッセージをデキューできません。
処理が済むと、キューの保存期間が0(ゼロ)の場合はそのメッセージは削除され、そうでない場合は指定された期間保存されます。メッセージが保存されている間は、キュー表ビューに対してSQLを使用して問い合せたり、QueueBrowser
で処理済メッセージのメッセージ識別子を指定してデキューできます。
クライアントは、QueueSender
を使用して、キューにメッセージを送信します。QueueSender
は、キューをクライアントのSession
のcreateSender
メソッドに渡すことで作成されます。また、クライアントにはキューを指定しないで、QueueSender
を作成するオプションがあります。この場合、キューを送信操作のたびに指定する必要があります。
クライアントは、QueueSender
によって送信されたすべてのメッセージのデフォルト配信モード、優先順位およびTimeToLive
を指定できます。または、クライアントはこれらのオプションを各メッセージに対して定義できます。
クライアントは、QueueReceiver
を使用して、キューからメッセージを受信します。QueueReceiver
は、クライアントのSession
のcreateQueueReceiver
メソッドを使用して作成されます。messageSelector
を使用して作成しても、使用せずに作成してもかまいません。
QueueBrowser
を使用すると、クライアントはメッセージを削除しないで、キュー上でメッセージを参照できます。このブラウズ用メソッドは、キュー内のメッセージをスキャンするために使用されるjava
.util
.Enumeration
を戻します。nextElement
に対する最初のコールが、キューのスナップショットを取得します。QueueBrowser
は、messageSelector
を使用して作成しても、使用せずに作成してもかまいません。
QueueBrowser
も、メッセージをスキャン中にオプションでロックできます。これは、メッセージに対するSELECT
...for
UPDATE
コマンドの場合と似ています。これによって、他のコンシューマがスキャン中のメッセージを削除することはなくなります。
messageSelector
によって、クライアントは、コンシューマに配信されるメッセージをmessageSelector
式と一致するメッセージに制限できるようになります。TextMessage
型、StreamMessage
型、BytesMessage
型、ObjectMessage
型またはMapMessage
型のペイロードを含むキューのmessageSelector
には、次の1つ以上を持つ任意の式を含めることができます。
接頭辞「ID:」が付いたJMSメッセージ識別子
JMSMessageID ='ID:23452345'
JMSメッセージ・ヘッダー・フィールドまたはプロパティ
JMSPriority < 3 AND JMSCorrelationID = 'Fiction' JMSCorrelationID LIKE 'RE%'
ユーザー定義のメッセージ・プロパティ
color IN ('RED', BLUE', 'GREEN') AND price < 30000
AdtMessage
型のペイロードを含むキューのmessageSelector
には、次の1つ以上を持つ任意の式を含めることができます。
接頭辞「ID:」なしのメッセージ識別子
msgid = '23434556566767676'
優先順位または相関識別子、あるいはその両方
priority < 3 AND corrid = 'Fiction'
メッセージ・ペイロード
tab.user_data.color = 'GREEN' AND tab.user_data.price < 30000
内容は次のとおりです。
JMSでは、パブリッシャ(出版者)の機能を持つアプリケーションとサブスクライバ(購読者)の役割を果すアプリケーションとの間の柔軟で動的な通信が可能です。アプリケーションが結合されることはなく、メッセージとその内容に基づいて相互に作用します。
メッセージの配信では、パブリッシャ・アプリケーションが明示的にメッセージ受信者を処理または管理する必要はありません。このため、パブリッシャ・アプリケーションの論理を変更しなくても、新しいサブスクライバ・アプリケーションを動的に追加できます。
同様にサブスクライバ・アプリケーションは、メッセージを送信しているパブリッシャ・アプリケーションに関係なく、メッセージの内容に基づいてメッセージを受信します。このため、サブスクライバ・アプリケーションの論理を変更しなくても、新しいパブリッシャ・アプリケーションを動的に追加できます。
サブスクライバ・アプリケーションは、メッセージ・プロパティまたはトピックのメッセージ内容に対してルールベースのサブスクリプション(予約購読)を定義することで、どのようなメッセージに関心があるのかを指定できます。システムは、ルールベースのサブスクリプションを使用して、パブリッシュされたメッセージの受信者を計算し、自動的にルーティングします。
パブリッシュ・サブスクライブ・モデルでは、メッセージはトピックに対してパブリッシュされ、トピックから受信されます。トピックは、AQjmsSession
のCreateTopic()
メソッドを使用して作成されます。クライアントは、AQjmsSession
のgetTopic()
メソッドを使用して事前に作成されたトピックに対するハンドルを取得できます。
クライアントは、クライアントのSession
のcreateDurableSubscriber()
メソッドを使用してDurableSubscriber
を作成します。messageSelector
を使用して作成しても、使用せずに作成してもかまいません。
messageSelector
によって、クライアントは、サブスクライバに配信されるメッセージをセレクタにマッチするメッセージに制限できます。セレクタ構文の詳細は、『Oracle Streams Advanced Queuing Java API Reference』のcreateDurableSubscriber
に関する項を参照してください。
永続サブスクライバが同じ名前を使用するときのアクションは、実行時にOracle Java Message Service(OJMS)クライアントに設定されるJ2EE準拠モードによって異なります。
非準拠モードでは、同じ名前の2つの永続的なTopicSubscriber
オブジェクトが、2つの異なるトピックに対してアクティブになることができます。準拠モードでは、複数の永続サブスクライバが同じ名前を持つことは許可されません。同じトピックに対して作成された2つのサブスクライバが同じ名前を使用する場合、各サブスクライバに使用されるセレクタが異なると、DBMS_AQJMS.ALTER_SUBSCRIBER()
の内部コールを使用して、基になるOracle Streams AQサブスクリプションが変更されます。
2つのサブスクライバが同じ名前を使用し、2つの異なるトピックに対して作成される場合、同じサブスクリプション名を使用するクライアントがそれぞれサブスクリプション名を作成すると、既存のサブスクリプションは削除され新しいサブスクリプションが作成されます。
2つのサブスクライバが同じ名前を使用し、2つの異なるトピックに対して作成される場合、別のクライアント(最初にそのサブスクリプション名を作成したクライアントではない)が既存のサブスクリプション名を使用すると、サブスクリプションは削除されずにエラーが発生します。サブスクリプションがJMSまたはPL/SQLのどちらで作成されたかが不明であるため、その他のトピックについてのサブスクリプションは削除しないでください。
リモート・サブスクライバは、createRemoteSubscriber
コールを使用して定義されます。リモート・サブスクライバは、リモート・トピックでの特定のコンシューマ、またはリモート・トピックでのすべてのサブスクライバになることができます。
リモート・サブスクライバは、AQjmsAgent
構造を使用して定義されます。AQjmsAgent
は、名前およびアドレスで構成されます。名前は、リモート・トピックのconsumer_name
を参照します。アドレスは、次のようにしてリモート・トピックを参照します。
schema.topic_name[@dblink]
リモート・トピックで特定のコンシューマに対してメッセージをパブリッシュするには、リモート・トピックでの受信者のsubscription_name
が、AQjmsAgent
の名前フィールドに指定されている必要があります。リモート・トピックは、AQjmsAgent
のaddressフィールドに指定される必要があります。
リモート・トピックのすべてのサブスクライバに対してメッセージをパブリッシュするには、AQjmsAgent
のnameフィールドをNULLに設定する必要があります。リモート・トピックは、AQjmsAgent
のaddressフィールドに指定される必要があります。
メッセージは、Topic
をcreatePublisher
メソッドに渡すことで作成されるTopicPublisher
を使用してパブリッシュされます。クライアントには、Topic
を指定しないでTopicPublisher
を作成するオプションもあります。この場合、Topic
は、パブリッシュ操作のたびに指定する必要があります。クライアントは、TopicPublisher
によって送信されたすべてのメッセージのデフォルト配信モード、優先順位およびTimeToLive
を指定できます。各メッセージに対してこれらのオプションを指定することもできます。
JMSパブリッシュ・サブスクライブ・モデルでは、クライアントは、トピックのすべてのサブスクライバにメッセージを送信するのではなく、明示的な受信者リストを指定できます。これらの受信者は、トピックの既存のサブスクライバである場合もあれば、そうでない場合もあります。受信者リストは、このメッセージのトピックのサブスクリプション・リストをオーバーライドします。受信者リスト機能は、JMSに対するOracleの拡張です。
受信者名が受信者リストに明示的に指定されていても、その受信者がキューのサブスクライバではない場合、その受信者に送信されるメッセージは、TopicReceiver
を作成することによって受信できます。サブスクライバ名が指定されていない場合、クライアントがメッセージを受信するには、リモート・サイトで永続サブスクライバを使用する必要があります。TopicReceiver
は、JMSに対するOracleの拡張です。
TopicReceiver
は、messageSelector
を使用して作成できます。これによって、クライアントは、受信者に配信されるメッセージをセレクタにマッチするメッセージに制限できます。
TopicBrowser
を使用すると、クライアントはメッセージを削除しないでトピック上でメッセージを参照できます。このブラウズ用メソッドは、トピック・メッセージをスキャンするために使用されるjava.util.Enumeration
を戻します。TopicBrowser
を作成できるのは、永続サブスクライバのみです。nextElement
に対する最初のコールが、トピックのスナップショットを取得します。
TopicBrowser
は、メッセージをスキャン中にオプションでロックできます。これは、メッセージに対するSELECT
...for
UPDATE
コマンドの場合と類似しています。これによって、他のコンシューマがスキャン中のメッセージを削除することはなくなります。
TopicBrowser
は、messageSelector
を使用して作成できます。これによって、クライアントは、コンシューマに配信されるメッセージをセレクタにマッチするメッセージに制限できるようになります。
TopicBrowser
は、パージ機能をサポートしています。これによって、TopicBrowser
を使用するクライアントは、トピックの現行のブラウズ操作中に参照されたすべてのメッセージを廃棄できます。パージとは、参照済のすべてのメッセージを破壊的に受信することと同じです(TopicSubscriber
を使用して削除した場合と似ています)。
パージでは、メッセージがTopicBrowser
のjava.lang.Enumeration
のnextElement()
操作へのコールを使用してクライアントに戻された場合、そのメッセージは参照済とみなされます。クライアントがまだ参照していないメッセージは、パージ中には廃棄されません。パージ操作は、同じTopicBrowser
に対して何度も実行できます。
TopicBrowser
の作成に使用したJMS Session
がコミットされると、パージは正常に実行されます。セッションに対する操作がロールバックされた場合、パージ操作も取り消されます。
JMSでパブリッシュ・サブスクライブ・モデルの通信を使用する手順は、次のとおりです。
メッセージを保持するために1つ以上のトピックを設定します。これらのトピックは、関心がある領域またはサブジェクトを表します。たとえば、トピックで請求済注文情報を表すことができます。
AQjmsDestination
でstart
コールを使用して、トピックに対するエンキュー/デキューを有効にします。
永続サブスクライバのセットを作成します。各サブスクライバは、受信を希望するメッセージを選択するmessageSelector
を指定できます。NULLのmessageSelector
は、そのトピックに対してパブリッシュされたすべてのメッセージの受信をサブスクライバが希望していることを示します。
サブスクライバはローカルでもリモートでもかまいません。ローカル・サブスクライバは、メッセージがパブリッシュされるトピックと同じトピックに対して定義された永続サブスクライバです。リモート・サブスクライバは、特定のキューのサブスクライバとして定義された別のトピックまたはそのトピックに対する受信者です。リモート・サブスクライバを使用するには、ソース・トピックと宛先トピック間の伝播を設定する必要があります。リモート・サブスクライバと伝播は、JMSに対するOracleの拡張です。
パブリッシャのSession
でcreatePublisher()
メソッドを使用してTopicPublisher
オブジェクトを作成します。メッセージは、publish
コールを使用してパブリッシュされます。メッセージは、トピックのすべてのサブスクライバ、またはトピックに対する指定された受信者のサブセットに対してパブリッシュできます。
サブスクライバは、receive
メソッドを使用してトピックに関するメッセージを受信します。
サブスクライバは、メッセージ・リスナーを使用して、非同期にメッセージを受信することもできます。
メッセージの順序付けとは、キューまたはトピックからメッセージが受信される順序を示します。優先順位の指定は、キューまたはトピックに対してキュー表が作成されるときに指定されます。現在、Oracle Streams AQではメッセージ優先順位とエンキュー時刻の順序付けをサポートしています。順序付けには、次の4つの方法があります。
First-In, First-Out(FIFO)
エンキュー時刻が順序付け基準として選択されると、メッセージはエンキュー時刻の順序で受信されます。エンキュー時刻は、メッセージのパブリッシュ/送信時にOracle Streams AQによってメッセージに割り当てられます。これはデフォルトの順序付けです。
優先順位による順序付け
優先順位による順序付けが選択されると、各メッセージに優先順位が割り当てられます。優先順位は、パブリッシュ/送信時にメッセージ・プロデューサ
によってメッセージ・プロパティとして指定できます。メッセージは、割り当てられた優先順位の順序で受信されます。
FIFO優先順位
FIFO優先順位による順序付けが選択されると、トピックまたはキューは優先順位による順序付けの場合と同様に機能します。2つのメッセージに同じ優先順位が割り当てられた場合、両者はエンキュー時刻の順に受信されます。
エンキュー時刻に続く優先順位による順序付け
同じエンキュー時刻のメッセージは、そのメッセージの優先順位に従って受信されます。2つのメッセージの順序付け基準が同じ場合、受信される順序は予想できません。ただし、1つのセッション中に特定の順序付け基準で生成されたメッセージは、送信された順序で受信されることがOracle Streams AQにより保証されます。
メッセージをキュー/トピックに対して送信/パブリッシュするときに、遅延を指定できます。遅延は、そのメッセージがメッセージ・コンシューマに対して使用可能になるまでの時間を表します。遅延指定されたメッセージは、遅延の期限が切れるまで待機状態になります。遅延指定は、メッセージ識別子による受信でオーバーライドされます。
遅延は、JMSメッセージ・プロパティに対するOracle Streams AQの拡張機能です。遅延の場合、Oracle Streams AQ用のバックグラウンド処理キュー・モニターを起動する必要があります。
メッセージのプロデューサは、メッセージの期限切れまたはTimeToLive
を指定できます。これによって、そのメッセージがメッセージ・コンシューマに対して使用可能な期間が定義されます。
TimeToLive
は、送信/パブリッシュ時に指定するか、またはMessageProducer
のTimeToLive
メソッドを使用して指定できます。前者が優先されます。Oracle Streams AQのバックグラウンド処理キュー・モニターを実行して、TimeToLive
を実装する必要があります。
1つのキュー/トピックに属しているメッセージをグループ化して1つのセットにし、一度に1コンシューマ以外は使用できないようにできます。そのためには、トランザクションでのメッセージのグループ化に対応したキュー表に、そのキュー/トピックを作成する必要があります。1つのグループに属するすべてのメッセージは、同じトランザクションで作成される必要があります。また、1つのトランザクションで作成されるすべてのメッセージは、同じグループに属します。
メッセージのグループ化は、JMS仕様に対するOracle Streams AQの拡張機能です。
この機能を使用すると、複雑なメッセージを、リンクされた一連の単純なメッセージに分割できます。たとえば、請求書キュー宛ての請求書は、ヘッダーのメッセージ、詳細情報の複数のメッセージ、フッターのメッセージの順に分割できます。
小さいオブジェクトに分割できるイメージやビデオなどの複合LOBがメッセージ・ペイロードにある場合は、メッセージのグループ化が非常に有効です。
グループに含まれるメッセージの優先順位、遅延および期限切れの各プロパティは、単にグループの最初のメッセージ(ヘッダー)のプロパティによってのみ判断されます。グループの他のメッセージのプロパティは無視されます。
メッセージ・グループは、伝播中も保持されます。宛先トピックは、トランザクション処理のグループ化に対して使用可能にしておく必要があります。
内容は次のとおりです。
JMSアプリケーションは、メッセージ・コンシューマを作成することによって、メッセージを受信できます。メッセージは、receive
コールを使用して同期的に受信するか、メッセージ・リスナーを使用して非同期的に受信できます。
受信モードには次の3つがあります。
メッセージがコンシューマに届くまでブロック
指定最大時間までブロック
非ブロック
コンシューマがナビゲーション・モードを指定しない場合、セッションの最初のreceive
はキューまたはトピックの最初のメッセージを取り出し、第2のreceive
は次のメッセージを取得します。優先順位が高いメッセージがコンシューマに届く場合、すでに届いているメッセージを削除するまで、コンシューマはこのメッセージを受信しません。
コンシューマが、メッセージに対してより効率的にキューのナビゲーションを制御できるように、Oracle Streams AQにはJMS拡張機能として複数のナビゲーション・モードが用意されています。これらのモードは、TopicSubscriber
、QueueReceiver
またはTopicReceiver
で設定できます。
グループ化されていないメッセージには、次の2つのモードを使用できます。
FIRST_MESSAGE
このモードでは、位置がキューの先頭にリセットされます。このモードでは、コンシューマによるキューの最上位にあるメッセージの削除が許可されているため、優先順位によって順序付けられたキューに有効です。
NEXT_MESSAGE
このモードは、コンシューマの確立された位置の後のメッセージを取得します。たとえば、4番目のメッセージの位置で適用されたNEXT_MESSAGE
は、そのキューの5番目のメッセージを取得します。これはデフォルトのアクションです。
グループ化メッセージには、次の3つのモードを使用できます。
FIRST_MESSAGE
このモードでは、位置がキューの先頭にリセットされます。
NEXT_MESSAGE
このモードでは、位置が同一トランザクションの次のメッセージに設定されます。
NEXT_TRANSACTION
このモードでは、位置が次のトランザクションの最初のメッセージに設定されます。
次の方法でメッセージが受信される場合、グループ化トランザクションのプロパティを無効にできます。
セレクタに相関識別子を指定して受信
セレクタにメッセージ識別子を指定して受信
トランザクション・グループのメッセージがすべて受信される前にコミット
NEXT
_MESSAGE
またはNEXT
_TRANSACTION
オプションの使用中にコンシューマがキューの最後に到達したとします。ブロッキングreceive()
を指定していた場合は、ナビゲート位置は自動的にそのキューの先頭に変更されます。
デフォルトでは、QueueReceiver
、TopicReceiver
またはTopicSubscriber
は、最初のreceiveコールにFIRST_MESSAGE
を、以降のreceive()
コールにNEXT_MESSAGE
を使用します。
デキューするクライアントがキューからメッセージを削除できる通常のreceive
の他に、JMSでは、JMSクライアントがキューで自身のメッセージをブラウズできるようにするインタフェースを提供しています。QueueBrowser
は、QueueSession
からcreateBrowser
メソッドを使用して作成できます。
メッセージが参照されると、そのメッセージは引き続き処理できます。メッセージがブラウズされた後は、同時セッションからreceive
コールがそのメッセージを削除する場合があるため、JMSセッションに引き続き使用できるとはかぎりません。
一度参照したメッセージが同時JMSクライアントによって削除されないようにするために、ロック・モードでメッセージを参照できます。そのためには、JMSインタフェースに対するOracle Streams AQの拡張機能を使用して、ロック・モードを持つQueueBrowser
を作成する必要があります。メッセージのロックは、セッションがコミットまたはロールバックを実行すると解放されます。
QueueBrowser
によって参照されたメッセージを削除するには、セッションがQueueReceiver
を作成し、JMSmesssageID
をセレクタとして使用する必要があります。
コンシューマは、
receiveNoData
コールを使用して、メッセージを取り出さないでキューまたはトピックから削除できます。これは、アプリケーションがQueueBrowser
を使用してすでにメッセージを調べている場合に便利です。このモードによって、JMSクライアントは、データベースからペイロードを取り出す場合のオーバーヘッドを回避できます。このオーバーヘッドは、大量のメッセージでは相当量になる可能性があります。
キュー/トピックからメッセージを受信するトランザクションが失敗した場合、そのメッセージを削除する試行に失敗したとみなされます。Oracle Streams AQは、メッセージ削除の試行に失敗した回数をメッセージ履歴に記録します。
アプリケーションでは、メッセージに対する再試行の最大回数をキュー/トピック・レベルで指定できます。メッセージ削除がこの数より多く失敗した場合、メッセージは例外キューに移動されます。
Oracle Streams AQでは、ユーザーはmax_retries
とともにretry_delay
も指定できます。これは、受信の試行に失敗したメッセージを、retry_delay
間隔後に引き続きキューで参照し、デキューできることを意味します。それまでこのメッセージはWAITING
状態になります。Oracle Streams AQのバックグラウンド・プロセスのタイム・マネージャは、再試行遅延プロパティを強制的に適用します。
再試行の最大回数および再試行の遅延は、キュー/トピックのプロパティです。このプロパティは、キュー/トピックの作成時、またはキュー/トピックに対する変更メソッドを使用して設定できます。MAX_RETRIESのデフォルト値は5です。
JMSクライアントは、setMessageListener
メソッドを使用してMessageListener
を設定することによって、メッセージを非同期的に受信できます。
コンシューマにメッセージが届いた場合、メッセージ・リスナーのonMessage
メソッドがそのメッセージで起動されます。メッセージ・リスナーは、メッセージの受信をコミットまたは異常終了できます。メッセージ・リスナーは、JMSコネクションが停止されている場合、メッセージを受信しません。一度メッセージ・リスナーがコンシューマに対して設定されると、メッセージの受信に
receive
コールを使用することはできません。
JMSクライアントは、セッションでMessageListener
を設定することによって、そのセッションのすべてのコンシューマに対してメッセージを非同期的に受信できます。一度メッセージ・リスナーが設定されると、そのセッションでは、その他のメッセージ受信モードを使用できません。
例外キューは、期限切れまたは処理できないすべてのメッセージのリポジトリになります。アプリケーションから例外キューには直接エンキューできません。ただし、期限切れまたは処理できないメッセージを処理するアプリケーションは、例外キューからこれらのメッセージを受信または削除できます。
例外キューからメッセージを取り出すには、JMSクライアントはPoint-to-Pointインタフェースを使用する必要があります。トピック用のメッセージの例外キューは、使用可能な複数のコンシューマでキュー表に作成する必要があります。他のキューと同様に、例外キューもAQOracleQueue
クラスでstart
メソッドを使用して、メッセージを受信できる必要があります。例外キューをエンキュー可能に設定しようとすると、例外が発生します。
例外キューは、「JMS_OracleExcpQ
」と呼ばれるOracle固有のメッセージ・プロパティです。これは、メッセージの送信/パブリッシュ前に、そのメッセージで設定できます。例外キューが指定されていないと、デフォルトの例外キューが使用されます。キュー表が作成されると、デフォルトの例外キューがAQ$_
queue_table_name
_E
という名前で自動的に作成されます。
メッセージは、次の条件が成立するときに例外キューに移されます。
そのメッセージが、指定されたtimeToLive
内にデキューされなかった場合。
複数のサブスクライバを指定したメッセージの場合、指定されたtimeToLive
内にそのメッセージをデキューできない受信者が1つ以上あると、メッセージは例外キューに移されます。
メッセージが正常に受信されたが、メッセージ処理中のエラーのためアプリケーションがreceive
を実行したトランザクションを異常終了した場合。そのメッセージはキュー/トピックに戻され、メッセージ受信のために待機中のどのアプリケーションでも使用可能になります。
アプリケーションがトランザクション全体を異常終了するか、receive
前のセーブポイントまでロールバックしたときは、receive
がロールバックまたはUNDOされたとみなされます。
これは失敗したメッセージ受信の試行であるため、その再試行回数は更新されます。メッセージの再試行回数が、メッセージが常駐するキュー/トピックに指定された最大値を超える場合、そのメッセージは例外キューに移されます。
メッセージが複数のサブスクライバを持つ場合、そのメッセージは、すべての受信者が再試行制限を超えたときにのみ、例外キューに移されます。
注意: サーバー・プロセスがインスタンスで停止した(ALTER SYSTEM KILL SESSION など)、またはSHUTDOWN ABORT によってデキュー・トランザクションが失敗した場合、RETRY_COUNT は増分されません。
|
内容は次のとおりです。
Oracle Streams AQによって、他のデータベースにあるサブスクライバをトピックにサブスクライブできます。トピックに対してパブリッシュされたメッセージがリモート・サブスクライバの基準を満たしている場合は、リモート・サブスクライバに指定されているリモート・データベースにあるキュー/トピックに自動的に伝播します。伝播は、データベース・リンクおよびOracle Net Servicesを使用して実行されます。これによって、同じデータベースに接続しなくても、アプリケーション同士が互いに通信できます。
リモート・サブスクライバを実装するには、次の2つの方法があります。
createRemoteSubscriber
メソッドは、トピック上またはトピックに対してリモート・サブスクライバを作成するために使用します。このリモート・サブスクライバは、クラスAQjmsAgent
のインスタンスとして指定されます。
AQjmsAgent
には、名前およびアドレスがあります。アドレスは、キュー/トピックおよびサブスクライバのデータベースへのデータベース・リンクで構成されています。
リモート・サブスクライバには、次の2種類があります。
リモート・サブスクライバがトピックである場合。
これは、AQjmsAgent
オブジェクトのリモート・サブスクライバに名前が指定されず、アドレスがトピックである場合に発生します。サブスクライバのサブスクリプションを満たすメッセージが、リモート・トピックに伝播されます。伝播されたメッセージは、それが満たすリモート・トピックのすべてのサブスクリプションに対して使用可能になります。
メッセージに対して特定のリモート受信者を指定する場合。
リモート・サブスクリプションは、リモート・データベースにある特定のコンシューマに対して指定できます。リモート受信者の名前が(AQjmsAgent
オブジェクトに)指定される場合、サブスクリプションを満たすメッセージが、その受信者専用のリモート・データベースに伝播されます。リモート・データベースにある受信者は、TopicReceiver
インタフェースを使用してメッセージを取り出します。リモート・サブスクリプションは、Point-to-Pointキューに対して指定することもできます。
伝播は、メッセージがターゲットの接続先データベースに伝播されるすべてのトピックについて、schedule_propagation
メソッドを使用してスケジューリングされる必要があります。
スケジュールは時間の枠を示し、メッセージはその枠内でソース・トピックから伝播されます。この時間枠は、ネットワーク通信量、ソース・データベースの負荷、接続先データベースの負荷などの多くの要因に左右されます。したがって、スケジュールは特定のソースおよび宛先にあわせて調整する必要があります。スケジュールが作成されると、ジョブは自動的にjob_queue
の機能に発行され、伝播が処理されます。
伝播スケジュールのための運用管理コールによって、スケジュール管理を柔軟に行うことができます。あるスケジュールの存続時間または伝播枠パラメータによって、伝播が開始される時間枠が指定されます。存続時間が指定されない場合、時間枠は無制限の単一枠になります。枠を定期的に繰り返す必要がある場合、連続する枠の間の周期的間隔を定義するnext_time
機能を使用して有限の存続時間を指定します。
あるキューに定義された伝播スケジュールは、そのキューの有効期間中いつでも変更または削除できます。さらに、(スケジュールを削除するかわりに)一時的に使用不可にするコール、および使用不可のスケジュールを使用可能にするコールがあります。メッセージがスケジュール内で伝播されているとき、そのスケジュールはアクティブです。すべての管理コールは、スケジュールがアクティブかどうかに関係なく実行されます。スケジュールがアクティブの場合、コールが実行されるまでに数秒かかります。
伝播が開始されるには、ジョブ・キュー・プロセスを起動する必要があります。少なくとも2つのジョブ・キュー・プロセスを起動する必要があります。接続先データベースへのデータベース・リンクも有効にする必要があります。伝播のソースおよび宛先トピックは、同じメッセージ型である必要があります。リモート・トピックは、エンキューできる必要があります。データベース・リンクのユーザーもリモート・トピックに対するエンキュー権限を持つ必要があります。
伝播のために定義されたカタログ・ビューは、アクティブ・スケジュールに関する次の情報を提供します。
そのスケジュールを処理しているバックグラウンド・プロセスの名前
伝播を処理しているセッションのSID(セッションおよびシリアル番号)
スケジュールを処理しているインスタンス(RACを使用している場合)
先行して正常に実行されたスケジュール
次に実行予定のスケジュール
スケジュールごとに次の伝播統計が保持され、キュー管理者がスケジュール調整に役立てることができます。
スケジュールの中で伝播されたメッセージ合計数
スケジュールの中で伝播されたバイト合計数
伝播枠の中で伝播されたメッセージの最大数
伝播枠の中で伝播されたバイトの最大値
伝播枠の中で伝播されたメッセージの平均数
伝播済メッセージの平均サイズ
伝播済メッセージの平均時間
伝播機能には、障害対処およびエラー・レポートが組み込まれています。たとえば、指定されたデータベース・リンクが無効な場合、リモート・データベースが使用できない場合、またはリモート・トピック/キューにエンキューできない場合、適切なエラー・メッセージがレポートされます。伝播は指数バックオフ・スキームを使用して、障害が発生したスケジュールからの伝播を再試行します。あるスケジュールで続けて障害が発生したときは、最初の再試行は30秒後、次の再試行は60秒後、3回目の再試行は120秒後、というように続きます。再試行時間が現行の伝播枠の期限切れ時刻を超える場合は、次の再試行は、次の伝播枠の開始時刻に行われます。最大16回の再試行が行われた後、そのスケジュールは自動的に使用不可能になります。
注意: 再試行が次の伝播枠にずれ込むと、常にずれ込むようになります。再試行スケジュールは指数バックオフ・スキームでは制御されなくなります。DBMS_AQADM.SCHEDULE_PROPAGATION() のnext_time パラメータに指定した日付関数により伝播枠間の間隔が短くなると、再試行の失敗回数がすぐに16を超えてスケジュールが使用不可になります。
|
障害のためにスケジュールが自動的に使用不可になると、関連情報がアラート・ログに書き込まれます。スケジュールに障害が発生しているかどうか、さらに発生している場合は連続的な障害が何回起きたかということが、最新の障害の原因および発生時刻を示すエラー・メッセージによって確認できます。この情報を調べることで、管理者は障害を回復し、スケジュールを使用可能にできます。
再試行の間に伝播が成功したときは、障害の数は0(ゼロ)にリセットされます。
伝播機能にはReal Application Clustersサポートが組み込まれていますが、ユーザーおよび管理者には透過的です。伝播を処理するジョブは、ソース・トピックが常駐しているキュー表の所有者と同じインスタンスに送られます。あるインスタンスに障害が発生してトピックを保存しているキュー表が他のインスタンスに移される場合は、伝播ジョブも必ず自動的に新しいインスタンスに移行されます。これによって、インスタンス間のping操作は最小限に抑えられ、パフォーマンスが向上します。伝播は、同時スケジュールをいくつでも処理できるように設計されています。
job_queue_processes
の最大数は1000で、その一部は伝播に関連しないジョブの処理に使用できます。このために、伝播にはマルチタスキングおよびロード・バランスのサポートが組み込まれています。伝播アルゴリズムは、複数スケジュールが単一スナップショット(job_queue
)のプロセスによって処理できるように設計されています。job_queue
プロセスに対する伝播の負荷は、異なるソース・トピックからのメッセージ到着の割合に基づいて偏りが発生する場合があります。あるプロセスが数個のアクティブ・スケジュールによって過負荷になっている一方で、別のプロセスは受動的なスケジュールが多いために余力があるというとき、伝播はプロセス間で負荷が均等になるようにスケジュールを自動的に再分配します。
ネットワーク障害のようなシステム・エラーが発生した場合、Oracle Streams AQは指数バックオフ・アルゴリズムを使用してメッセージを伝播する試みを継続します。キューからデータベース・リンクへの伝播中のアプリケーション・エラーを示している状況では、Oracle Streams AQはそのメッセージにUNDELIVERABLE
というマークを付けてalert.log
に記録します。このようなエラーは、リモート・キューが存在しない場合、またはソース・キューおよびリモート・キューの型が一致しない場合に発生します。background_dump_dest
ディレクトリのトレース・ファイルには、そのエラーに関する追加情報があります。
新規のジョブ・キュー・プロセスが開始すると、型を再検証できるように型の不一致エラーを消去します。ジョブ・キュー・プロセス数に上限を設定して、伝播のビジー状態が続く場合、ジョブ・キュー・プロセスが終了して再開するまで待つ必要はありません。キューの型は、必要に応じてDBMS_AQADM.VERIFY_QUEUE_TYPES
を使用して再検証できます。
注意: キューからキューへの伝播中に型の不一致が検出されると、伝播は停止してエラーが発生します。このような場合は、DBA_SCHEDULES ビューを問い合せて、特定の宛先への伝播中に発生した最後のエラーを判断する必要があります。このメッセージには、UNDELIVERABLE マークは付いていません。
|
あるフォーマットのメッセージを別のフォーマットのメッセージにマップするために変換を定義できます。変換は、同一の情報を異なるフォーマットで表現するアプリケーションを統合する必要がある場合に有効です。変換はSQL式およびPL/SQLファンクションです。メッセージ変換は、標準JMSインタフェースに対するOracle Streams AQの拡張機能です。
変換は、DBMS_TRANSFORM.create_transformation
プロシージャを使用して行います。変換は、次の操作を行う場合に指定できます。
キューまたはトピックへのメッセージの送信
キューまたはトピックからのメッセージの受信。
TopicSubscriber
の作成
RemoteSubscriber
の作成。これによって、異なるフォーマットのトピック間でメッセージを伝播できます。
Oracle Database 10gでは、Oracle JMSはSun社のJMS 1.1標準に準拠しています。実行時に、Oracle Java Message Service(OJMS)クライアントに対してJ2EE準拠モードを定義できます。準拠モードにするには、コマンドライン・オプションとしてJavaプロパティ oracle.jms.j2eeCompliant
をTRUE
に設定します。非準拠モードにする場合は何もしません。FALSE
がデフォルト値です。
J2EE準拠をサポートし、非準拠モードでも使用できるOracle Streams AQの機能は次のとおりです。
非トランザクション・セッション
永続サブスクライバ
一時キューおよびトピック
非永続配信モード
AQ$_JMS_MESSAGE
型のOracle Streams AQキューを使用した単一のJMSキューまたはトピックに対する複数のJMSメッセージ・タイプ
永続サブスクライバに対するnoLocal
オプション
関連項目
|