...

MQ Java デザインのポイント ISE Web & Transaction System 2003年7月

by user

on
Category: Documents
421

views

Report

Comments

Transcript

MQ Java デザインのポイント ISE Web & Transaction System 2003年7月
MQ Java
デザインのポイント
ISE Web & Transaction System
2003年7月
<MQ Java デザインのポイント>
トピック
Web環境でのメッセージング処理パターン
一方向型
要求/応答型
デザインのポイント
一方向型処理で使用される機能
要求/応答型処理で使用される機能
その他の機能
Base JavaとJMSの機能比較
! 当資料内の情報には、ISEによるテスト結果を基にしたものが含まれています。これらの情報は、マニュ
アルには記載されておらず、今後、変更される可能性があります。
! 当資料内のコーディング・イメージは、アプリケーションとして使用されることを想定していません。(エラー
処理等は省いています) 従って、そのまま使用し、正常に稼動することは保証していません。
2
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
メッセージング処理パターン
3
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
トピック
Web環境でのメッセージング処理パターン(1)
一方向型
一方向型処理のデザイン
"
"
複数メッセージ処理
1対N通信
Web環境でのメッセージング処理パターン(2)
要求/応答型
要求/応答型と一方向型との混在
要求/応答型処理のデザイン
"
"
"
"
応答メッセージの返却先
要求メッセージと応答メッセージの紐付け
サーバ・アプリケーションの起動方法
UOWの設定
4
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
Web環境でのメッセージング処理パターン(1)
一方向型
1対1、1対Nのデータ送信
送信側アプリケーション
"
"
ブラウザーからのリクエストでデータを送信する
論理的な宛先を意識してデータを送信(最終送信先は知らなくて良い)
例)キュー名、トピック名、ポート名 など
受信側アプリケーション
1.
2.
"
ブラウザーからのリクエストでデータを受信する
or
サーバ・アプリケーションとして起動され、メッセージを受信、処理する
論理的な宛先を意識してデータを受信(送信元は意識しなくて良い)
例)キュー名、トピック名、ポート名 など
MQPUT
MQGET
受信側アプリケーション(1)
MQGET
送信側アプリケーション
受信側アプリケーション(2)
5
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
一方向型処理のデザイン
複数メッセージをグループとして処理する場合
扱うデータが大きい場合には、複数メッセージに分割して送受信する
"
ファイル転送、イメージ・データ転送など
送信側/受信側アプリケーションは、複数メッセージを1UOWとする
複数メッセージ間の紐付け、順序管理を行なう
"
"
MQ論理メッセージ、グループ・メッセージ機能を利用
MsgID、CorrelIdを利用してグループ化を行なう
MQPUT
:
:
MQCMIT
:
:
送信側アプリケーション
MQGET
:
:
MQCMIT
受信側アプリケーション
6
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
一方向型処理のデザイン
全てのメッセージが届いてから、メッセージ受信するためには…
論理メッセージ機能を利用
"
MQGET時のオプションにMQGMO_ALL_MSGS_AVALABLEを指定
制御用キューとデータ用キューを利用
"
"
データ用キューに複数メッセージ送信後、制御用キューに制御メッセージを送信
制御メッセージが届けば、データ・メッセージはすべてキューに到着済
制御メッセージとデータ・メッセージの紐付けはCorrelIDを利用
MDBで複数メッセージを処理するためには..
MDBは起動時には1メッセージしか受信しない
#起動後、ユーザロジック内で複数メッセージを受信する
制御用キューとデータ用キューを利用
"
"
制御用キューをリスナー・ポートとして設定
onMessage() 内で、データ用キュー内のメッセージを受信する
MQPUT
:
:
MQCMIT
:
データ用キュー
MQGET
:
MDB
:
リスナー
ポート
送信側アプリケーション
EJBコンテナ
制御用キュー
7
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
一方向型処理のデザイン
“1対N通信 = Pub/Subモデル“とは限らない
Pub/Subモデルが適しているケース
"
"
送信側(パブリッシャー)は、宛先を意識しない
受信側(サブスクライバー)が欲しいデータを、能動的に登録/取り消しする場合
PTPモデルが適しているケース
"
"
"
複数宛先を送信側で決定したい場合
送信側は、宛先を意識しないが、管理者が宛先を登録、変更する場合
受信側が、受け取るデータを登録しない場合
Pub/Subモデル利用時の考慮点
Pub/Sub用のブローカーが必要(次のいづれか1つ)
"
"
"
"
"
WebSphere MQ Event Broker
WAS V5に付属の Broker 機能
WebSphere MQ Integrator に付属の Broker 機能
WebSphere Business Integration Message Brokers のEvent Broker 機能
サポート・パック:MA0C MQSeries Publish/Subscribe
http://www-3.ibm.com/software/integration/support/supportpacs/individual/ma0c.html
"
それぞれ機能が異なるので注意
ブローカーの運用、管理、バックアップ
サブスクライバーが受信データを登録する際、セキュリティ・チェックが必要
8
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
Web環境でのメッセージング処理パターン(2)
要求/応答型(同期型)
1対1のデータ通信
クライアント・アプリケーション(要求側)
"
"
ブラウザーからのリクエストで、要求メッセージを論理的な宛先に送信
応答メッセージの到着を、指定した宛先で待つ
サーバ・アプリケーション(応答側)
"
"
要求メッセージを待ち、処理、応答メッセージを返す常駐アプリケーション(Javaアプリ)
メッセージが届いたら、起動されデータを受信、処理、応答を返す(MDB)
UOWは次の3つに分割される
"
"
"
要求メッセージの送信
要求メッセージの受信、処理、応答メッセージの送信
応答メッセージの受信
MQPUT
MQGET
INSERT
MQPUT
MQGET
クライアント・
アプリケーション
サーバ・アプリケーション
9
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
Web環境でのメッセージング処理パターン
要求/応答型と一方向型との混在
クライアント・アプリケーション(要求側)
1. ブラウザーからのリクエストで要求メッセージを論理的な宛先に送信
ブラウザーに受付IDなどを返す
2. ブラウザーから受付IDを受け取り、応答キューからメッセージを受信する
サーバ・アプリケーション(応答側)
"
"
要求メッセージを待ち、処理、応答メッセージを返す常駐アプリケーション(Javaアプリ)
メッセージが届いたら、起動されデータを受信、処理、応答を返す(MDB)
MQPUT
MQGET
INSERT
MQPUT
ID
クライアント・アプリケーション(1)
ID
サーバ・アプリケーション
MQGET
クライアント・アプリケーション(2)
10
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
要求/応答型処理のデザイン
応答メッセージの返却先
クライアント・アプリケーションが、要求メッセージ内に応答先を指定
"
"
MQMDのReplyToQに応答キュー名を指定
RepylToQMgrは自動的に設定される
サーバ・アプリケーションは、指定された応答先に応答メッセージを返す
"
"
"
要求メッセージ内のReplyToQ、ReplyToQmgr を指定してキューをオープンし、応答を送
信
キュー・マネージャー名がリモートであれば、同名のトランスミッション・キューがオープンされる
リモート・キュー定義は不要
QM1(キュー・マネージャー名)
RQMNAME(QM2)
RQMNAME(QM2)
RNAME(LQ2)
RNAME(LQ2)
QM2(キュー・マネージャー名)
LQ2(ローカル・キュー)
MQOPEN
RQ2
クライアント・
アプリケーション
RQ2(リモートキュー)
MQOPEN
QM1 、LQ1
MQチャネル
QM1(
(XMITQ)
LQ1(ローカル・キュー)
サーバ・
アプリケーション
トランスミッション・キュー(XMITQ)は、接続相手の
キュー・マネージャーと同一名称に設定する
11
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
要求/応答型処理のデザイン
要求メッセージと応答メッセージの紐付け
メッセージID(MsgID)、相関ID(CorrelId)を利用して対応させる
クライアント・アプリケーション
"
"
MQMDのMsgIDを設定:MQに採番させても良い
JMSはMsgIDをユーザ設定できないので、MQに採番させる
CorrelID=要求メッセージのMsgID で、メッセージを選択して応答キューを待つ
サーバ・アプリケーションは、要求メッセージのMsgIDを応答メッセージのCorrelIDに設
定し返す
複数クライアントで1つの応答キューを共有することが可能
その他
クライアント・アプリケーションは、応答キューを待つタイムアウト値を設定
"
WaitInterval指定
照会型のメッセージには、有効期限を設定
"
Expiry
クライアント・アプリケーション
MQPUT
MsgID=MQMI_NONE
:
MQGET
CorrelID=要求メッセージのMsgID
サーバ・アプリケーション
MQGET
:
MQPUT
CorrelID=要求メッセージのMsgID
12
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
要求/応答型処理のデザイン
サーバ・アプリケーションの起動方法
常駐Javaアプリケーション
"
トランザクションを開始して、要求キューにメッセージが来るのを待ち受ける
MDB
"
リクエスト・メッセージが到着したら、起動されるMDBを作成
UOWの設定
クライアント・アプリケーションの、メッセージ送信と受信のUOWは分かれる
"
同期を取らないと、要求メッセージが送信されないから
サーバ・アプリケーションは、要求メッセージと応答メッセージまでを1つのUOWに設定
"
MDBの場合、トランザクションは、コンテナ管理(CMT)と設定する
UOW
MQPUT
MQGET
INSERT
MQPUT
UOW
MQGET
クライアント・
アプリケーション
UOW
サーバ・アプリケーション
13
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
デザインのポイント
14
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
トピック
デザインのポイント
一方向型処理で使用される機能
"
グループ化/セグメント化
応答/要求型処理で使用される機能
"
"
要求/応答メッセージの紐付け
応答先の指定/応答先への送信
その他の機能
"
"
"
"
"
"
"
"
クライアント接続
Browse機能
メッセージの永続性
同期点処理
グローバル・トランザクション
コネクション・プーリング
エラー処理
トレース機能
JMSでコーディングする際の注意点
機能比較
15
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
一方向型処理で使用される機能
グループ化/セグメント化
大きなデータを複数のメッセージに分割して送信
"
ファイル転送、イメージ・データ転送
受信側は、複数メッセージを組み立て、1つのデータとして処理
メッセージの順序性が保証される
同じサーバ・インスタンスで処理される
グループ化
アプリケーションがメッセージの分割/組み立てを行なう
"
メッセージは、MQMDのグループID(GroupId)と順序番号(MsgSeqNumber)で関連づけられる
受信アプリケーション
送信アプリケーション
pmo.options
= MQPMO_LOGICAL_ORDER
MQPUT
(MQMF_MSG_IN_GROUP)
MQPUT
(MQMF_MSG_IN_GROUP)
MQPUT
(MQMF_LAST_MSG_IN_GROUP)
gmo.options
= MQGMO_LOGICAL_ORDER
While(GroupStatus
== MQGS_MSG_IN_GROUP)
{
MQGET
}
GrpID=1
順序番号=1
GrpID=1
順序番号=2
GrpID=1
順序番号=3
16
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
一方向型処理で使用される機能
セグメント化
キュー・マネージャーがメッセージの分割/組み立てを行なう
"
"
キュー・マネージャーもしくはキューの最大メッセージ長(MaxMsgLength)より大きいメッセージを
PUTしたときのみセグメント化が行なわれる
メッセージは、MQMDのグループID(GroupId)、順序番号(MsgSeqNumber)、オフセット
(Offset)で関連づけられる
アプリケーションは、メッセージの分割/組み立てを行なう必要はない
"
PUT/GET時にセグメント化を意識したオプションを設定する必要はある
$
PUT時は、MQMF_SEGMENTATION_ALLOWEDを指定
$
GET時は、MQGMO_COMPLETE_MSGを指定
送信アプリケーション
MQPUT
(MQMF_SEGMENTATION_ALLOWED
)
キュー・マネージャー
GrpID=1
順序番号=1
Offset=0
受信アプリケーション
GrpID=1
順序番号=1
Offset=10
gmo.options
= MQGMO_COMPLETE_MSG
MQGET
GrpID=1
順序番号=1
Offset=20
17
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
グループ化/セグメント化
比較
Base Java
JMS
グループ化
◎(MQIと同等の設定が可能)
・キュー・マネージャーによるIDの自動採番
・全てのMSGが揃ってからGETすることが可能
△
・ユーザがグループIDや順序番号を設定
・MQGMO_LOGICAL_ORDERの指定はできない
・MQGMO_ALL_MSGS_AVAILABLEの指定はでき
ない
セグメント化
◎(MQIと同等の設定が可能)
×(利用不可)
注:MQ z/OS版では、セグメント化機能はサポートされていない
18
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BJ
グループ化(BaseJava)
MQIと同様のオプションを指定できる
送信アプリケーション
MQPutMessageOptionsオブジェクトのoptionsに、
MQC.MQPMO_LOGICAL_ORDERを指定
"
自動的にグループIDおよび順序番号がセットされる
pmo.options = MQC.MQPMO_LOGICAL_ORDER;
MQMessageオブジェクトのmessageFlagsに、
MQC.MQMF_MSG_IN_GROUPを指定しながら複数メッセージを送信
msg.messageFlags = MQC.MQMF_MSG_IN_GROUP;
"
グループ最後のメッセージには、MQC.MQMF_LAST_MSG_IN_GROUPを指定
msg.messageFlags = MQC.MQMF_LAST_MSG_IN_GROUP;
19
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BJ
グループ化(BaseJava)
受信アプリケーション
MQGetMessageOptionsオブジェクトのoptionsに、
MQC.MQGMO_LOGICAL_ORDERを指定
"
メッセージを論理順序で取得することができる
gmo.options = MQC.MQGMO_LOGICAL_ORDER;
"
MQGetMessageOptionsオブジェクトのoptionsに、MQC.MQGMO_ALL_MSGS_AVAILABLEを
指定するとグループ内の全てのメッセージが到着してからメッセージをGETできる
gmo.options = MQC.MQGMO_ALL_MSGS_AVAILABLE;
MQGetMessageOptionsオブジェクトのgroupStatusが
MQC.MQGS_LAST_MSG_IN_GROUPになるまでGETを繰り返す
"
GET後のgroupStatusには、以下のいずれかの値(char型)がセットされる
$
MQC.MQGS_NOT_IN_GROUP(グループ内のメッセージではない場合)
$
MQC.MQGS_MSG_IN_GROUP(グループ内のメッセージの場合)
$
MQC.MQGS_LAST_MSG_IN_GROUP(グループ内の最後のメッセージの場合)
20
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ
≪ノート≫
BJ
送信アプリケーション
3件のグループ・メッセージを送信する場合
(省略)
q = qMgr.accessQueue(qName, openOptions);
pmo = new MQPutMessageOptions();
pmo.options |= MQC.MQPMO_LOGICAL_ORDER;
msg.messageFlags = MQC.MQMF_MSG_IN_GROUP;
msg.write(アプリケーション・データ1);
q.put(msg, pmo);
msg.clearMessage();
msg.messageFlags = MQC.MQMF_MSG_IN_GROUP;
msg.write(アプリケーション・データ2);
q.put(msg, pmo);
msg.clearMessage();
msg.messageFlags = MQC.MQMF_LAST_MSG_IN_GROUP;
msg.write(アプリケーション・データ3);
q.put(msg, pmo);
msg.clearMessage();
(省略)
21
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ
≪ノート≫
BJ
受信アプリケーション
グループ内の最後のメッセージが到着してから、グループ・メッセージを順番に最後まで受
信する場合
(省略)
gmo.options |= MQC.MQGMO_LOGICAL_ORDER;
gmo.options |= MQC.MQGMO_ALL_MSGS_AVAILABLE;
do{
msg = new MQMessage();
q.get(msg, gmo);
:
(メッセージ処理)
:
}while(gmo.groupStatus != MQC.MQGS_LAST_MSG_IN_GROUP);
(省略)
22
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
グループ化(JMS)
送信アプリケーション
MQPMO_LOGICAL_ORDERの指定ができない
"
"
複数メッセージをMQのグループ・メッセージとして送信することはできる
ユーザーがグループIDや順序番号を設定する必要がある
JMSプロパティーのJMSXGroupIDに一意の文字列(String)を指定
"
"
MQMDのGroupIdに指定した値がセットされる
内部的に、MQMDのmessageFlagsにMQMF_MSG_IN_GROUPがセットされる
msg.setStringProperty(“JMSXGroupID”, “001”);
JMSプロパティーのJMSXGroupSeqに値(int)を指定しながら複数メッセージを送信
"
"
"
MQMDのMsgSeqNumberに指定した値がセットされる
グループの最初のメッセージは、この値が“1”でなければならない
後続メッセージには前のメッセージの値に“1”を加えた値を指定
msg.setIntProperty(“JMSXGroupSeq”, 1);
グループの最後のメッセージには、JMS_IBM_Last_Msg_In_Groupに
true(boolean値)を指定
"
内部的に、MQMDのmessageFlagsにMQMF_LAST_MSG_IN_GROUPがセットされる
msg.setBooleanProperty(“JMS_IBM_Last_Msg_In_Group”, true);
23
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
グループ化(JMS)
≪ノート≫
JMS
JMSXプロパティ
”JMSX”をPrefixに持つJMSプロパティはJMSの仕様だが、実装は義務付けられていな
い
"
JMSXGroupID、JMSXGroupSeqなど
JMSXプロパティを用いてメッセージのグループ化を行なっているJMSアプリケーションのポー
タビリティは保証されない
プロバイダーがサポートしているJMSXプロパティは、ConnectionMetaDataオブジェクトの
getJMSXPropertyNamesメソッドを使用して調べることが可能
MQConnectionMetaData meta = new MQConnectionMetaData();
java.util.Enumeration enu = meta.getJMSXPropertyNames();
while(enu.hasMoreElements()){
System.out.println("JMSXPropaty : " + enu.nextElement());
}
MQがサポートするJMSXプロパティ
"
"
"
"
"
JMSXUserID
JMSXAppID
JMSXDeliveryCount
JMSXGroupID
JMSXGroupSeq
24
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
グループ化(JMS)
末
受信アプリケーション
MQGMO_LOGICAL_ORDERおよびMQGMO_ALL_MSGS_AVAILABLEの指定が
できない
"
"
"
グループ内の全てのメッセージが到着したことをアプリケーションは確認する必要がある
⇒セレクターを使ってグループ最後のメッセージを指定して受信待ち
アプリケーションが受信メッセージの関連性と順序性を確認する必要がある
⇒JMSプロパティーのJMSXGroupID/JMSXGroupSeq/JMS_IBM_Last_Msg_In_Groupの
値から判別
JMSプロパティーをJMSセレクターを使用して検索することになるので、メッセージの滞留数が
パフォーマンスに影響(p49参照)
JMSでMQグループ・メッセージの受信アプリケーションを作成するのは困難
グループ化をMQの機能を利用しないで行なう場合
"
"
メッセージIDと相関IDでグループ化を行ない、制御メッセージを使用する方法(p7参照)
$
制御メッセージでグループ最後のメッセージが到着したことを確認できる
$
メッセージIDと相関IDをキーにセレクターで受信するので滞留数によるパフォーマンスの劣
化がない(p49参照)
送信側もJMSの場合は、メッセージIDを自由に使えないので、相関IDにグループIDを指定し、
順序番号は他のプロパティを使うことになる
25
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ
≪ノート≫
JMS
送信アプリケーション
グループIDを”001”として、3件のグループ・メッセージを送信する場合
(省略)
TextMessage msg1 = session.createTextMessage(ユーザ・データ1);
msg1.setStringProperty(“JMSXGroupID”, “001”);
msg1.setIntProperty(“JMSXGroupSeq”, 1);
sender.send(msg1);
TextMessage msg2 = session.createTextMessage(ユーザ・データ2);
msg2.setStringProperty(“JMSXGroupID”, “001”);
msg2.setIntProperty(“JMSXGroupSeq”, 2);
sender.send(msg2);
TextMessage msg3 = session.createTextMessage(ユーザ・データ3);
msg3.setStringProperty(“JMSXGroupID”, “001”);
msg3.setIntProperty(“JMSXGroupSeq”, 3);
msg3.setBooleanProperty(“JMS_IBM_Last_Msg_In_Group”, true);
sender.send(msg3);
(省略)
26
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BJ
セグメント化(BaseJava)
MQIと同様のオプションを指定できる
送信アプリケーション
MQMessageオブジェクトのmessageFlagsに、
MQC.MQMF_SEGMENTATION_ALLOWEDを指定
"
キュー・マネージャーが自動的にメッセージを分割
msg.messageFlags = MQC.MQMF_SEGMENTATION_ALLOWED;
受信アプリケーション
MQGetMessageOptionsオブジェクトのoptionsに、
MQC.MQGMO_COMPLETE_MSGを指定
"
"
キュー・マネージャーが自動的にセグメント化されたメッセージを組み立てて、
アプリケーションに渡す
セグメント化されていないメッセージを受信することも可能
gmo.options = MQC.MQGMO_COMPLETE_MSG;
27
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ
≪ノート≫
BJ
送信アプリケーション
10MBのデータをファイル(10MG.dat)から読み取り、セグメント化されることを許可して
メッセージを送信する場合
"
キュー・マネージャーもしくはキューの最大メッセージ長が10MBより小さい場合、
メッセージはセグメント化される
(省略)
msg.messageFlags = MQC.MQMF_SEGMENTATION_ALLOWED;
FileInputStream fis = new FileInputStream("10MB.dat");
byte b[] = new byte[10000000];
fis.read(b);
msg.write(b);
queue.put(msg, pmo);
(省略)
28
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ
≪ノート≫
BJ
受信アプリケーション
セグメント化されているメッセージを受信する場合
(省略)
gmo.options |= MQC.MQGMO_COMPLETE_MSG;
queue.get(msg, gmo);
(省略)
29
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(Base Java)
≪ノート≫
BJ
BaseJavaの一方向型送信アプリケーション
String QMgr_Name = "QM1";
String Q_Name = "Q1";
String Message = “This is a test message";
MQQueueManager
MQQueue
MQPutMessageOptions
MQMessage
int openOptions = 0;
qMgr = null;
queue = null;
pmo = null;
msg = null;
qMgr = new MQQueueManager(QMgr_Name);
openOptions |= MQC.MQOO_OUTPUT;
queue = qMgr.accessQueue(Q_Name, openOptions);
msg = new MQMessage();
msg.writeString(Message);
pmo = new MQPutMessageOptions();
queue.put(msg, pmo);
queue.close();
qMgr.disconnect();
30
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(Base Java)
≪ノート≫
BJ
BaseJavaの一方向型受信アプリケーション
String QMgr_Name = "QM1";
String Q_Name = "Q1";
MQQueueManager
MQQueue
MQGetMessageOptions
MQMessage
int openOptions = 0;
qMgr = null;
queue = null;
gmo = null;
msg = null;
qMgr = new MQQueueManager(QMgr_Name);
openOptions |= MQC.MQOO_INPUT_AS_Q_DEF;
queue = qMgr.accessQueue(Q_Name, openOptions);
msg = new MQMessage();
gmo = new MQGetMessageOptions();
gmo.options
|= MQC.MQGMO_FAIL_IF_QUIESCING;
gmo.options
|= MQC.MQGMO_WAIT;
gmo.waitInterval |= MQC.MQWI_UNLIMITED;
queue.get(msg, pmo);
queue.close();
qMgr.disconnect();
31
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(JMS)
≪ノート≫
JMS
JMSの一方向型送信アプリケーション
String QMgr_Name = "QM1";
String Q_Name = "Q1";
String Message = "This is a test message";
MQQueueConnectionFactory qcf
= null;
MQQueue
queue = null;
QueueConnection
qc
= null;
QueueSession
session = null;
QueueSender
sender = null;
TextMessage
msg
= null;
qcf = new MQQueueConnectionFactory();
qcf.setQueueManager(QMgr_Name);
queue = new MQQueue(Q_Name);
qc = qcf.createQueueConnection();
qc.start();
session = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
msg = session.createTextMessage(Message);
sender = session.createSender(requestQ);
sender.send(msg);
sender.close();
session.close();
qc.close();
qc = null;
32
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(JMS)
≪ノート≫
JMS
JMSの一方向型受信アプリケーション
String QMgr_Name = "QM1";
String Q_Name = "Q1";
MQQueueConnectionFactory qcf
= null;
MQQueue
queue = null;
QueueConnection
qc
= null;
QueueSession
session = null;
QueueReceiver
receiver = null;
TextMessage
msg
= null;
qcf = new MQQueueConnectionFactory();
qcf.setQueueManager(Qmgr_Name);
MQQueue requestQ = new MQQueue(Q_Name);
qc = qcf.createQueueConnection();
qc.start();
session = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
receiver = session.createReceiver(queue);
msg = receiver.receive(10000);
receiver.close();
session.close();
qc.close();
qc = null;
33
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
要求/応答型処理で使用される機能
要求/応答メッセージの紐付け
メッセージID/相関IDを使用して要求メッセージと応答メッセージを紐づける
相関ID指定の受信
応答先の指定/応答先への送信
クライアント側は、要求メッセージに応答先キュー名/キュー・マネージャー名を指定
サーバ側は、指定された応答先へ応答メッセージを送信
クライアント・アプリケーション
メッセージID=AAA
PUT
サーバ・アプリケーション
GET
要求メッセージ
メッセージID=AAA
要求キュー
ユニークなメッセージ
IDをセット
応答先をセット
GET wait
(相関ID=AAA)
要求メッセージの
メッセージID⇒相関ID
PUT
応答キュー
応答メッセージのメッ
セージIDが相関IDに
セットされている
メッセージを受信
34
応答メッセージ
相関ID=AAA
要求メッセージのメッセー
ジIDを応答メッセージの
相関IDにセットし、
応答先にPUT
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
要求/応答型処理で使用される機能
比較
Base Java
JMS
要求/応答メッ
セージの紐付け
◎(MQIと同等の設定が可能)
○
・メッセージIDを自由に設定できない
(キュー・マネージャーが自動的に設定する)
応答先の指定
/応答先への
送信
◎( MQIと同等の設定が可能)
◎
35
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
要求/応答メッセージの紐付け(BaseJava)
BJ
クライアント・アプリケーション
要求メッセージのメッセージIDにユニークな値を指定して送信
"
"
要求メッセージ(MQMessage)のmessageIdに任意のバイト配列をセット
MQMI_NONE(デフォルト値)もしくは、MQPMOのoptionsにMQPMO_NEW_MSG_IDを指定して
いる場合は、キュー・マネージャーによって自動的にユニークな値がセットされる
requestMsg.messageId = MQC.MQMI_NONE;
要求メッセージのメッセージID値が相関IDにセットされている応答メッセージを受信
"
"
GMOのmatchOptionsにMQMO_MATCH_CORREL_IDをセット
応答メッセージ(MQMessage)のcorrelationIdに要求メッセージのmessageIdをセット
gmo.matchOptions = MQC.MQMO_MATCH_CORREL_ID;
replyMsg.correlationId = requestMsg.messageId;
replyQ.get(replyMsg, gmo);
36
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
要求/応答メッセージの紐付け(BaseJava)
BJ
サーバ・アプリケーション
受信した要求メッセージのメッセージIDを応答メッセージの相関IDに設定し、送信
"
受信用MQMessageのmessageIdを、送信用MQMessageのcorrelationIdに設定
replyMsg.correlationId = requestMsg.messageId;
replyQ.put(replyMsg, pmo);
37
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
応答先の指定/応答先への送信(BaseJava)
BJ
クライアント・アプリケーション
要求メッセージに応答先キュー名を指定して送信
"
MQMessageのreplyToQueueNameに設定
requestMsg.replyToQueueName = “REP_Q”;
応答先キュー・マネージャー名は自動的に自分の接続しているキュー・マネージャー名が
セットされる
"
replyToQueueManagerNameに値を設定する必要はない
38
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
応答先の指定/応答先への送信(BaseJava)
BJ
サーバ・アプリケーション
受信した要求メッセージから応答先キュー名と応答先キュー・マネージャー名を取得し、
キューをオープン
"
受信用MQMessageのreplyToQueueNameとreplyToQueueManagerNameを
MQQueueManagerのaccessQueueメソッドの引き数に設定
オープンしたキューに対し、応答メッセージをPUT
String repQ = requestMsg.replyToQueueName;
String repQMgr = requestMsg.replyToQueueManagerName;
replyQ = qMgr.accessQueue(repQ, openOptions, repQMgr, “”, “” );
replyQ.put(replyMsg, pmo);
39
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(Base Java)
≪ノート≫
BJ
クライアント・アプリケーション
(省略)
String QMgr_Name = "QM1";
String requestQ_Name = "RQ1";
String replyQ_Name = "Q2";
String requestMsgText = “This is a request message";
MQQueueManager qMgr = new MQQueueManager(QMgr_Name);
int openOptions |= MQC.MQOO_OUTPUT;
MQQueue requestQ = qMgr.accessQueue(requestQ_Name, openOptions);
MQPutMessageOptions pmo = new MQPutMessageOptions();
MQMessage requestMsg = new MQMessage();
requestMsg.messageId = MQC.MQMI_NONE;
requestMsg.replyToQueueName = replyQ_Name;
requestMsg.writeString(requestMsgText);
requestQ.put(requestMsg, pmo);
:
:
40
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(Base Java)
≪ノート≫
BJ
クライアント・アプリケーション(続き)
:
:
int openOptions2 |= MQC.MQOO_INPUT_AS_Q_DEF;
MQQueue replyQ = qMgr.accessQueue(replyQ_Name, openOptions2);
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options |= MQC.MQGMO_FAIL_IF_QUIESCING;
gmo.options |= MQC.MQGMO_WAIT;
gmo.matchOptions |= MQC.MQMO_MATCH_CORREL_ID;
gmo.waitInterval |= MQC.MQWI_UNLIMITED;
MQMessage replyMsg = new MQMessage();
replyMsg.correlationId = requestMsg.messageId;
replyQ.get(replyMsg, gmo);
requestQ.close();
replyQ.close();
qMgr.disconnect();
(省略)
41
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(Base Java)
≪ノート≫
BJ
サーバ・アプリケーション
(省略)
String QMgr_Name = "QM2";
String requestQ_Name = "Q1";
MQQueueManager qMgr = new MQQueueManager(qMgrName);
int openOptions |= MQC.MQOO_INPUT_AS_Q_DEF;
MQQueue requestQ = qMgr.accessQueue(requestQ_Name, openOptions);
MQMessage requestMsg = new MQMessage();
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options
|= MQC.MQGMO_WAIT;
gmo.waitInterval |= MQC.MQWI_UNLIMITED;
gmo.options
|= MQC.MQGMO_FAIL_IF_QUIESCING;
gmo.options
|= MQC.MQGMO_SYNCPOINT;
requestQ.get(requestMsg, gmo);
:
:
42
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(Base Java)
≪ノート≫
BJ
サーバ・アプリケーション(続き)
:
:
String replyQMgr_Name = requestMsg.replyToQueueManagerName;
String replyQ_Name = requestMsg.replyToQueueName;
int openOptions2 |= MQC.MQOO_OUTPUT;
replyQ = qMgr.accessQueue(replyQ_Name, openOptions2, QMgr_Name, "", "");
replyMsg = new MQMessage();
replyMsg.writeString(“This is a reply messge");
replyMsg.correlationId = requestMsg.messageId;
MQPutMessageOptions pmo = new MQPutMessageOptions();
pmo.options |= MQC.MQPMO_SYNCPOINT;
replyQ.put(replyMsg, pmo);
qMgr.commit();
requestQ.close();
replyQ.close();
qMgr.disconnect();
(省略)
43
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
要求/応答メッセージの紐付け(JMS)
クライアント・アプリケーション
要求メッセージにメッセージIDの設定はせずに送信
"
"
"
JMSの場合、アプリケーションが任意のメッセージIDを設定することができない
キュー・マネージャーがPUT時にユニークなIDをセット
PUT後のメッセージ・オブジェクトからキュー・マネージャーのセットしたメッセージIDを取得
JMSのセレクター機能を使用し、相関IDを指定して受信
"
"
"
要求メッセージのメッセージIDが相関IDにセットされている応答メッセージを受信
MessageのgetJMSMessgeIDメソッドにて要求メッセージのメッセージIDを文字列として取得
セレクター(String)に文字列”JMSCorrelationID=‘要求メッセージのメッセージID’ ”を設定
(省略)
sender.send(requestMsg);
String msgId = requestMsg.getJMSMessageID();
String selector = "JMSCorrelationID='" + msgId + "'";
QueueReceiver receiver = session.createReceiver(replyQ, selector);
Message replyMsg = receiver.receive();
(省略)
44
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
要求/応答メッセージの紐付け(JMS)
サーバ・アプリケーション
要求メッセージのメッセージIDを取得し、応答メッセージの相関IDに設定
"
要求メッセージのgetJMSMessageIDメソッドで、メッセージIDを取得し、その値を
応答メッセージのsetJMSCorrelationIDメソッドで応答メッセージに設定
replyMsg.setJMSCorrelationID(requestMsg.getJMSMessageID());
45
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMSのセレクター機能
≪ノート≫
JMS
JMSヘッダ、JMSプロパティの属性の値を指定して受信する機能
セレクター(文字列)に「属性名=値」の形式で指定
"
String selector = “JMSCorrelationID=XXXXX”;
QueueReceiverに対しセレクターは1つのみ設定でき、設定後の変更は不可
"
QueueSessionのcreateQueueReceiverメソッドの第二引き数にセレクターをセット
該当メッセージを見つけるまでキュー内のメッセージをBrowseするので、滞留数がパフォー
マンスに影響
JMSMessageIDおよびJMSCorrelationIDを指定して受信する場合のみ、以下のように
セレクターを指定することでMQの検索機能を使うことができる
"
"
キュー内のメッセージをBrowseして検索しないので、パフォーマンスは滞留数にほとんど影響され
ない
指定方法
$
MQMDのMsgIdおよびCorrelIDにセットされた値の16進数表記にPrefixとして「ID:」を付け
てセレクターに指定
例えば、MQMDのMsgIDに
414D5120514D31202020202020202020D848DD3E20000401
と設定されているメッセージをセレクターで受信する場合、セレクターの設定は以下のようにする
selector = “JMSMessageID=‘ID:414D5120514D31202020202020202020D848DD3E20000401’ “
46
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMSMessageID
≪ノート≫
JMS
JMSメッセージのメッセージID(JMSMessageID)
アプリケーションが任意の値を設定することはできない
PUT時にキュー・マネージャーがMQMDのmessageIdに割り当てた値がJMSMessageIDに
セットされる
"
"
"
"
MQのメッセージIDは、24バイトのバイナリ・データ
JMSMessageIDは、文字列(String)
Prefixとして「ID:」が付く
例えば、キュー・マネージャーがMQMDのmessageIdに以下の値を割り当てた場合
414D5120514D31202020202020202020D848DD3E20000401 (バイナリ・データ)
PUT後のMessageオブジェクトのJMSMessageIDには、以下の値がセットされる
ID: 414D5120514D31202020202020202020D848DD3E20000401(文字列)
アプリケーションは、PUT後、getJMSMessageIDメソッドでメッセージIDを取得可能
"
"
メソッドの戻り値には、「ID:」が付加された文字列が返る
セレクターにセットする場合、戻り値をそのまま設定すると、MQの検索機能が使える
47
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMSCorrelationID
≪ノート≫
JMS
JMSメッセージの相関ID(JMSCorrelationID)
アプリケーションから任意の値を設定可能(設定方法は以下の3通り)
1.
2.
3.
文字列を設定
$
相手がJMSアプリケーションであるときに使用
$
message.setJMSCorrelationID("12345");
$
MQMDのCorrelIdとMQRFH2ヘッダのCidにセットされる
16進数表記の文字列(Prefixとして「ID:」を付加)を設定
$
受信メッセージのメッセージIDを送信メッセージの相関IDに設定する場合に使用
$
replyMsg.setJMSCorrelationID(requestMsg.getJMSMessageID());
$
MQMDのCorrelIdにのみセットされる
バイト配列を設定
$
message.setJMSCorrelationIDAsBytes(b);
$
MQMDのCorrelIdにのみセットされる
値の取得は以下のメソッドを使用
"
"
getJMSCorrelationID()
$
MQRFH2のCidに値がセットされている場合は、その文字列が返る
$
MQMDのCorrelIdにのみ値がセットされている場合は、バイナリ・データの16進数表記に
「ID:」が付加された文字列が返る
getJMSCorrelationIDAsBytes()
$
MQMDのCorrelIdにセットされているバイナリ・データのバイト配列が返る
48
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMSメッセージとMQメッセージ
≪ノート≫
JMS
JMSメッセージとMQメッセージの関係(メッセージID/相関ID)
アプリケーション
Message msg = new Message();
キュー・マネージャー
PUT前の
PUT前のJMS
前のJMSメッセージ
JMSメッセージ
JMSMessageID
msg.setJMSCorrelationID("12345");
MQメッセージ
メッセージ
キュー・マネージャー MQ
が生成
MQMD.MessageID
JMSCorrelationID
"12345"
414534A32…….
sender.send(msg)
MQMD.CorrelID
3132333435…….
PUT後の
PUT後のJMS
後のJMSメッセージ
JMSメッセージ
JMSMessageID
MQRFH2.CrlID
"ID:414534A32....."
"12345"
JMSCorrelationID
msgID = msg.getJMSMessageID();
"12345"
correlID = msg.getJMSCorrelationID();
49
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
応答先の指定/応答先への送信(JMS)
JMS
クライアント・アプリケーション
応答先が設定されたQueueオブジェクトをJNDIから取得
InitialContext ic = new InitialContext();
Queue replyQ = (Queue)ic.lookup("java:comp/env/jms/ReplyQ");
"
JNDIを使用しない場合は、MQQueueオブジェクトを作成し、応答キュー名とキューマネージャー
名を設定
MQQueue replyQ = new MQQueue(replyQ_Name);
replyQ.setBaseQueueManagerName(replyQMgr_Name);
Queueオブジェクトを要求メッセージに設定
"
MessageオブジェクトのsetJMSReplyToメソッドで設定
requestMsg.setJMSReplyTo(replyQ);
50
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
応答先の指定/応答先への送信(JMS)
JMS
サーバ・アプリケーション
要求メッセージからgetJMSReplyToメソッドでQueueオブジェクトを取得し、
そのオブジェクトをもとにQueueSenderを作成
"
オブジェクトには、クライアント側でセットされた応答キュー名とキュー・マネージャー名が設定され
ている
sender = session.createSender((Queue)requestMsg.getJMSReplyTo());
51
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(JMS)
≪ノート≫
JMS
クライアント・アプリケーション
(省略)
String requestMsgText = “This is a request message";
String QMgr_Name = "QM1";
String requestQ_Name = “Q1”;
String replyQ_Name = “Q2”;
MQQueueConnectionFactory qcf = new MQQueueConnectionFactory();
qcf.setQueueManager(QMgr_Name);
MQQueue requestQ = new MQQueue(requestQ_Name);
MQQueue replyQ = new MQQueue(replyQ_Name);
QueueConnection qc = qcf.createQueueConnection();
qc.start();
QueueSession session = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueSender sender = session.createSender(requestQ);
TextMessage requestMsg = session.createTextMessage(requestMsgText);
Destination destination = session.createQueue("queue://QM1/Q2");
requestMsg.setJMSReplyTo(destination);
sender.send(requestMsg);
:
:
52
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(JMS)
≪ノート≫
JMS
クライアント・アプリケーション(続き)
:
:
String msgId = requestMsg.getJMSMessageID();
String selector = "JMSCorrelationID='" + msgId + "'";
QueueReceiver receiver = session.createReceiver(replyQ, selector);
Message replyMsg = receiver.receive();
getMsg = ((TextMessage)inMsg).getText();
sender.close();
receiver.close();
session.close();
qc.close();
qc = null;
(省略)
53
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(JMS)
≪ノート≫
JMS
サーバ・アプリケーション
(省略)
String putMsg = null;
String getMsg = null;
String QMgr_Name = "QM1";
String requestQ_Name = "Q1";
MQQueueConnectionFactory qcf = new MQQueueConnectionFactory();
qcf.setQueueManager(Qmgr_Name);
MQQueue requestQ = new MQQueue(requestQ_Name);
QueueConnection qc = qcf.createQueueConnection();
qc.start();
QueueSession session = qc.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
QueueReceiver receiver = session.createReceiver(requestQ);
Message requestMsg = receiver.receive(10000);
:
:
54
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(JMS)
≪ノート≫
JMS
サーバ・アプリケーション(続き)
:
:
QueueSender sender = session.createSender((Queue)requestMsg.getJMSReplyTo());
TextMessage replyMsg = session.createTextMessage(“This is a reply message");
replyMsg.setJMSCorrelationID(requestMsg.getJMSMessageID());
sender.send(outMsg);
Session.commit();
sender.close();
receiver.close();
session.close();
qc.close();
qc = null;
(省略)
55
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
クライアント接続
MQIでクライアント接続を行なう場合
クライアント接続のための設定が必要
"
"
キュー・マネージャー側にサーバ接続チャネルを用意
クライアント側にクライアント接続チャネルを用意
$
MQSERVER環境変数
$
チャネル定義ファイル
コードはローカル接続のときと同じでよい
"
クライアント接続用ライブラリー(MQICライブラリー)のリンクが必要
$
ローカル接続のときは、MQIライブラリーをリンク
56
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
MQ Javaでのクライアント接続
MQ Javaクライアントと通常のMQクライアントの違い
TCP/IPのみサポート
クライアント側の設定は全てJavaオブジェクトに行なう
"
"
チャネル定義ファイルは使用できない
$
自動再接続の機能は使用できない
環境変数は使用できない
$
MQSERVER、MQCCSID、MQCHLLIB、MQCHLTAB、、、
比較
Base Java
クライアント接続
JMS
○
・チャネル定義ファイルは使用できない
・環境変数は使用できない
57
○
・チャネル定義ファイルは使用できない
・環境変数は使用できない
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
MQ Javaでのクライアント接続(BaseJava)
BJ
BaseJavaでクライアント接続を行なう場合
MQEnvironmentの以下の変数に設定
"
"
"
"
"
hostname(必須)
$
サーバ・マシンのホスト名(IPアドレス)
channel(必須)
$
チャネル名(サーバ接続チャネルと同一名)
port
$
ポート番号(デフォルトは、1414)
userID
$
ユーザーID
$
ここで、指定したIDでMQにアクセスする
CCSID
$
デフォルトでは、819がセットされるのでDBCSのCCSIDを持つQMGRと接続できない
$
明示的にDBCSのCCSID(932、943、、、)を設定する必要がある
エラーはMQExceptionで指定したログに出力される
"
デフォルトは、コンソール
58
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(BaseJava)
≪ノート≫
BJ
BaseJavaでクライアント接続を行なう場合
(省略)
MQEnvironment.hostname = "9.170.X.XXX";
MQEnvironment.channel = "SYSTEM.DEF.SVRCON";
MQEnvironment.port = 1414;
MQEnvironment.CCSID = 932;
qMgr = new MQQueueManager(qMgrName)
(省略)
59
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
MQ Javaでのクライアント接続(JMS)
JMS
JMSでクライアント接続を行なう場合
QueueConnectionFactoryの以下の属性に設定(WASコンソール、JMSAdminを使用)
"
"
"
"
"
TRANSPORT(必須)
$
”CLIENT”を指定
HOSTNAME(必須)
$
サーバ・マシンのホスト名(IPアドレス)
CHANNEL(必須)
$
チャネル名(サーバ接続チャネルと同一名)
PORT
$
ポート番号(デフォルトは、1414)
CCSID
$
デフォルトでは、819がセットされるのでDBCSのCCSIDを持つQMGRと接続できない
$
明示的にDBCSのCCSID(932、943、、、)を設定する必要がある
コード内で設定する場合は、QueueConnectionFactoryの上記属性に対応したメソッド
を使用
"
TRANSPORT属性に指定する値は、"JMSC.MQJMS_TP_CLIENT_MQ_TCPIP"を指定
60
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(JMS)
≪ノート≫
JMS
JMSでクライアント接続を行なう場合
コード内で設定する場合
(省略)
qcf.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
qcf.setHostName("9.170.X.XXX");
qcf.setChannel("SYSTEM.DEF.SVRCONN");
qcf.setPort(1414);
qcf.setCCSID(932);
QueueConnection qc = qcf.createQueueConnection();
(省略)
61
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
アクセス・ユーザー
≪ノート≫
MQ Javaでクライアント接続するときのアクセス・ユーザーID
優先順位
設定
1
サーバー接続チャネル(SVRCONN)のMCAUSER
MCAUSER属性に設定したユーザーID
MCAUSER
2
・BaseJavaの場合、プログラム内のMQEnvironmentオブジェクトのuserID
userID属性に設定したユーザーID
userID
(password属性の設定は無効)
・JMSの場合、createQueueConnection("username","password")メソッドで指定したユーザーID
(passwordの設定は無効)
3
チャネルの起動ユーザー
i) inetdを使用する場合は、inetd.confに指定した起動ユーザーID
inetd.confの例) QM1 stream tcp nowait mqm /usr/lpp/mqm/bin/amqcrsta amqcrsta -m QM1
ii) リスナーを使用する場合は、リスナー起動ユーザー
62
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
Browse機能
MQのBrowse機能
キュー内のメッセージを削除せずに参照のみ行なう
"
メッセージの中身を確認してからGETするかしないかを判断できる
Browseでメッセージを待つことができる
"
MQGMO_WAITを使用
ロックをかけて他のアプリケーションがBrowseしたメッセージをGETできなくすることができる
"
MQGMO_LOCKを使用
カーサーが指しているメッセージをGETすることができる
"
MQGMO_MSG_UNDER_CURSERを使用
受信アプリケーション
カーサー
MQOPEN MQOO_BROWSE
MQGET (MQGMO_BROWSE_FIRST)
Message 1
MQGET (MQGMO_BROWSE_NEXT)
Message 2
MQGET (MQGMO_BROWSE_NEXT)
Message 3
MQGET (MQGMO_MSG_UNDER_CURSER)
Message 4
63
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
Browse機能
比較
Base Java
Browse機能
JMS
◎(MQIと同等の設定が可能)
・GET待ちが可能
・ロックをかけることができる
・カーサーの指すメッセージをGETできる
64
△
・GET待ちができない
・ロックがかけられない
・カーサーを使用したメッセージのGETができない
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BJ
Browse機能(Base Java)
MQIと同じオプションを指定できる
MQQueueオブジェクト作成時のaccessQueueメソッドの第二引数(オープン・オプション)
にMQC.MQOO_BROWSEをセット
openOptions = MQC.MQOO_BROWSE;
queue = qMgr.accessQueue(qName, openOptions);
最初のGET時には、MQGetMessageOptionsのoptionsに
MQC.MQGMO_BROWSE_FIRSTを指定してGET
"
カーサーがキュー内の最初のメッセージにセットされる
gmo.options = MQC.MQGMO_BROWSE_FIRST;
2回目以降のGET時には、 MQC.MQGMO_BROWSE_NEXTを指定してGET
"
カーサーがキュー内の次のメッセージに移動する
gmo.options = MQC.MQGMO_BROWSE_NEXT;
BrowseしたメッセージをGET(キューから削除)する場合は、
MQC.MQGMO_MSG_UNDER_CURSORを指定してGET
"
カーサーが現在、指しているメッセージをGET
gmo.options = MQC.MQGMO_MSG_UNDER_CURSOR;
65
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ(BaseJava)
≪ノート≫
BJ
BaseJavaでBrowseを行なう場合
(省略)
openOptions |= MQC.MQOO_INPUT_AS_Q_DEF;
openOptions |= MQC.MQOO_BROWSE;
queue = qMgr.accessQueue(qName, openOptions);
for( int s = 0; s < browseCount; s++){
msg = new MQMessage();
gmo = new MQGetMessageOptions();
if(s == 0){
gmo.options
|= MQC.MQGMO_BROWSE_FIRST;
}else{
gmo.options
|= MQC.MQGMO_BROWSE_NEXT;
}
q.get(msg, gmo);
}
(省略)
66
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
Browse機能(JMS)
JMSのBrowse機能
QueueSessionのcreateBrowserメソッドでQueueBrowserを作成
QueueBrowser browser = (QueueBrowser)session.createBrowser(queue);
QueueBrowserのgetEnumerationメソッドでjava.util.Enumerationオブジェクトを取得
"
内部的には、このタイミングでMQOO_BROWSEオプション付きでMQOPENだけを行なう
java.util.Enumeration enu = (java.util.Enumeration)browser.getEnumeration();
EnumerationオブジェクトのnextElementメソッドでメッセージを参照
"
内部的には、MQGMO_BROWSE_FIRST/MQGMO_BROWSE_NEXTオプション付きで
MQGET
Message message = (Message)enu.nextElement();
EnumerationオブジェクトのhasMoreElementsメソッドの戻り値で次のメッセージがあるか
を判別
"
"
true:メッセージあり
false:メッセージなし
enu.hasMoreElements();
67
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
Browse機能(JMS)
考慮点
キューにメッセージがないときに、nextElementメソッドを発行するとエラーが発生する
"
事前に、hasMoreElementsメソッドでメッセージがあることを確認すること
Browse待ちができないので、アプリケーションからポーリングを行なう場合は、
定期的にhasMoreElementsメソッドでメッセージがあるか確認する
(省略)
for(int i = 0; i < 100; i++){
if(enu.hasMoreElements()){
Message inMsg = (Message)enu.nextElement();
System.out.println("message : " + ((TextMessage)inMsg).getText());
}else{
System.out.println("no message");
Thread.sleep(1000);
}
}
(省略)
68
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ
≪ノート≫
JMS
JMSでBrowseを行なう場合
(省略)
QueueSession session = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueBrowser browser = (QueueBrowser)session.createBrowser(queue);
java.util.Enumeration enu = (java.util.Enumeration)browser.getEnumeration();
while(enu.hasMoreElements()){
Message inMsg = (Message)enu.nextElement();
if(inMsg instanceof TextMessage){
getMsg = ((TextMessage)inMsg).getText();
System.out.println(“message : " + getMsg);
}else{
System.out.println(“message : not text message");
}
}
(省略)
69
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
メッセージの永続性
ノン・パーシステント・メッセージ
キュー・マネージャーの再起動後、メッセージは消失
ログへの書き込みない
パーシステント・メッセージと比べ、パフォーマンスはよい
パーシステント・メッセージ
キュー・マネージャーの再起動を跨って、メッセージを保持
ログへの書き込みあり
ノン・パーシステント・メッセージと比べ、パフォーマンスは劣る
比較
Base Java
メッセージの永続性
JMS
◎(MQIと同等の設定が可能)
◎
・デフォルト値がBaseJavaと異なる
70
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BJ
メッセージの永続性(BaseJava)
MQIと同様のオプションを指定できる
MQMessageオブジェクトのpersistenceに以下の値を設定
"
"
"
MQC.MQPER_PERSISTENCE_AS_Q_DEF:宛先キューの設定に依存(デフォルト)
MQC.MQPER_NOT_PERSISTENT:ノン・パーシステント・メッセージ
MQC.MQPER_PERSISTENT:パーシステント・メッセージ
requestMsg.persistence = MQC.MQPER_PERSISTENT;
71
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
メッセージの永続性(JMS)
以下の2つのオブジェクトに設定可能
Queueオブジェクト
"
"
"
JNDIネームスペースに登録している場合は、管理ツールJMSAdminもしくはWASの管理コンソー
ルから設定
アプリケーション内で作成している場合は、setPersistenceメソッドで設定
以下のいづれかの値を設定
$
JMSC.MQJMS_PER_APP:QueueSenderの設定に依存(デフォルト値)
$
JMSC.MQJMS_PER_QDEF:キューの設定に依存
$
JMSC.MQJMS_PER_PER:パーシステント・メッセージ
$
JMSC.MQJMS_PER_NON:ノン・パーシステント・メッセージ
QueueSenderオブジェクト
"
setDeliveryModeメソッドで以下のいづれかの値を指定
$
DeliveryMode.PERSISTENT(デフォルト値)
$
DeliveryMode.NON_PERSISTENT
sender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
"
sendメソッドの引き数に指定することも可能
$
send(Message message, int deliveryMode, int priority, long timeToLive)
72
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
メッセージの永続性(JMS)
JMS
Queueオブジェクトの設定が優先される
"
"
QueueSenderオブジェクト作成後のMQQueueオブジェクトの設定変更も有効
MQQueueオブジェクトがMQJMS_PER_APPの場合にのみ、QueueSenderでの設定が有効
73
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コード変換
MQのコード変換機能
メッセージのユーザ・データ部分を指定したCCSIDのコードに変換することができる
データが全て文字データの場合(MQFMT_STRING)のみ使用可能
"
バイナリ・データが混在する場合は、ユーザExitを組み込むことも可能
変換は、以下の2ヶ所で可能(いづれかを選択)
"
"
アプリケーションが受信するとき(通常の方法)
$
MQGMO_CONVERTを指定してGET
$
GET時にMQMDのCodedCharSetIdに指定したCCSIDのコードに変換される
送信チャネルがメッセージを送信するとき
$
送信チャネルのCONVERT属性をYESに設定
$
接続先のキュー・マネージャーのCCSID属性に設定されたコードに変換される
BaseJavaは、使用可能
JMSは使用不可
キュー・マネージャー
受信アプリケーション
MQMD.Format=
MQFMT_STRING
MQMD.CCSID=5026
5026 ⇒ 943
74
gmo.options
= MQGMO_CONVERT
msg.CodedCharSetId=943
MQGET
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
Java環境でのコード変換
Java環境でのコード変換
Java環境では、文字データ(String)はUnicodeで扱われる
"
アプリケーション内の文字データとMQメッセージ内の文字データとの間で、
必ず、to/from Unicode変換が行なわれる
MQのコード変換機能を使用する必要はない
"
使用すると2度コード変換が行なわれることになる
BaseJava、JMSとも、文字データをUnicodeから指定したCCSIDに変換してメッセージに
セットするメソッドを提供
"
受信後の文字データ取得用のメソッドでは、MQMDのCodedCharSetIdに設定されている
CCSIDからUnicodeに変換される
Javaアプリケーション
キュー・マネージャー
Javaアプリケーション
文字データ
MQのメソッドによる
コード変換
”あいうえお”(Unicode)
BaseJava/JMSメッセージ
PUT
”あいうえお”(CCSID:943)
MQメッセージ
”あいうえお”(CCSID:943)
BaseJava/JMSメッセージ
”あいうえお”(CCSID:943)
文字データ
”あいうえお”(Unicode)
75
GET
MQのメソッドによる
コード変換
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コード変換
比較
Base Java
MQのコード変換
機能(※1)
メソッドによる
Unicode変換
JMS
◎(MQIと同等の設定が可能)
×
・CONVERTオプションの指定ができない
◎
◎
※1 Java環境では、MQのコード変換機能は使用しなくてよい
76
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BJ
コード変換(BaseJava)
メッセージ作成時のコード変換(Unicode ⇒ 指定CCISD)
MQMessageオブジェクトのcharacterSetに変換先のCCSIDを設定し、
writeStringメソッドで文字データをメッセージ・バッファーにセット
"
"
注意
"
文字データは、Unicodeから指定したCCSIDにコード変換される
設定できるCCSID
$
マニュアル「Using Java」のChapter9. The WebSphere MQ base Java classes and
interfacesのMQMessageクラスの記述を参照
$
マニュアルには943は出ていないが使用可能
デフォルト値が819となってしまうので、必ず明示的にCCSIDを設定すること
msg = new MQMessage();
msg.characterSet = 943;
msg.writeString("あいうえお");
writeUTFメソッドを使用するとcharacterSetの値に関係なくUTF(CCSID:1208)に変換
される
"
"
"
先頭に2バイトのLengthを付加したUTF Stringを書き込む
writeStringでCCSID 1208を使用した場合はLengthは付加されない
writeUTFで作成されたメッセージはreadUTFで取得しないと例外が発生する
writeCharsメソッドを使用するとCCSIDの設定に関係なくUnicode(CCSID:1200)に変
換される
77
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コード変換(JMS)
JMS
メッセージ作成時のコード変換(Unicode ⇒ 指定CCSID)
TextMessageオブジェクトのJMS_IBM_Character_SetかQueueオブジェクトのsetCCSID
メソッドで変換先のCCSIDを指定し、setTextメソッドで文字データを設定
"
"
"
"
文字データは、Unicodeから指定したCCSIDにコード変換される
TextMessageオブジェクトの設定が優先される
指定可能なCCSIDは、BaseJavaと同じ
どちらにも設定しないと、デフォルトで、1208(UTF-8)がセットされる
message.setStringProperty("JMS_IBM_Character_Set", "943");
message.setText("テストメッセージ");
"
"
"
MQMDのCodedCharSetIdの値は、送信メッセージにMQRFH2が付加されるかどうかで変わる
MQRFH2ヘッダ付きメッセージの場合
$
MQMDのCodedCharSetIdは819で固定、MQRFH2のCodedCharSetIdに指定した
CCISDがセットされる
MQRFH2ヘッダなしメッセージの場合
$
MQMDのCodedCharSetIdに指定したCCSIDがセットされる
MapMessageの場合、setStringメソッドでコード変換される
StreamMessageの場合、writeStringメソッドでコード変換される
78
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コード変換
注意点
BaseJavaやJMSでCCSIDに指定した値と、実際の変換時に使われる変換テーブルの
紐付けは非公開
"
"
例えば、MQMessageオブジェクトのcharacterSetに943を指定した場合、変換にCp943が使用
されるのか、Cp943Cが使用されるのかは公開されていない
幕張のテスト結果では、、
charaterSetの値
使用される変換テーブル
932
SJIS
943
Cp943
930
Cp930
939
Cp939
注意すべきは、943を指定したとき
"
"
Windows上のブラウザからJavaアプリケーションに文字データが入ってきたときは、WASのデフォル
ト設定で通常「Cp943C」の変換テーブルが使用される
そのデータをMQのメッセージとして送信する場合、943を指定すると「Cp943」が使われ、Java環
境へのインとアウトで異なる変換テーブルを使用することになる
対策および詳細は、ISE NotesDB「ザ・技術」から
「OLTP/MQ Technical Updates 2003 #1」ワークショップ
の資料「WAS-MQ連携文字コード」を参照
文字化け
79
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
同期点処理
メッセージのPUT/GET処理に対し同期を取る
1つのキュー・マネージャーへの接続(コネクション・ハンドル)の範囲でUOWを設定
メッセージ処理をUOWに入れるかどうかはPUT/GET時に指定
"
MQxMO_SYNCPOINTを設定
MQCMIT/MQBACKで同期点調整
MQPUT
(MQPMO_SYNCPOINT)
MQGET
(MQGMO_SYNCPOINT)
MQPUT
(MQPMO_SYNCPOINT)
MQCMIT
MQPUT
(MQPMO_SYNCPOINT)
MQCMIT
MQBACK
比較
Base Java
同期点処理
◎(MQIと同等の設定が可能)
JMS
○
・PUT/GET単位でUOWに入れるかどうか指定できない
・ MQGMO_SYNCPOINT_IF_PERSISTENTの指定不可
80
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BJ
同期点処理(BaseJava)
MQIと同様のオプションを指定できる
メッセージのPUT/GET時に同期点処理を行なうかどうかを指定
PUT/GET単位で指定ができる
PUTの場合
"
MQPutMessageOptionsオブジェクトのoptionsに以下のいずれかの値を設定
$
MQC.MQPMO_NO_SYNCPOINT:同期点処理なし
$
MQC.MQPMO_SYNCPOINT:同期点処理あり
pmo.options = MQC.MQPMO_SYNCPOINT;
GETの場合
"
MQGetMessageOptionsオブジェクトのoptionsに以下のいずれかの値を設定
$
MQC.MQGMO_NO_SYNCPOINT:同期点処理なし
$
MQC.MQGMO_SYNCPOINT:同期点処理あり
$
MQC.MQGMO_SYNCPOINT_IF_PERSISTENT
:パーシステントメッセージの場合は同期点処理ありで受信
gmo.options = MQC.MQGMO_SYNCPOINT;
81
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
同期点処理(BaseJava)
BJ
同期点調整
コミット
"
MQQueueManagerオブジェクトのcommitメソッドを使用
qMgr.commit();
バックアウト
"
MQQueueManagerオブジェクトのbackoutメソッドを使用
qMgr.backout();
82
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ
≪ノート≫
BJ
BaseJavaでの同期点処理
(省略)
MQPutMessageOptions pmo = new MQPutMessageOptions();
pmo.options = MQC.MQPMO_SYNCPOINT;
requestQ.put(requestMsg, pmo);
:
qMgr.commit();
(省略)
83
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
同期点処理(JMS)
QueueSessionに対し同期点処理を行なうかどうかを指定
1メッセージ単位での同期点の指定ができない
"
"
同期点を指定したQueueSessionを使用するPUT/GET処理は全て1つのUOWに入る
MQGMO_SYNCPOINT_IF_PERSISTENTの指定もできない
QueueConnectionのcreateQueueSessionメソッドの第一引数にBoolean値を指定
"
"
true:同期点処理を行なう
false:同期点処理を行なわない
session = qc.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
同期点調整
コミット
"
QueueSessionのcommitメソッドを使用
session.commit();
ロールバック
"
QueueSessionのrollbackメソッドを使用
session.rollback();
84
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ
≪ノート≫
JMS
JMSでの同期点処理
(省略)
QueueSession session = qc.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
QueueReceiver receiver = session.createReceiver(queue);
Message inMsg = receiver.receive();
:
session.commit();
(省略)
85
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
同期点処理(JMS)
同期点付きのPUT/GET処理の間に同期点なしの処理を行なう場合は、
QueueSessionオブジェクトを分ける必要がある
同期点付きのQueueSessionと同期点なしのQueueSessionを作成し、処理に応じ使い
分ける
(省略)
QueueSession qs = qc.createQueueSession(true, Session.AUTO_ACKNOWLEDGE); //同期点付き
QueueReceiver receiver = qs.createReceiver(queue1);
QueueSender sender = qs.createSender(queue3);
QueueSession qsNoSync = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); //同期点なし
QueueSender senderNoSync = qsNoSync.createSender(queue2);
Message getMsg = receiver.receiver(); // ①同期点付きのGET
senderNoSync.send(getMsg); // ②同期点なしのPUT
sender.send(getMsg); // ③同期点付きのPUT
session.commit();
(省略)
上の例の場合、③のPUTが失敗すると①でGETしたメッセージはキューにバックアウトされ
るが②の処理は正常に処理される
86
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
Message Acknowledge
JMSの仕様で規定しているメッセージ受信処理に対する同期点処理
受信したメッセージに対しアプリケーションがAcknowledgeすると、メッセージはキューから
削除される
QueueSession作成時、トランザクション属性(createQueueSessionメソッドの第一引
数)をfalseにして、第二引数に以下の3つのオプションのいづれかを指定
"
"
"
Session.AUTO_ACKNOWLEDGE
$
アプリケーションがGETした時点で、自動的にAcknowledgeされる
Session.CLIENT_ACKNOWLEDGE
$
アプリケーションが明示的にAcknowledgeする必要がある
$
受信したMessageオブジェクトのacknowledgeメソッドを発行することでAcknowledgeする
$
acknowledgeメソッドを発行したタイミングでメッセージはキューから削除される
$
Acknowledgeせずに複数のメッセージを受信している場合、1つのメッセージに対し
acknowledgeメソッドを発行するとすべてのメッセージがAcknowledgeされる
Session.DUPS_OK_ACKNOWLEDGE
$
2重受信を防ぐためのQueueSessionの処理を軽減させる
$
障害時、2重受信の可能性がある
トランザクション属性をtrueとしている場合は、上記オプションに関係なく、コミットした時点
で自動的にAcknowledgeされる
同じQueueSessionで行なわれるPUT処理は、受信メッセージのAcknowledgeに関係な
く、処理される
87
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
Message Acknowledge
CLIENT_ACKNOWLEDGEの場合のコーディング・イメージ
QueueSession session = qc.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
QueueReceiver receiver = session.createReceiver(queue);
Message inMsg = receiver.receive();
:
inMsg.acknowledge();
MQでは、内部的にMQの同期点処理機能で実装
AUTO_ACKNOWLEDGE/DUPS_OK_AKNOWLEDGEで受信するときは、内部的には
MQGMO_NO_SYNCPOINTオプションでMQGETを発行
CLIENT_ACKNOWLEDGEのときは、MQGMO_SYNCPOINTオプションでMQGETを発行
"
acknowledgeメソッド発行時に、内部的にMQCMITを発行
88
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
グローバル・トランザクションへの参加
外部リソース(DB2、Oracleなど)の更新処理とPUT/GETを同一UOWに入れる
2フェーズ・コミットを実施
BaseJavaとJMSとでトランザクション・コーディネーターとなる製品が異なる
BaseJavaの場合
"
"
WebSphere MQ がコーディネーター
MQのデータベース・コーディネーション機能を利用可能
JMSの場合
"
"
WebSphere Application Server がコーディネーター
MQのデータベース・コーディネーション機能は利用不可
$
MQはコーディネーターになれない
比較
Base Java
グローバル・
トランザクション
JMS
◎(MQIと同等の設定が可能)
・MQがコーディネーター
◎
・WASがコーディネーター
89
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
グローバル・トランザクションへの参加(BaseJava)
BJ
BaseJavaでグローバル・トランザクションに参加する場合
※コーディング上の注意点のみ記述
設定、構成面での必要事項は、「システム構成」セッションの資料を参考
MQQueueManagerオブジェクトのメソッドを使用してデータベースとのコネクションを取得
"
"
"
"
getJDBCConnection(XADataSource xads, String dbuserId, String dbuserPW)
戻り値は、java.sql.Connection
XADataSourceオブジェクトの取得方法は、各データベース製品に依存
DB2の場合
COM.ibm.db2.jdbc.DB2XADataSource xads = new DB2XADataSource();
xads.setDatabaseName("XADB");
Connection dbcon = qmgr.getJDBCConnection(xads, "DB2userID", "DB2userPW");
トランザクションの開始/終了は、MQQueueManagerオブジェクトのメソッドを使用
"
"
"
開始:beginメソッド
コミット:commitメソッド
バックアウト:backoutメソッド
qMgr.begin();
:
qMgr.commit();
90
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コーディング・イメージ
≪ノート≫
BJ
BaseJavaでグローバル・トランザクションに参加する場合
//省略
MQQueueManager qmgr = new MQQueueManager("QMgrName");
COM.ibm.db2.jdbc.DB2XADataSource xads = new DB2XADataSource();
xads.setDatabaseName("XADB");
Connection dbcon = qmgr.getJDBCConnection(xads, "DB2userID", "DB2userPW");
qmgr.begin();
MQQueue q = qmgr.accessQueue(qName, openOptions);
MQMessage msg = new MQMessage();
msg.writeUTF("メッセージ");
q.put(msg, putMsgOption);
Statement stmt = dbcon.createStatement();
stmt.executeUpdate("<SQL文>'");
qmgr.commit();
//省略
91
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
グローバル・トランザクションへの参加(JMS)
JMS
JMSでグローバル・トランザクションに参加する場合
※コーディング上の注意点のみ記述
設定、構成面での必要事項は、「システム構成」セッションの資料を参考
コンテナー管理トランザクションの場合(EJB、MDB)
"
"
"
コンテナーがトランザクションを管理
JNDIからXA用のQueueConnectionFactoryを取得
$
このQCFを使用したPUT/GETは自動的にコンテナー管理のグローバル・トランザクション
に参加
アプリケーションは、トランザクションを意識したコーディングをする必要はない
$
JNDIから取得するQCFは通常通りQueueConnectionFactory型にキャスト
$
JMSのオブジェクト作成時やPUT/GET時も特別な指定、コーディングは必要ない
$
トランザクションのBegin/Commit/Backoutの指示も必要なし
92
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
グローバル・トランザクションへの参加(JMS)
JMS
JMSでグローバル・トランザクションに参加する場合(続き)
ビーン管理トランザクションの場合(Servlet、EJB、MDB)
"
"
JNDIからXA用のQueueConnectionFactoryを取得
$
JMSWrapXAQueueConnectionFactory
$
このQCFを使用したPUT/GETはグローバル・トランザクションに参加できる
トランザクションの開始/終了は、アプリケーションが指示
$
javax.jta.UserTransactionのメソッドを使用(オブジェクトはJNDIから取得)
$
開始:beginメソッド
$
コミット:commitメソッド
$
バックアウト:rollbackメソッド
InitialContext ic = new InitialContext();
UserTransaction ut = (UserTransaction)ic.lookup("java:comp/UserTransaction");
ut.begin();
:
トランザクション処理
:
ut.commit();
注意:アプリケーション・クライアント(Javaアプリケーション)はグローバル・トランザクションに参加できない
93
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
コーディング・イメージ
JMSでグローバル・トランザクションに参加する場合
(省略)
InitialContext ic = new InitialContext();
UserTransaction ut = (UserTransaction)ic.lookup("java:comp/UserTransaction");
DataSource ds = (DataSource)ic.lookup("java:comp/env/jdbc/XADS");
QueueConnectionFactory qcf = (QueueConnectionFactory)ic.lookup("java:comp/env/jms/XAQCF");
ut.begin(); //トランザクション開始
QueueConnection qc = qcf.createQueueConnection();
qc.start();
QueueSession session = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueReceiver receiver = session.createReceiver(requestQ);
QueueSender sender = session.createSender(replyQ);
java.sql.Connection conn = ds.getConnection();
TextMessage inMsg = (TextMessage)receiver.receive(); //メッセージ受信
String tmp = inMsg.getText();
java.sql.PreparedStatement pst = conn.prepareStatement(sql);
int flag = pst.executeUpdate(); //データベース更新
sender.send(inMsg); //メッセージ送信
conn.close();
qc.close();
ut.commit(); //コミット
(省略)
94
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コネクション・プーリング
MQ Javaが内部的に独自のコネクション・プーリング機能を提供
BaseJava、JMSともに同じ仕組みのプーリングを使用
"
使用方法は若干異なる
使用しなくなった(アプリケーションがDisconnectした)コネクションを切断せずに
プールし、再利用する
"
事前に指定した数のコネクションをプールする仕組みではない
コネクションの保持時間と最大保持数を指定可能
"
"
保持時間を超えたコネクションは消去
最大保持数を超える場合、一番古いコネクションから消去
コネクション・プール
保持時間:5分
最大保持数:10個
②検索
アプリケーション
①MQCONN
MQOPEN
MQPUT
:
MQCLOSE
④MQDISC
③取得
キュー・マネージャー
⑤返却
95
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
コネクション・プーリング
デフォルト・コネクション・マネージャーを提供
"
保持時間および最大保持数が固定されている
保持時間:5分
最大保持数:10個
独自のコネクション・マネージャーを作成することも可能
"
"
保持時間および最大保持数を任意に指定できる
作成したものをデフォルトのコネクション・マネージャーとしてセットできる
プールのスコープはコネクション・マネージャー
"
デフォルトのコネクション・マネージャーを使用している場合は、プロセスごとに1つ
ローカル/クライアント接続とも使用可能
比較
Base Java
コネクション・
プーリング
JMS
◎
◎
・BaseJavaの機能を内部的に利用
96
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BaseJavaのコネクション・プーリング
BJ
使用方法は以下の3通り
方法1.デフォルト・コネクション・マネージャーを使用する
方法2.独自のコネクション・マネージャーを作成する
方法3.独自のコネクション・マネージャーを作成し、
デフォルト・コネクション・マネージャーとして使用する
97
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
方法1
BJ
方法1.デフォルト・コネクション・マネージャーを使用
使用方法 ⇒トークン(MQPoolToken)をMQEnvironmentに登録
"
MQEnvironmentのaddConnectonPoolTokenメソッドを発行
MQPoolToken token = MQEnvironment.addConnectionPoolToken();
停止方法 ⇒トークンをMQEnvironmentから削除
"
"
MQEnvironmentクラスのremoveConnectionPoolTokenメソッドを発行
使用開始時に作成したトークンを引き数に渡す
MQEnvironment.removeConnectionPoolToken(token);
複数のスレッドからトークンの登録/削除を行なっている場合、ひとつでもトークンが登録
されている間は、プールは存続
トークンが全て削除されると、プール内のコネクションは全て切断される
コネクションの保持時間と最大保持数の設定はできない
98
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BJ
方法2
方法2.独自のコネクション・マネージャーを作成
使用方法
1. MQSimpleConnectionManagerのインスタンスを作成
MQSimpleConnectionManager mySCM = new MQSimpleConnectionManager();
2. コネクションの保持時間/最大保持数を設定
% 保持時間:setTimeoutメソッド(ミリ秒)
% 保持数 :setHighThresholdメソッド
mySCM.setTimeout(3600000); //1時間
mySCM.setHighThreshold(50); //50個
3. プーリングの活動化
setActiveメソッドの引き数に以下の値を指定
MQSimpleConnectionManager.MODE_ACTIVE
mySCM.setActive(MQSimpelConnectionManager.MODE_ACTIVE);
4. MQSimpleConnectionManagerをMQQueueManagerのコンストラクタに引き数として渡す
MQQueueManager qmgr = new MQQueueManager(“My_QMGR”, mySCM);
99
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
方法2
BJ
停止方法 ⇒プーリングの非活動化
"
setActiveメソッドの引き数に以下の値を指定
MQSimpleConnectionManager.MODE_INACTIVE
mySCM.setActive(MQSimpelConnectionManager.MODE_INACTIVE);
100
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BJ
方法3
方法3.独自のコネクション・マネージャーを作成し、
デフォルト・コネクション・マネージャーとして使用
使用方法
1. MQSimpleConnectionManagerのインスタンスを作成
MQSimpleConnectionManager mySCM = new MQSimpleConnectionManager();
2. コネクションの保持時間/最大保持数を設定
% 保持時間:setTimeoutメソッド(ミリ秒)
% 保持数 :setHighThresholdメソッド
mySCM.setTimeout(3600000); //1時間
mySCM.setHighThreshold(50); //50個
3. 自動モードに設定
setActiveメソッドの引き数に以下の値を指定
MQSimpleConnectionManager.MODE_AUTO
mySCM.setActive(MQSimpelConnectionManager.MODE_AUTO);
4. デフォルトのコネクション・プーリングとしてセット
MQEnvironmentのsetDefaultConnectionManagerメソッドの引き数に渡す
MQEnvironment.setDefaultConnectionManager(mySCM);
101
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BJ
方法3
使用方法(続き)
5. トークンの登録
MQEnvironmentのaddConnectonPoolTokenメソッドを発行
MQPoolToken token = MQEnvironment.addConnectionPoolToken();
停止方法
"
トークンの削除
MQEnvironmentクラスのremoveConnectionPoolTokenメソッドを発行
使用開始時に作成したトークンを引き数に渡す
MQEnvironment.removeConnectionPoolToken(token);
102
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
JMSのコネクション・プーリング
JMSのコネクション・プーリング
BaseJavaのコネクション・プーリングを内部的に使用
デフォルト設定のままで、アプリケーションは意識することなく使用できる
"
"
"
ただし、キュー・マネージャーと接続されたコネクションが1つでもないと、プール自体がなくなる
MQEnvironmentにMQTokenを登録してプーリングの永続化ができる
$
BaseJavaの方法1を使用
MQSimpleConnectionManagerを使用してプーリングの設定を行なうこともできる
$
BaseJavaの方法3を使用
$
方法2は使用できない
103
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
BJ
エラー処理(BaseJava)
BaseJavaのエラー処理
BaseJavaのメソッドは処理が異常終了した場合、MQExceptionをthrowする
"
理由コード、完了コードのどちらか1つでも0以外の値の場合、例外がthrowされる
理由コード、完了コードはMQExceptionの変数として定義される
"
"
理由コード:MQException.reasonCode
完了コード:MQException.completionCode
コール毎のエラー・チェックは不要 → 複数コールのエラーをまとめてチェック可能
"
try~catchによりMQExceptionをcatchし、その変数を調べることで理由コード、完了コードを取
得
コーディング例
try{
queueA.put(messageA,putMessageOptionsA);
queueB.put(messageB,putMessageOptionsB);
}
catch(MQException ex){
System.out.printIn("An Error occured ;" +
"CC =" + ex.completionCode +
"RC =" + ex.reasonCode);
}
104
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
エラー処理(JMS)
JMSのエラー処理
JMSのメソッドは処理が異常終了した場合、JMSExceptionをthrowする
"
"
内部的にMQExceptionを含む場合がある
getLinkedExceptionメソッドでMQExceptionを取得可能
コール毎のエラー・チェックは不要 → 複数コールのエラーをまとめてチェック可能
"
"
try~catchによりJMSExceptionをcatchし、内容を出力
MQExceptionがリンクされている場合は、理由コード、完了コードを取得
例
try{
:
(JMS処理)
:
}
catch(JMSException je){
System.out.printIn("An Error occured :" + je);
Exception e = je.getLinkedException();
if(e != null){
System.out.println("linked exception :");
System.out.println(" CC =" + e.completionCode);
System.out.println(" RC =" + e.reasonCode);
}
}
105
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
エラー処理(JMS)
注意点
JMSでは、No_WaitかWait_Interval指定でGETしたとき、キューにメッセージがなくても
例外をthrowせず、正常終了する
"
"
BaseJavaの場合は、MQRC_NO_MSG_AVAILABLE(MQRC:2033)の例外が発生
後続の処理で受信メッセージのオブジェクトに対し操作を行なうと、そのタイミングで例外が発生
してしまう
受信後のメッセージ処理前には、MessageオブジェクトのNullチェックを行なう
Message inMsg = receiver.receiveNoWait();
if(inMsg == null){
System.out.println("No message !");
}else{
:
メッセージ処理
:
}
106
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
トレース機能(BaseJava)
BJ
トレースの指定は、コード内に記述
MQEnvironmentクラスのメソッドを使用
enableTracing(n)
n:トレース・レベル 1から5まで設定可能
"
"
"
"
"
1:Entry、Exit、Exception
2:1+パラメーター情報
3:2+MQSeriesヘッダー、データ・ブロック
4:3+ユーザー・データ
5:4+JVMのメソッド・トレース
disableTracing()でトレース終了
レベル5のトレースを取得するには、java_g、appletviewer_gでアプリケーションを実行する
デフォルトではjavaコンソールに出力される(System.err)
"
Streamを使用して出力先を指定することも可能
設定例
レベル4のトレースをjmstrace.txtファイルに出力させる場合
FileOutputStream traceFile = new FileOutputStream("jmstrace.txt");
MQEnvironment.enableTracing(4, traceFile);
107
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
トレース機能(JMS)
トレースの指定は、JVMの起動パラメータに設定
パラメータ"MQJMS_TRACE_LEVEL"に以下のいづれかの値をセット
"
"
on :MQ JMSレベルのトレース
base:MQ base Javaレベルのトレース
出力先ファイル名:mqjms.trc(固定)
出力ディレクトリ:デフォルトでは、コマンド実行ディレクトリに出力
"
"MQJMS_TRACE_DIR"で変更可能
設定例
MyJMSProgプログラムのトレースをMQ base Javaレベルで/tmp/jmstrcディレクトリに出
力させる場合
java -DMQJMS_TRACE_LEVEL=base -DMQJMS_TRACE_DIR=/tmp/jmstrc MyJMSProg
コーディング内でBaseJavaのトレース機能を利用することも可能
MQEnvironmentのenableTracingメソッドを使用
"
BaseJavaレベルのトレースしか取れない
108
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
トレース機能
比較
Base Java
トレース機能
JMS
◎
・コード内に記述する必要がある
・細かいレベル設定が可能
◎
・コード内に記述する必要はない
・細かいレベルの設定ができない
・ただし、BaseJavaの機能を利用すれば、
BaseJavaと同じ設定が可能
109
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMSでコーディングする際の注意点
110
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
FAIL_IF_QUIESCING
PUT/GET時にFail_If_Quiescingがデフォルトで設定される
MQ5.2以前は、設定されていなかった
MQQueueConnectionFactoryのsetFailIfQuiesceメソッドに以下の値を渡すことで設定
を変更可能
"
"
"
JMSC.MQJMS_FIQ_YES: Fail_If_Quiescingあり(デフォルト)
JMSC.MQJMS_FIQ_NO : Fail_If_Quiescingなし
WASのコンソールからは設定できない
ただし、テスト(2003.6実施)では JMSC.MQJMS_FIQ_NOの設定は有効ではない
"
"
"
"
JMSC.MQJMS_FIQ_NOを設定しても、、、
トレース上は、Fail_If_Quiescingが有効になっている
アプリケーションがGetWait状態のとき、endmqm( i オプションなし)でキュー・マネージャーは終了
アプリケーションには、即時に、以下の例外が発生
javax.jms.JMSException: MQJMS2002: MQ キューからメッセージを取得できませんでした
補足:MQxMO_FAIL_IF_QUIESCINGオプション
"
PUT/GET時にキュー・マネージャーが終了中だと、処理を失敗させ、アプリケーションにエラーを
返す
111
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMS
JMSのデフォルト値
JMSでは、MQI/BaseJavaでコーディングしたときとデフォルトの設定が異なる
Priorityのデフォルト値は、4
"
MQI/BaseJavaでは、0
永続性のデフォルト値は、パーシステント
"
MQI/BaseJavaでは、キューの属性に依存( AS_Q_DEF )
$
キューのデフォルト属性はノン・パーシステントなのでMQI/BaseJavaのデフォルトは、
ノン・パーシステント
112
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
機能比較
BaseJavaとJMSの機能比較表
機能
Base Java
JMS仕様
に準拠
JMS
グループ化
◎(MQIと同等の設定が可能)
・キュー・マネージャーによるIDの自動採番
・全てのMSGが揃ってからGETすることが可能
△
・ユーザがグループIDや順序番号を設定
・MQGMO_LOGICAL_ORDERの指定はできない
・MQGMO_ALL_MSGS_AVAILABLEの指定はできない
△
セグメント化
◎(MQIと同等の設定が可能)
×(利用不可)
N/A
要求/応答メッセージ
の紐付け
◎(MQIと同等の設定が可能)
○
・メッセージIDを自由に設定できない
○
応答先の指定/
応答先への送信
◎( MQIと同等の設定が可能)
◎
○
クライアント接続
○
・チャネル定義ファイルは使用できない
・環境変数は使用できない
○
・チャネル定義ファイルは使用できない
・環境変数は使用できない
○
◎(MQIと同等の設定が可能)
・GET待ちが可能
・ロックをかけることができる
・現カーサーの指すメッセージをGETできる
△
・GET待ちができない
・ロックがかけられない
・カーサーを使用したメッセージのGETができない
○
メッセージの永続性
◎(MQIと同等の設定が可能)
◎
○
MQのコード変換機能
◎(MQIと同等の設定が可能)
×
・CONVERTオプションの指定ができない
N/A
◎
◎
○
Browse機能
メソッドによる
Unicode変換
113
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
機能比較
BaseJavaとJMSの機能比較表(つづき)
機能
JMS
Base Java
JMS仕様
に準拠
同期点処理
◎(MQIと同等の設定が可能)
○
・PUT/GET単位でUOWに入れるかどうか指定できない
○
グローバル・
トランザクション
◎(MQIと同等の設定が可能)
・MQがコーディネーター
◎
・WASがコーディネーター
○
コネクション・
プーリング
◎
◎
・BaseJavaの機能を内部的に利用
○(※2)
トレース機能
◎
・コード内に記述する必要がある
・細かいレベル設定が可能
◎
・コード内に記述する必要はない
・細かいレベルの設定ができない
N/A
Priortyの設定(※1)
◎(MQIと同等の設定が可能)
◎
・デフォルト値は4に設定される
○
Report機能(※1)
◎(MQIと同等の設定が可能)
◎
×
クラスター環境での
BINDオプションの設定
(※1)
◎(MQIと同等の設定が可能)
△
・オプションの設定は不可
・MQBIND_AS_Q_DEFが採用される
N/A
コンテキストの設定(※1)
◎(MQIと同等の設定が可能)
×
・コンテキスト関連のオプションの設定ができない
N/A
※1 これらの機能は、当資料で詳細な説明をしていません
※2 BaseJavaのクラスを使用した場合は、JMSの仕様からは外れます
114
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMSヘッダ/プロパティとMQMDの対応
JMS
JMSヘッダ/プロパティとMQMDの対応表
JMSヘッダ
MQMD
JMSDestination
MQRFH2
備考
jms.Dst
Send Method
JMSDeliveryMode
Persistence
jms.Dlv
Send Method
JMSExpiration
Expiry
jms.Exp
Send Method
JMSPriority
Priority
jms.Pri
Send Method
JMSMessageID
MessageID
-
Send Method
JMSTimestamp
PutDate/PutTime
-
Send Method
JMSCorrelationID
CorrelId
jms.Cid
Message Object
JMSReplyTo
ReplyToQ/ReplyToQMgr
jms.Rto
Message Object
mcd.Type
Message Object
-
Receive-Only
JMSType
JMSRedelivered
BackoutCount
JMSプロパティ
MQMD
MQRFH2
備考
JMSXUserID
UserIdentifier
-
Send Method
JMSXAppID
PutApplName
-
Send Method
JMSXDeliveryCount
BackoutCount
-
Receive-Only
JMSXGroupID
GroupId
jms.Gid
Message Object
JMSXGroupSeq
MsgSeqNumber
jms.Seq
Message Object
115
Copyright ISE Co., Ltd.
<MQ Java デザインのポイント>
JMSヘッダ/プロパティとMQMDの対応
JMS
JMSヘッダ/プロパティとMQMDの対応表
プロバイダ固有JMSプロパティ
MQMD
MQRFH2
備考
JMS_IBM_Report_Exception
Report
-
Message Object
JMS_IBM_Report_Expiration
Report
-
Message Object
JMS_IBM_Report_COA
Report
-
Message Object
JMS_IBM_Report_COD
Report
-
Message Object
JMS_IBM_Report_PAN
Report
-
Message Object
JMS_IBM_Report_NAN
Report
-
Message Object
JMS_IBM_Report_Pass_Msg_ID
Report
-
Message Object
JMS_IBM_Report_Pass_Correl_ID
Report
-
Message Object
JMS_IBM_Report_Discard_Msg
Report
-
Message Object
JMS_IBM_MsgType
MsgType
-
Message Object
JMS_IBM_Feedback
Feedback
-
Message Object
JMS_IBM_Format
Format
-
Message Object
JMS_IBM_PutApplType
PutApplType
-
Send Method
JMS_IBM_Encoding
Encoding
-
Message Object
JMS_IBM_Character_Set
CodedCharacterSetId
-
Message Object
JMS_IBM_PutDate
PutDate
-
Send Method
JMS_IBM_PutTime
PutTime
-
Send Method
JMS_IBM_Last_Msg_In_Group
MsgFlags
-
Message Object
116
Copyright ISE Co., Ltd.
Fly UP