20
-1- 9章 プログラミング・インターフェース ~ その2 WebSphere MQとJava ~ この章では、WebSphereMQが持つJavaプログラミング・インタフェースについて、簡単にお話し したいと思います。(個々のAPIの機能 やパラメーターについては、あまり触れません) これまでお話ししてきましたように、WebSpher e MQはいろい ろなシステムを緩やかに結合するための 通信ミドルウェアです。今日現在ではInternet を利用して、各地に点在するシステムを接続することが 必然的になりましたので、バージョン5以降からはJava環境 でも利用出来るようになりました。 WebSphere M Qが持つJava プログラミング・インターフェースとしては、 ●WebSphe re M Q独自のJavaプログラミン グ・インターフェースである、MQ Base Java ●J2EEの世界で使われる、JMS(Ja va Message Service の略) の2つがあります。 また、アプリケーションとキュー・マネージャーの接続方法から見ると、 ●アプリケーションが、同一システム上で稼働するキュー・マネージャーと直接接続する、 バインディング接続 ●アプリケーションが、ネットワークを経由してキュー・マネージャーと接続するクライアント 接続 の2種類があります。そして、これらの接続方法は、MQ Base JavaとJMSのどちらでも利用出来ます (ただし、一部のプラットフォームではバインディング接続が出来ないものがあります) では、まず最初にそれぞれのインタフェースについて、お話ししましょう。 9-1. MQ Base Java MQ Base Jav aインタフェースは、7章でお話ししたMQIをJavaの世界に 移植した、WebSphere M Q 独自のJav aプログラミング・インターフェースです。そのため、MQIが実装しているメッセ ージ処理 機能のほとんどをJavaアプリケーション から利用出来ます。 Copyright IBM Japan, Ltd

