タイガー!タイガー!じれったいぞー!(SE編)

AS400, Java, JavaEE, JSF等の開発、習慣など。日々の気づきをまとめたブログ(備忘録)

【MQ】 JavaでローカルキューにPutしてみる

以前に宣言した通り、今回より、IBM MQを検証した結果を掲載していこうと思います。

キューマネージャ、ローカルキュー、コネクション・オブジェクトを作成し、メッセージをPutするところから始めましょう。

まずは、基本を理解していきたいところ。

IBM MQとは?

IBM MQ(Message Queuing)は、IBMが提供するメッセージングソフトウェアの製品。

分散環境でアプリケーションやシステム間でメッセージを安全かつ信頼性高くやり取りするためのメッセージング・ミドルウェアを提供し、異なるプラットフォームやアプリケーション間で非同期のメッセージのやり取りを可能するものです。

検証環境について

  • O/S: Windows Server 2022 Server Standard Edition
    ファイアウォール設定: 受信規則追加 TCP(1414-1415)を許可
    ・ユーザー情報: t_yamada を追加し、mqmグループに追加
  • MQ Server: IBM MQ Ver 9.3.4.0
  • InstPath: C:¥Program Files\IBM\MQ
  • DataPath: C:¥ProgramData\IBM\MQ

事前準備

IBM MQ9.3のインストール

  • カスタムで「MQIクライアント」を選択する
  • 9.3から「MQエクスプローラー」が付属されなくなったみたい。男は黙ってCUIとする!

IBM MQ 9.3.0以降、 IBM MQ ExplorerIBM MQ インストール・パッケージから削除されました。
これは、 Fix Centralから入手できるスタンドアロン・ダウンロードとして引き続き入手できます。
(IBM MQ Explorer の概要より)

キューマネージャー

まず作成から起動です。

  • q: デフォルト設定
  • lc: 循環ロギング
> crtmqm -q -lc TSQMGR
> strmqm TSQMGR

確認方法

>dspmq
QMNAME(TSQMGR)                   STATUS(実行中)

停止方法

  • w:正常終了、すべてのアプリの終了を待つ
> endmqm -w TSQMGR

ローカルキュー

次は、ローカルキュー作成です。

> runmqsc TSQMGR  
   
DEFINE QL(QL.A) DESCR('QL.A Text')  
END  

確認(ローカルキューの全属性表示)はこちら。

> runmqsc TSQMGR  
  
DISPLAY QL(QL.A)  
END  

認証設定

作成したキューマネージャーへは、ServerにあるIDとPASSでのみ接続可能とします(これで合っているのかな?)

> runmqsc TSQMGR  
   
DEFINE AUTHINFO('MY.AUTHINFO') AUTHTYPE(IDPWOS) CHCKCLNT(REQUIRED) REPLACE  
ALTER QMGR CONNAUTH('MY.AUTHINFO')  
REFRESH SECURITY  
END  

この設定で、サーバとは別のPC上のJavaアプリケーションから、サーバ上に所属するIDとそのPASSでのみ接続できるようになりました。 CHCKCLNT(OPTIONAL)だと、別のPCのログインIDがサーバに存在しているだけでアクセス可能となりました。

MQクライアント

SVRCONNチャネルを定義し、MQクライアントが外部から接続できるにします。

> runmqsc TSQMGR  
DEFINE CHL(TSQMGR_CLNT) CHLTYPE(SVRCONN) TRPTYPE(TCP)  
ALTER QMGR CHLAUTH(DISABLED) CONNAUTH(' ')  
REFRESH SECURITY  
END  

リスナー・プロセスを起動して、クライアントの接続を待ちます。 1414ポートを開けることを忘れずに...。

> runmqlsr -t TCP –p 1414 -m TSQMGR

このコマンドで応答を待ち続けることになるので、別のDOS窓で実行するといいでしょう。

サンプルコード

ここまで来たら、javaアプリケーションの準備です。

IBM MQ classes for Java and JMSを取得します。

https://mvnrepository.com/artifact/com.ibm.mq/com.ibm.mq.allclient/9.3.4.0

dependencies {
    implementation group: 'com.ibm.mq', name: 'com.ibm.mq.allclient', version: '9.3.4.0'
}
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class testPutMQ {
    // MQサーバーの接続情報
    private static final String HOST = "192.168.1.1";
    private static final int PORT = 1414;
    private static final int CCSID = 932;
    private static final String CHANNEL = "TSQMGR_CLNT";
    private static final String QMGR = "TSQMGR";
    private static final String QUEUE_NAME = "QL.A";
    private static final String USER = "t_yamada";
    private static final String PASSWORD = "password";
    
    public static void main(String[] args) {
        try {
            MQEnvironment.hostname = HOST;
            MQEnvironment.port = PORT;
            MQEnvironment.CCSID = CCSID;
            MQEnvironment.channel = CHANNEL;
            MQEnvironment.userID = USER;
            MQEnvironment.password = PASSWORD;

            MQQueueManager qmgr = new MQQueueManager(QMGR);
            MQQueue queue = qmgr.accessQueue(QUEUE_NAME, CMQC.MQOO_OUTPUT);

            MQMessage message = new MQMessage();
            //*** MQMD (Message descriptor) ***
            message.expiry = 600; //有効時間(ミリ秒)ex: 600: 60秒
            message.format = CMQC.MQFMT_STRING; //文字形式
            message.persistence = CMQC.MQPER_NOT_PERSISTENT; //Persistence
            message.characterSet = 932;
            //*** Origin Context ***
            DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS");
            String formatNowDate = dtf1.format(LocalDateTime.now());
             String text = "Hello, MQ さん!: " + formatNowDate;
            message.write(text.getBytes("MS932"));

            MQPutMessageOptions pmo = new MQPutMessageOptions();
            pmo.options = CMQC.MQPMO_NO_SYNCPOINT;
            queue.put(message, pmo);
            System.out.println("Message sent successfully.");

            queue.close();
            qmgr.disconnect();

        } catch (MQException ex) {
            System.err.println("MQ Exception: " + ex.reasonCode + ", " + ex.getMessage());
            ex.printStackTrace();
        } catch (Exception ex) {
            System.err.println("Exception: " + ex.getMessage());
            ex.printStackTrace();
        }
    }
}

ローカルキューを確認

試しにJavaアプリからは2回実行してみました。

MQサーバ側で、すでに提供されているキューの中身を確認するコマンドを実施してみます。

>amqsgbr QL.A TSQMGR
   
Sample AMQSGBR0 (browse) start
TSQMGR
Messages for QL.A
1 <Hello, MQ さん!: 2024/03/12 18:22:56.433>
2 <Hello, MQ さん!: 2024/03/12 18:22:59.817>
no more messages
Sample AMQSGBR0 (browse) end

下記のプログラムだと、MQMDを含めてより詳しいメッセージの中身を確認することができます。

> amqsbcg QL.A TSQMGR

まずは、第一弾なので、今日はこんなところでオッケーでしょうか。