こんにちは、IBM MQ を使用してメッセージ リスナーを作成する方法を知っている人はいますか? JMS 仕様を使用してそれを行う方法は知っていますが、IBM MQ でそれを行う方法がわかりません。リンクやポインタは大歓迎です。
7 に答える
以前のレスポンダーが指摘したように WMQ Java API がありますが、WMQ は JMS もサポートしているため、そこから始めるためのリソースがいくつかあります。
次の記事をご覧ください: IBM WebSphere Developer Technical Journal: Running a standalone Java application on WebSphere MQ V6.0
また、完全な WMQ クライアントをインストールしており、jar を入手しただけではない場合は、多くのサンプル コードがインストールされています。デフォルトでは、これらはプラットフォームに応じて C:\Program Files\IBM\WebSphere MQ\tools\jms または /opt/mqm/samp にあります。
WMQ クライアントのインストール メディアが必要な場合は、ここから入手してください。これは WMQ v7 クライアントであり、v6 クライアントではないことに注意してください。v6 QMgr と互換性がありますが、v6 は 2011 年 9 月の時点でサポートが終了しているため、v7 クライアントと、可能であれば v7 QMgr で新しい開発を行う必要があります。両方の側が v7 である場合、利用可能な機能とパフォーマンスの強化が多数あります。
必要な場合は、ここで製品マニュアルを入手できます。
最後に、JMS 例外が発生したときに、リンクされた例外を出力するようにしてください。これは WMQ の問題ではなく、JMS の問題です。Sun は、JMS 例外用に複数レベルのデータ構造を提供しており、実際に興味深い部分はネストされたレベルにあることがよくあります。これは大したことではなく、数行で実装できます。
try {
.
. code that might throw a JMSException
.
} catch (JMSException je) {
System.err.println("caught "+je);
Exception e = je.getLinkedException();
if (e != null) {
System.err.println("linked exception: "+e);
} else {
System.err.println("No linked exception found.");
}
}
これは、JMS エラーとトランスポート エラーの違いを判断するのに役立ちます。たとえば、JMS セキュリティ エラーは WMQ 2035、JSSE 構成、またはアプリがファイル システム内の何かにアクセスできない可能性があります。これらのうちの 1 つだけが、WMQ エラー ログを掘り下げるのに多くの時間を費やす価値があり、リンクされた例外を出力することによってのみ、それがその例外であるかどうかを判断できます。
IBM ヘルプを参照してください: WebSphere MQ ベース Java アプリケーションの作成
IBM には、キューと対話するための API があります。サンプルは次のとおりです。
import com.ibm.mq.*; // Include the WebSphere MQ classes for Java package
public class MQSample
{
private String qManager = "your_Q_manager"; // define name of queue
// manager to connect to.
private MQQueueManager qMgr; // define a queue manager
// object
public static void main(String args[]) {
new MQSample();
}
public MQSample() {
try {
// Create a connection to the queue manager
qMgr = new MQQueueManager(qManager);
// Set up the options on the queue we wish to open...
// Note. All WebSphere MQ Options are prefixed with MQC in Java.
int openOptions = MQC.MQOO_INPUT_AS_Q_DEF |
MQC.MQOO_OUTPUT ;
// Now specify the queue that we wish to open,
// and the open options...
MQQueue system_default_local_queue =
qMgr.accessQueue("SYSTEM.DEFAULT.LOCAL.QUEUE",
openOptions);
// Define a simple WebSphere MQ message, and write some text in UTF format..
MQMessage hello_world = new MQMessage();
hello_world.writeUTF("Hello World!");
// specify the message options...
MQPutMessageOptions pmo = new MQPutMessageOptions(); // accept the // defaults,
// same as MQPMO_DEFAULT
// put the message on the queue
system_default_local_queue.put(hello_world,pmo);
// get the message back again...
// First define a WebSphere MQ message buffer to receive the message into..
MQMessage retrievedMessage = new MQMessage();
retrievedMessage.messageId = hello_world.messageId;
// Set the get message options...
MQGetMessageOptions gmo = new MQGetMessageOptions(); // accept the defaults
// same as MQGMO_DEFAULT
// get the message off the queue...
system_default_local_queue.get(retrievedMessage, gmo);
// And prove we have the message by displaying the UTF message text
String msgText = retrievedMessage.readUTF();
System.out.println("The message is: " + msgText);
// Close the queue...
system_default_local_queue.close();
// Disconnect from the queue manager
qMgr.disconnect();
}
// If an error has occurred in the above, try to identify what went wrong
// Was it a WebSphere MQ error?
catch (MQException ex)
{
System.out.println("A WebSphere MQ error occurred : Completion code " +
ex.completionCode + " Reason code " + ex.reasonCode);
}
// Was it a Java buffer space error?
catch (java.io.IOException ex)
{
System.out.println("An error occurred whilst writing to the message buffer: " + ex);
}
}
} // end of sample
IBM jar がベース Maven リポジトリーにあるかどうかはわかりません。過去に、ローカルの IBM インストールからそれらを抽出し、ローカルの SVN リポジトリーに配置する必要があったことを知っています。私は次の瓶を使用しています:
<dependency>
<groupId>com.ibm</groupId>
<artifactId>com.ibm.mq</artifactId>
<version>5.3.00</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.ibm</groupId>
<artifactId>com.ibm.mq.pcf</artifactId>
<version>5.3.00</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.ibm</groupId>
<artifactId>com.ibm.mqbind</artifactId>
<version>5.3.00</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.ibm</groupId>
<artifactId>com.ibm.mqjms</artifactId>
<version>5.3.00</version>
<scope>compile</scope>
</dependency>
上記のサンプルをご覧ください。
特にラインで
MQGetMessageOptions gmo = new MQGetMessageOptions();
system_default_local_queue.get(retrievedMessage, gmo);
MQRC_NO_MSG_AVAILABLE例外をスローする前に、指定された時間待機するようにgetを構成できます。または、永遠に待つことができます。
gmo.waitInterval= qTimeout;
gmo.options = MQC.MQGMO_WAIT
したがって、新しいメッセージを探し続けるスレッドを作成して、それらをハンドラーに渡すことができます。取得と配置は、同じスレッドまたはアプリケーションである必要はありません。
これがあなたの質問に答えるのに役立つことを願っています。
念のため、誰かが私のように MQ Listener の stackoverflow をグーグルで検索する場合に備えて... JMS の実現による答えではないかもしれませんが、これは私が探していたものです。このようなもの:
MQQueueConnectionFactory cf = new MQQueueConnectionFactory();
MQQueueConnection conn = (MQQueueConnection)cf.createQueueConnection();
MQQueueSession session = (MQQueueSession)conn.createSession(false, 1);
Queue queue = session.createQueue("QUEUE");
MQQueueReceiver receiver = (MQQueueReceiver)session.createReceiver(queue);
receiver.setMessageListener(new YourListener());
conn.start();
YourListener は MessageListener インターフェイスを実装する必要があり、メッセージを onMessage(Message msg) メソッドで受信します。
次のように指定できるメッセージを取得する前のループで
gmo.options = MQC.MQGMO_WAIT
gmo.waitInterval = MQConstants.MQWI_UNLIMITED;
これにより、キューにメッセージが存在するまでループが待機します。私には、それは似ていますMessageListerner
既存の回答に加えて重要な点: JMS はMessageListener
、非同期コールバックとしてメッセージを受信できるクラスを提供します。
ネイティブ API には同等の機能がありません。必要に応じて繰り返し呼び出す必要がありget(...)
ます。