9章プログラミング・インターフェース~そ …public.dhe.ibm.com/software/dw/jp/websphere/wmq/mq_intro/...J2EEの世界で使われる、JMS(JavaMessageServiceの略)

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

  • - 1 -

    9 章 プログラミング・インターフェース ~ その2 WebSphere MQとJava ~

    この章では、WebSphere MQが持つJavaプログラミング・インタフェースについて、簡単にお話し

    したいと思います。(個々のAPIの機能やパラメーターについては、あまり触れません)

    これまでお話ししてきましたように、WebSphere MQはいろいろなシステムを緩やかに結合するための

    通信ミドルウェアです。今日現在ではInternetを利用して、各地に点在するシステムを接続することが

    必然的になりましたので、バージョン 5以降からはJava環境でも利用出来るようになりました。

    WebSphere MQが持つJavaプログラミング・インターフェースとしては、

    ●WebSphere MQ独自のJavaプログラミング・インターフェースである、MQ Base Java

    ●J2EEの世界で使われる、JMS (Java Message Serviceの略)

    の2つがあります。

    また、アプリケーションとキュー・マネージャーの接続方法から見ると、

    ●アプリケーションが、同一システム上で稼働するキュー・マネージャーと直接接続する、

    バインディング接続

    ●アプリケーションが、ネットワークを経由してキュー・マネージャーと接続するクライアント

    接続

    の2種類があります。そして、これらの接続方法は、MQ Base JavaとJMSのどちらでも利用出来ます。

    (ただし、一部のプラットフォームではバインディング接続が出来ないものがあります)

    では、まず最初にそれぞれのインタフェースについて、お話ししましょう。

    9-1. MQ Base Java

    MQ Base Javaインタフェースは、7章でお話ししたMQIをJavaの世界に移植した、WebSphere MQ

    独自のJavaプログラミング・インターフェースです。そのため、MQIが実装しているメッセージ処理

    機能のほとんどをJavaアプリケーションから利用出来ます。

    Copyright IBM Japan, Ltd

  • - 2 -

    またこのMQ Base Javaを使ったプログラムでは、ロジックもMQIを使ったプログラムに似ている

    ところが多いので、MQIアプリケーションからの移行も比較的容易にできます。

    (1) プログラムの流れ

    おおまかな流れは、下の図のようになります。

    ①必要なパッケージのimport

    まず最初に、プログラムで必要となるjava.io.*などのimportを行います。WebSphere MQ

    アプリケーションで使用するのは主にcom.ibm.mq.jarですので、これを忘れずにimport

    して下さい。

    なお、

    - Unix系 /opt/mqm/java/lib

    - Windows [WebSphere MQ導入先ディレクトリー]\Java\lib

    には、com.ibm.mq.jar以外にも幾つかのクラス・ライブラリーがありますので、予め

    これらのディレクトリーを環境変数"CLASSPATH"に追加しておくことと、必要に応じて

    他のライブラリーもimportするようにして下さい。

    ②環境設定

    ご存じの通り、一般にJavaアプリケーションはshellやコマンド・プロンプトで設定され

    ている環境変数にアクセス出来ません (つまり、環境変数 "MQSERVER"を利用したクライ

    アント接続ができない)。このため、Javaを使ったWebSphere MQアプリケーションでは

    「どのホスト上の、どのキュー・マネージャーに接続するか」をアプリケーションの

    中でコーディングする必要があります。com.ibm.mq.jarにはMQEnvironmentというクラスが

    Copyright IBM Japan, Ltd

  • - 3 -

    Copyright IBM Japan, Ltd

    あり、このクラスが持つ幾つかのstatic変数を設定することで、クライアント接続のため

    必要となる情報の設定を行います。例えば、

    - 接続先キュー・マネージャーが存在するホスト名を指定する、MQEnvironment.

    hostname

    - 接続に使用するチャネル名を指定する、MQEnvironment.channel

    - リスナー・プログラムがListernしているポート番号を指定する、MQEnvironment.

    port

    - 接続先キュー・マネージャーのCCSID属性を指定する、MQEnvironment.CCSID

    などがあります。これらを設定した後、反映させるために、

    MQEnvironment.properties.put()メソッドを呼び出して下さい。

    MQEnvironment.hostname = "orange.wsdd.com"; // 接続先ホスト

    MQEnvironment.channel = "ch.javaTest"; // チャネル名.

    // キュー・マネージャー上に、

    // SVRCONNとして定義済みのこと.

    MQEnvironment.port = 1416; // リスナーがlisternしているport.

    MQEnvironment.CCSID = 932; // 接続先キュー・マネージャーの

    // CCSID属性の値

    MQEnvironment.properties.put( MQC.TRANSPORT_PROPERTY,

    MQC.TRANSPORT_MQSERIES );

    この段階では、まだチャネル接続は行われていません。(なお、WebSphere MQ V6からは、

    Javaアプリケーションから、クライアント接続チャネル・テーブルへのアクセスが出来る

    ようになりました)

    ③キュー・マネージャーとの接続

    MQQueueManagerクラスのコンストラクターを呼び出すことで、キュー・マネージャーとの

    接続が行われます。生成されたMQQueueManagerクラスのインスタンスが、MQIのMQCONNで

  • - 4 -

    Copyright IBM Japan, Ltd

    得られる接続ハンドルに相当します。なお、MQQueueManagerクラスのコンストラクター

    には幾つかのバリエーションがありますので、必要に応じて使い分けて下さい。

    // キュー・マネージャー "orange" と接続 : 一番簡単なコンストラクター呼び出し方法

    MQQueueManager myQmgr = new MQQueueManager( "orange" );

    インスタンスの生成が成功すると、内部的にMQCONNが発行され、指定されたキュー・

    マネージャーとの接続が行われます。

    ④キューのオープン

    MQ Base Javaを使ったプログラムでキューをオープンするには、MQQueueクラスのインス

    タンスを生成しますが、これには2つの方法があります。

    一つは、オーソドックスなJavaのプログラミングと同様に、MQQueueクラスのコンストラ

    クターでインスタンスを生成する方法です。

    MQQueue myQueue = new MQQueue(

    myQmgr, // MQQueueManagerのインスタンス

    "lq01", // (String) キューの名前

    openOpt, // (int) オプション

    null, // (String) キュー・マネージャー名

    null, // (String) 動的キューの名前

    null // (String) 代替ユーザー ID

    );

    もう一つは、③で作成したMQueueManagerクラスが持つaccessQueue()メソッドを呼び出し

    て、インスタンスを生成する方法です。

    MQQueue myQueue = myQmgr.accessQueue(

    "lq01", // (String) キューの名前

    openOpt, // (int) オプション

    null, // (String) キュー・マネージャー名

  • - 5 -

    Copyright IBM Japan, Ltd

    null, // (String) 動的キューの名前

    null // (String) 代替ユーザー ID

    );

    どちらの方法でも、キューをどのような目的で使用するのか、つまり後続の処理がMQIの

    MQPUT/MQGET/MQSET/MQINQのどれなのかを指定するためのオプションを指定する必要が

    あります (上記のコードでは、openOpt)。ここで生成されたインスタンスが、MQIの

    MQOPENで得られるオブジェクト・ハンドルに相当します。

    ⑤各種パラメータの設定

    8章でお話ししたMQIでは、

    - キューにメッセージを書き込む(MQPUT)場合には、MQPMO構造体

    - キューからメッセージを読み出す(MQGET)場合には、MQGMO構造体

    に、それぞれ必要なパラメータを設定しました。MQ Base Javaでは、これらの構造体も

    - MQPutMessageOptions

    - MQGetMessageOptions

    というクラスとして提供されており、MQPMO構造体やMQGMO構造体で使ったパラメータが

    設定出来るようになっています。

    MQPutMessageOptions pmo = new MQPutMessageOptions();

    pmo.Options = (~パラメータを設定~)

    MQGetMessageOptions gmo = new MQGetMessageOptions();

    gmo.Options = (~パラメータを設定~)

    ⑥メッセージ処理

    WebSphere MQでの「メッセージ」とは、メッセージの属性や宛先情報などを格納した

    ヘッダ部分とユーザー・データという2層から構成されています。 MQ Base Javaでは、

    MQMessageクラスがこれらの情報の「入れ物」となります。

    MQMessage msg = new MQMessage(); // ヘッダ部分 + ユーザー・データ

  • - 6 -

    Copyright IBM Japan, Ltd

    ヘッダ部分に設定すべき情報は、このMQMessageクラスが持つ各変数に設定することになり

    ます。

    msg.messageType = MQC.MQMT_DATAGRAM;

    msg.characterSet = 932; // このメッセージに含まれるデータのCCSID

    msg.format = MQC.MQFMT_STRING; // ユーザー・データは、文字型

    msg.persistence = MQC.MQPER_PERSISTENT; // パーシスタント・メッセージ

    (などなど...)

    メッセージをキューに書き込む場合、このインスタンスに実際のユーザー・データを格納

    します。なお格納するためのメソッドは、ユーザー・データのタイプなどにより、異なり

    ます。

    String myMsg = "台風14号接近中 !"; // ユーザー・データ

    msg.writeString( myMsg); // 上記のデータを、先に設定したCCSIDで

    // 扱う

    (*)他に、Unicodeを扱うためのwriteChar()/writeChars()や、Javaオブジェクトを

    扱うためのwriteObject()などがあります。取り扱うデータのタイプによって、

    適切なメソッドを使用して下さい。

    MQMessageのインスタンスの準備が終わったら、キューへ書き込みます。この時使用する

    put()メソッドは、MQQueueクラスに実装されています。

    myQueue.put( msg, pmo); // キューに書き込む.

    一方メッセージをキューから読み出す場合には、

    ⅰ. MQGetMessageOptionsクラスのインスタンス生成と、必要なパラメータの設定

    (MQGetMessageOptions.waitIntervalなど)

    ⅱ. MQMessageクラスのインスタンス生成と、必要なパラメータの設定

    Ⅲ. ユーザー・データを格納するバッファーの準備

    を行い、MQQueueクラスに実装されているget()メソッドを呼び出します。

    myQueue.get( msg, gmo ); // メッセージを読み出す

    そして、MQMessageからユーザー・データを読み出します。この時使用するメソッドは、

    やはりユーザー・データのタイプにより異なります。例えば、readLine()メソッドは、

    MQMessage.CCSIDで指定されたCCSIDからUnicodeへデータ変換を行い、1行分の文字列を

    指定されたバッファーにコピーします。

    String myMsg = null; // バッファーの準備

    msg.readLine( myMsg ); // データをUnicodeに変換し、1行分の文字

  • - 7 -

    Copyright IBM Japan, Ltd

    // 列を準備したバッファーに読み込む

    (*)他に、Unicodeを扱うためのreadChar()や、Unicodeに変換し指定された長さ分の

    文字列を読み込むreadLine()、Javaオブジェクトを扱うreadObject()などが

    あります。

    ⑦キューのクローズ

    メッセージの処理が終わったら、MQIと同様にキューのクローズを行います。

    myQueue.close(); // キューのクローズ.

    利用が終わったキューは、必ずclose()メソッドを呼び出すことを忘れないようにして

    下さい。

    ⑧キュー・マネージャーからの切断

    最後に、キュー・マネージャーからの切断を行います。

    mqQmgr.disconnect(); // キュー・マネージャーからの切断

    キューのクローズと同様に、アプリケーションの終了時にはdisconnect()メソッドで

    キュー・マネージャーから切断することを忘れないようにして下さい。

    (2) エラー処理

    MQ Base Javaの各メソッドは、MQIのように理由コードや完了コードをアプリケーションに戻し

    ません。その代わりに、正常終了以外の理由コードや完了コードを、MQExceptionという

    Exceptionでアプリケーションに通知します。このため、MQIを利用したアプリケーションでは

    各API毎に行っていたエラー処理を、まとめてtry-catchブロックで処理することが出来ます。

    (極端な事を言えば、アプリケーション全体のエラー処理を1つのtry-catchブロックにまとめ

    て処理、ということも可能ですが、適切な単位で処理して下さい)

    try

    {

    myQueue.put( msg1, pmo1 );

    myQueue.put( msg2, pmo2 );

    myQueue.put( msg3, pmo3 );

    }

    catch( MQException mqe )

    {

    System.out.println(" 問題発生 /理由 : " + mqe.reasonCode +

    "/ 状態 : " + mqe.completionCode );

    // 終了処理など、その他の処理

    // 例えば、MQQueue.close(),MQQueueMqnager.disconnect()など

    }

    MQExceptionとして得られる、MQException.reasonCodeとMQException.completionCodeには、

    MQIアプリケーションで使われた理由コードと完了コードと同じものが設定されます。もし

    これらの値をアプリケーション内で使用する場合には、"MQC.MQRC_xxxxx"や"MQC.MQCC_xxxxx"

    といったシンボルを利用して下さい。

  • - 8 -

    Copyright IBM Japan, Ltd

    (3) マルチ・スレッドへの対応

    MQ Base Javaでは、MQQueueManagerオブジェクトやMQQueueオブジェクトを、複数スレッドで

    共有することが可能です。ただし、WebSphere MQ関連のメソッドが"synchronized"されている

    ため、あるスレッドで呼び出されたWebSphere MQ関連のメソッドの処理中には、他のスレッド

    の処理が待たされることになります。もし複数スレッドが同時に処理を行いたいような場合に

    は、それぞれのスレッドでMQQueueManagerオブジェクトやMQQueueオブジェクトを生成する

    ようにして下さい。

    9-2. JMS

    JMSは、J2EEの世界で利用されるメッセージング・ミドルウェア用のAPIです。この規格では、

    メッセージの送信及び受信という、基本的な機能に関するインターフェースや、アプリケーション

    から見たときのメッセージの論理的な構造が、定められています。(詳細に関しては、JMSの仕様書

    や市販の本をご参照下さい)

    では、JMSについて、簡単にお話ししたいと思います。

    (1) JMSとは

    上述の通り、JMS(Java Message Service)は、J2EEで規約されているインタフェース、および

    「仕組み」で、メッセージング製品毎の違いを吸収して、アプリケーション・コードの共通化

    を目的としています。

    JMSの構成要素は、下の図のようになります。

    ●JMSクライアント

    JMSクライアントとは、JMSインターフェースを利用して、ユーザー・データを含む

    メッセージの送受信を行う、Javaアプリケーションのことを指します。

    ●JMSプロバイダー

    WebSphere MQのような、JMSを実装したメッセージング機能を提供する製品や仕組みを

    意味します。

  • - 9 -

    Copyright IBM Japan, Ltd

    ●メッセージ

    JMSクライアントが扱うユーザー・データを含むオブジェクトです。JMSで扱うメッ

    セージの論理的な構造は、下の図のように3階層になります。

    ⅰ. ヘッダ

    メッセージを識別するためのIDや宛先情報、そのメッセージの優先度など、各

    メッセージング製品で共通の属性を保持するためのフィールドです。これらの

    属性の中には、アプリケーションから設定可能なものと、設定出来ないものが

    あります。

    ⅱ. プロパティー

    ヘッダ部分に設定される基本的な属性に対し、付加的な情報を表す属性を保持

    するフィールドです。例えば、このメッセージを作成したユーザーやアプリ

    ケーションに関する情報などがあります。またアプリケーション独自の属性を

    追加することも、可能です。

    ⅲ. ボディー

    ユーザー・データが格納されるフィールドですが、データのタイプによって

    JMSでは次の5つのメッセージ・タイプを定義しています。

    - BytesMessage

    Byteストリームを扱うメッセージで、イメージなどバイナリー・データを扱う

    場合に使用します。

    - TextMessage

    その名の通り、テキスト・データを扱うためのメッセージです。

    - MapMessage

    String型の変数名とその値(intやbyteなどJavaの基本的なデータ型)というペア

    を複数個格納したメッセージです。アプリケーション・プログラムは、メッ

    セージに含まれるString型の変数名を指定することで、メッセージ内の順番に

    かかわらず、その変数に対応する値にアクセスできます。(ランダム・アクセス

    ファイルのように)

    - StreamMessage

    MapMessageと同様に、複数のJava基本データが格納されたメッセージですが、

    MapMessageと異なって各データに名前が付いていない、単に複数の「データ」

    の並びとなっています。このため、シーケンシャル・ファイルのように、並ん

    でいる順番でしかデータを処理出来ない、メッセージになります。

    - ObjectMessage

    java.io.Seriealizableを実装したJavaオブジェクトを扱うためのメッセージ

    です。

    なお、これらのタイプ毎に、メッセージの作成や送受信といった処理で使われる

    メソッドが異なりますので、注意して下さい。

    ボディーヘッダ プロパティー ボディーヘッダ プロパティー

  • - 10 -

    Copyright IBM Japan, Ltd

    ●ネームスペース (ディレクトリー・サービス)

    JMSでは、アプリケーション・プログラムとJMSプロバイダーである各製品の性質を分離

    するために、ネームスペース(ディレクトリー・サービス)を利用します。それぞれの

    製品独自の属性(例えば、WebSphere MQでのキューの各種属性など)やコンテキストを

    必要に応じて登録しておきます。アプリケーション・プログラムは実行時にlookup()を

    行って、必要な情報を入手することで、各製品の機能を利用できるようになります。

    (このような仕組みを利用せず、アプリケーション・プログラムが実行時に直接必要な

    コンテキストを生成する方法もあります)

    WebSphere MQの場合、JMSAdminというコマンドを使って、キュー・マネージャーや

    キューの名前などの情報を、ネームスペースやディレクトリー・サービスへ登録します。

    (2) プログラムの流れ

    先にお話ししたように、JMSでのプログラムはメッセージの送信および受信という基本的な

    機能に対する共通規格です。そのため、従来のMQIやMQ Base Javaを使ったプログラミングとは

    かなり異なります。

    まずJMSアプリケーションは、「ドメイン」と呼ばれる2つのプログラミング・パターンに、分類

    されます。

    ●Point to Point型 (PTP型)

    PTP型のシステムでは、メッセージの作成/送信側の事をProducerと、またメッセージの

    受信側の事をConsumerと呼びます。

    ProducerとConsumerは、それぞれQueueオブジェクトに接続し、このQueueオブジェクト

    を介してメッセージの送受信を行います。このとき、

    - 1つのQueueオブジェクトには、複数のProducer/Consumerがそれぞれ接続可能

    - あるProducerが送信した1メッセージを受け取ることが出来るのは、Queueオブジェ

    クトに接続しているConsumerの中の1つだけ (同時に複数のConsumerが、同一メッ

    セージを受信出来ない)

  • - 11 -

    Copyright IBM Japan, Ltd

    ことになります。

    * このPTP型アプリケーションで言う「Queueオブジェクト」とは、物理的なキューと

    その属性を抽象化したものです。

    ●Publish/Subscribe型 (Pub/Sub型)

    Pub/Sub型のシステムでは、メッセージの作成/送信側をPublisher、受信側をSubscriber

    とそれぞれ呼びます。

    このタイプのシステムでは、Publisher側、Subscriber側共にそれぞれが関係する

    「Topic」と呼ばれるオブジェクトに接続し、このTopicを介してメッセージの送受信を

    行います。P2Pシステムとは、

    - Publihserが送信したメッセージは、そのTopicに接続しているSubscriber全てが

    受信可能 (どのように全てのSubscriberにメッセージを渡すかという機能の実装

    方法は、それぞれのJMSプロバイダー毎に異なります)

    という点が異なります。

    * このPub/Sub型アプリケーションで使われる「Topicオブジェクト」とは、物理的な

    キューとその各種属性と、各Subscriberにメッセージを配信する機能を合わせた

    オブジェクトになります。

    なお、JMS 1.0.2まではドメイン毎にAPIが異なっていましたが、JMS 1.1では同じAPIで対応

    出来るようになりました。ここでは、JMS 1.1でのプログラムの流れを、簡単に追うことに

    します。

  • - 12 -

    Copyright IBM Japan, Ltd

    ①必要なパッケージのimport

    WebShere MQを使ったJMSアプリケーションで必要となるクラス・ライブラリーは、主に

    com.ibm.mq.jarになります (jms.jarでも可能です)。更にConnectionFactoryをJNDI

    ネームスペースから取得する場合には、jndi.jarなど幾つかのクラス・ライブラリーが

    必要になります。例えば、以下のようになります。

    import javax.jms.*; // JMSインタフェースのimport

    import javax.naming.*; // JNDI用

    import java.util.Hashtable; // JNDI初期化用

    (なお、ConnectionFactoryをアプリケーション実行時に生成する場合には、

    com.ibm.mqjms.jarが必要になります)

    ②ConnectionFactoryの取得

    ConnectionFactoryとは、JMSクライアント(JMSアプリケーション)がJMSプロバイダーとの

    接続するために必要となる情報とお考え下さい。WebSphere MQで言えば、

    - 接続先のキュー・マネージャーの名前や、CCSID属性

    - 使用するキューの名前や、各種属性

    - キュー・マネージャーが稼働しているホスト名

    - 接続するために使用するチャネルの名前

    などが相当します。この際、JNDIなどを利用して、予め登録済みの各種情報にアクセス

    することになります。(MQ Base JavaのMQEnvironmentの設定作業に相当します)

    // InitialContextFactoryの生成

    java.util.Hashtable environment = new java.util.Hashtable();

    environment.put( Context.INITIAL_CONTEXT_FACTORY, icf );

  • - 13 -

    Copyright IBM Japan, Ltd

    environment.put( Context.PROVIDER_URL, url );

    Context ctx = new InitialContext( environment );

    // ConnectionFactoryの取得

    ConnectionFactory factory;

    factory = (ConnectionFactory)ctx.lookup(......); //パラメータ省略

    ③Destinationの取得

    Destinationとは、

    - メッセージの送信側にとっては、メッセージの送信先

    - メッセージの受信側にとっては、メッセージの取り出し元

    のオブジェクト、つまりキューを抽象化したものです。予めネームスペースにその実体の

    名前や各種属性を登録しておき、JMSクライアントがlookup()することで、Destinationを

    取得します (Destinationクラスは"abstract"クラスですので、実際にはQueueオブジェク

    ト又はTopicオブジェクトを取得することになります)

    Queue myQueue;

    // ネームスペースから、"testQueue"で表現されるキューの情報を入手する

    myQueue = (Queue)ctx.lookup( testQueue );

    ④Connectionの生成

    ②で得られた情報を元に、キュー・マネージャーに接続するために必要となる環境設定を

    行い、Connectionオブジェクトを生成します。

    // ConnectionFactoryから、Connectionを生成

    Connection connection = factory.createConnection();

    // 生成したConnectionオブジェクトは、まだ停止状態

    このConnectionオブジェクトとは、JMSクライアントとJMSプロバイダーとの「ネット

    ワーク・レベルでの接続」を、抽象化したものとお考え下さい。

    ⑤Sessionの生成

    ③で生成したConnectionオブジェクトを基に、Sessionオブジェクトの生成を行います。

    Session session = connection.createSession(

    transactionFlag, // 同期点処理するか、どうかの指定

    Session.AUTO_ACKNOWLEDGE // 省略値.

    );

    第1パラメータで指定しますが、このSessionが同期点処理の単位となります。第2パラ

    メータは、JMSクライアントがメッセージを受信した際に、ACKをどのように送信側へ戻す

    かを指定します。

    このSessionオブジェクトは、メッセージの処理を行うMessageProducerやMessageConsumer

    の生成だけでなく、Messageオブジェクトを生成するという役割も持ちます。

    ここから、MessageProducer(メッセージの送信側)とMessageConsumer(メッセージの受信側)

    とで、ちょっと異なります。まずは、MessageProducer側からです。

    ⑥MessageProducerの生成

  • - 14 -

    Copyright IBM Japan, Ltd

    SessionオブジェクトのcreateProducer()を利用して、MessageProducerオブジェク

    トを生成します。この時③で取得したDestinationオブジェクトと関連づけるため、

    そのDestinationオブジェクトをパラメータに指定します。

    MessageProducer msgSender;

    // myQueueは、③で取得したDestinationオブジェクト(Queueオブジェクト)

    msgSender = session.createProducer( myQueue );

    MessageProducerの作成が終わったら、Connectionオブジェクトを開始します。

    connection.start();

    この時点でキュー・マネージャーとの接続が行われます。

    ⑦メッセージの作成

    Messageオブジェクトも、Sessionオブジェクトから生成します。ただし、MapMessageや

    TextMessageなどのメッセージ・タイプ毎に、メソッドが異なります。

    String msgContent = "原稿が遅そいぞ"; // ユーザー・データ(テキスト)

    TextMessage msg;

    // TextMessageの生成

    msg = session.createTextMessage( );

    // ユーザー・データの埋め込み

    msg.setText( msgContent );

    ⑧メッセージの送信

    メッセージを送信するには、Destinationオブジェクトのsend()メソッドを使います。

    mySender.send( msg );

    これに対して、MessageConsumer側は、以下のような流れになります。

    ⑨MessageConsumerの生成

    SessionオブジェクトのcreateConsumer()を利用して、MessageConsumerオブジェクトを

    生成します。この時③で取得したDestinationオブジェクトと関連づけるため、その

    Destinationオブジェクトをパラメータに指定します。

    MessageConsumer msgReceiver;

    // myQueueは、③で取得したDestinationオブジェクト(Queueオブジェクト)

    msgReceiver = session.createConsumer( myQueue );

    MessageConsumerの作成が終わったら、Connectionオブジェクトを開始します。

    connection.start();

    この時点でキュー・マネージャーとの接続が行われます。

    ⑩メッセージの受信

    メッセージを読み出するためには、MessageConsumerオブジェクトに実装されている

    メソッドを使います。例えば、Queueオブジェクトからメッセージを読み出すためには、

    long waitInteral = 3000; // 待ち時間 (msec)

    Message receivedMsg = msgReceiver.receive(waitInterval);

    ここで、パラメータのwaitIntervalは、メッセージ受信の待ち時間です。

    ⑪メッセージ・タイプの確認と処理

  • - 15 -

    Copyright IBM Japan, Ltd

    ところで前述の通り、JMSでは5つのメッセージ・タイプがあり、それぞれのメッセージ・

    タイプ毎にその処理を行うメソッドが異なります。⑩でDestinationオブジェクトから

    読み取った時点ではそのメッセージがどのタイプなのかまだ分かりませんので、その

    タイプを確認する必要があります。(予め、送られてくるメッセージのタイプが決まって

    いるのであれば、別ですが)

    if( receivedMsg instanceof TextMessage )

    {

    // TextMessage処理

    String userData = ( (TextMessage)receivedMsg ).getText( );

    // 何らかの処理

    .......

    }

    else if( receivedMsg instanceof MapMessage )

    {

    // MapMessage処理

    } // 以下省略

    最後に、後処理を行います。

    ⑫使用したオブジェクトのクローズ

    まず、使用したMessageProducerオブジェクト又はMessageConsumerオブジェクトを、

    close()メソッドを使って、解放します。

    // MessageProducerの停止

    msgSender.close();

    又は

    // MessageConsumerの停止

    msgReceiver.close();

    これにより、新たなメッセージの送受信が停止することになります。

    続いて、Sessionオブジェクトを停止します。

    session.close();

    Connectionオブジェクトは、stop()メソッドにより停止状態へ遷移してから、close()

    メソッドにより、解放を行います。

    connection.stop();

    connection.close();

    これらの後処理を行うことにより、不要になった各種資源が解放されます。アプリケーション

    の最後には、これらの処理を忘れないようにして下さい。

    ここで、簡単にInitialContextFactoryから始まる各オブジェクト間の関係をまとめてみると、

    下の図のようになります。

  • - 16 -

    Copyright IBM Japan, Ltd

    (3) その他 ~ マルチ・スレッドへの対応、ConnectionFactory ~

    ①マルチ・スレッドへの対応

    JMSで使われるオブジェクトのマルチ・スレッドへの対応は、以下のようになっています。

    同期点処理の単位であるSessionオブジェクトは、複数スレッドで利用出来ません。もし

    マルチ・スレッド・アプリケーションから、同時にメッセージ処理を行いたい場合には

    それぞれのスレッドでSessionオブジェクトを生成して、使用して下さい。

    ②ConnectionFactoryとDestinationオブジェクト

    JMSアプリケーションの実行時に必要な情報を「表現して」いるConnectionFactoryや

    Destinationオブジェクトは、ネームスペースへlookup()することで入手すると、前述

    しました。では、どのようにネームスペースへ、これらの情報を登録するのでしょうか。

    WebSphere MQでは、JMSAdminというコマンドがあり、これを使ってWebSphere MQ独自の

    情報をネームスペースへ登録することが出来ます。このJMSAdminは、JMSAdmin.configと

    いう構成ファイルで指定されたネームスペースへ接続し、runmqscコマンドに似たコマンド

    で情報を登録します。

    JMSオブジェクト 複数スレッドからの利用

    Destination 可能

    ConnectionFactory 可能

    Connection 可能

    Session 不可能

    MessageProducer 不可能

    MessageConsumer 不可能

  • - 17 -

    Copyright IBM Japan, Ltd

    Linux上のWebSphere MQ V5.3でJMSAdminを実行すると、こんな感じになります。

    [uraga@nihonshu bin]# JMSAdmin -cfg JMSAdmin.config

    5648-C60 (c) Copyright IBM Corp. 1999. All right Reserved.

    MQSeries Classes for Java(tm) Message Servie Administrationを開始しています。

    InitCtx> define qcf(JMSTestCtx) +

  • - 18 -

    Copyright IBM Japan, Ltd

    (1) MQMD.MsgIdの指定

    7章でお話ししたように、MQMD構造体で表現されるメッセージのヘッダ部分には、そのメッ

    セージの属性などを表す各種フィールドがあります。この中でMsgIdフィールドは、アプリ

    ケーション・プログラムが独自に設定出来るフィールドの1つです。

    従来のMQIをJavaの世界へ移植したMQ Base Javaでも、このMsgIdフィールドを操作することが

    できます。しかしJMSを使った場合、送信側アプリケーション・プログラム内で独自の値を設定

    しても、JMSプロバイダーであるWebSphere MQがそのメッセージの一意性を保証するための値に

    「上書き」してしまいます。そのため受信側で処理する際、想定していた値がMsgIdフィールド

    にないことになります。

    (2) メッセージのSegmentation/Grouping

    1つの大きなメッセージをキュー・マネージャーが処理可能な大きさに自動分割したり、または

    それを元の大きさのメッセージに復元したりする機能や、物理的に別個の複数メッセージを

    グループ化して論理的に1つのメッセージとして扱う機能を、WebSphere MQはサポートしていま

    す。

    MQ Base Javaでもこれらの機能を利用可能ですが、JMSには該当する機能はありません。

    (この機能を使うためには、ヘッダ部分のあるフィールドを操作する必要があり、JMSでは操作

    できないため)

    (3) 配布リストの利用

    FAXの同報通信のように、WebSphere MQにも送信側の1回のMQPUTで、複数の宛先にメッセージを

    送る機能があります。このとき送信側アプリケーションで、複数の宛先を記述した配布リスト

    と呼ばれるリストを利用します。

    この機能もWebSphere MQ独自の機能であるため、MQ Base Javaからは利用可能ですが、JMSでは

    利用出来ません。

    (4) MQINQコール又はプログラムからのrunmqscコマンド実行

    MQIには

    機能 MQ Base Java JMS

    MQMD.MsgIdの指定 アプリケーションによる設定可能 アプリケーションによる設定不可能

    メッセージのSegmentation/Grouping 可能 不可能

    配布リストの利用 可能 不可能

    MQINQ/MQSERコール又はプログラムか

    らのrunmqscコマンド実行

    可能

    (ただし、幾つかのclassの作成が必

    不可能

    Message Selectorのサポート なし あり

    Publish/Subscribe機能のサポート 標準のAPIがないため、幾つかのclass

    の作成やコーディングが必要

    標準のAPIがあるので、容易

    非同期リスナーのサポート なし 有り

  • - 19 -

    Copyright IBM Japan, Ltd

    ●キュー・マネージャーが管理しているキューなどのオブジェクトの属性を取得する

    MQINQ

    ●オブジェクトの属性を変更するMQSET

    というAPIがあります。またアプリケーション・プログラムの中からrunmqscコマンドや、

    それと同等の機能を利用することができます。

    この機能もWebSphere MQ独自の機能ですので、MQ Base Javaでは利用可能ですが、JMSでは

    利用出来ません。(ただし、利用したいコマンドを意味するパラメータ群を、Javaのclassと

    して作成する必要があります)

    (5) Message Selectorのサポート

    メッセージをキューから読み出す際、MQIやMQ Base Javaではヘッダ部分のMsgIdフィールドと

    CorrelIdフィールドの二つを使って、特定のメッセージを選択することが出来ました。

    一方JMSでは、Message Selectorと呼ばれる機能を使うと、ヘッダ部分だけでなくプロパティー

    部分もメッセージを選択するときの条件として使うことができます。例えば、

    // 検索条件の設定 (Message Selectorの生成)

    String msgSelector = "(Weather = Rain) or (Weather = Typhoon)";

    MessageConsumer msgReceiver;

    // myQueueは、先に取得済み(Queueオブジェクト)

    msgReceiver = session.createConsumer( myQueue, msgSelector );

    // この後メッセージ受信を開始すると、プロパティーの"Weather"が

    // "Rain"か"Typhoon"という値になっているメッセージだけを

    // このアプリケーションは読み出すことになる.

    このMessage Selector機能を利用することで、JMSアプリケーションではより柔軟な条件指定が

    出来ることになります。

    (6) Publish/Subscribe機能のサポート

    WebSphere MQでPublish/Subscribe機能を利用する場合には、別途ブローカーを稼働させる

    必要があります。(V5.3移行では製品導入時に、Publish/Subscribe機能の導入を選択出来る)

    このブローカーと、Publish側アプリケーションおよびSubscribe側アプリケーションとの間で

    幾つかの情報の交換などを行うことで、情報の配信が出来るようになります。

    JMSでは、標準でこのPublish/Subscribeアプリケーション用のAPIを実装しているため、上記の

    ようなやり取りを意識せず、アプリケーションを作成することが出来ます。一方MQ Base Java

    には、Publish/Subscribe用のAPIを特に準備されていないため、ブローカーとのやり取りや

    そのためのヘッダの構築などを、コーディングする必要があります。

    (7) 非同期リスナーのサポート

    キューからメッセージを読み出す際、アプリケーションはAPIの制御が戻るまで待たされること

    になります。例えば、10秒という待ち時間を指定してメッセージの読み出しを行った場合、

    10秒内にメッセージがキューから読み出し可能になるか、又は10秒という時間が超過するまで

    そのアプリケーションは「待たされる」ことになるわけです。この状況は、MQIでもMQ Base

    Javaでも、また単純にMessageConsumer.receive()メソッドを利用しているJMSアプリケー

  • - 20 -

    Copyright IBM Japan, Ltd

    ションでも、変わりはありません。

    しかし、JMSには「非同期リスナー」と呼ばれるメッセージの受信処理だけを別のclassとして

    実装し、main()の処理と別のスレッドで実行させる機能があります。この機能を使うと、

    main()は各種セットアップや終了処理などに専念させ、メッセージの受信とその処理は別の

    スレッドで行うことが可能になり、より効率的なメッセージ処理を実装することができます。

    1つのアプリケーションで、MQ Base JavaとJMSの両方を使うことが出来ませんので、システムの

    用件やお使いになる環境によって使い分ける必要があります。例えば、

    ●従来のMQIでコーディングされたクライアント・アプリケーションをJava環境へ移行する

    場合.

    ●様々なプラットフォーム上で稼働するアプリケーションを簡単に作成したい場合.

    ●メッセージのヘッダ部分の操作が必要な場合.

    などには、MQ Base Javaを使うことをお勧めします。一方、

    ●Web Application Server上のEJBから、メッセージの送受信を行いたい場合.

    ●他のメッセージング・ミドルウェアで利用していたアプリケーションを、WebSphere MQに

    移植する場合.

    といったケースでは、JMSの方が適切と考えて下さい。

    (補足)WebSphere MQ V7.0からは、JMSでサポートされていたPublish/Subscribeや非同期リスナーと

    いった機能の一部を、MQIから利用できるようになりました。