[英]How to remove message from queue by condition?
我從IBM MQ獲得消息。 如何按條件從隊列中刪除消息?
我試圖設置gmo.options = CMQC.MQGMO_MSG_UNDER_CURSOR; 但這對我沒有幫助。
MQQueue queue = queueManager.accessQueue(e.getIbmQueue().trim(), CMQC.MQOO_INPUT_SHARED | CMQC.MQOO_FAIL_IF_QUIESCING | CMQC.MQOO_INQUIRE, null, null, null);
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options = MQGMO_ALL_MSGS_AVAILABLE | MQGMO_WAIT | MQGMO_PROPERTIES_AS_Q_DEF | MQGMO_FAIL_IF_QUIESCING | MQOO_INPUT_AS_Q_DEF | MQGMO_SYNCPOINT;
gmo.matchOptions = MQMO_MATCH_CORREL_ID;
gmo.waitInterval = 50000;
byte[] body = null;
while (true) {
try {
queue.get(msg, gmo);
body = new byte[msg.getMessageLength()];
String businessIdFromIbm = msg.getStringProperty("usr.uuid");
if (businessIdFromIbm.equals("123")) {
//delete message
}
msg.clearMessage();
}
上面示例中的queue.get調用是破壞性的get-在該調用期間,該消息將從隊列中邏輯刪除。
您正在使用同步點,因此您將需要調用queuemanager.commit()來完成工作單元(或者,如果您調用queuemanager.disconnect(),同步點將被自動提交)。
MQGMO_MSG_UNDER_CURSOR僅在您打開瀏覽隊列(CMQC.MQOO_BROWSE)並針對該隊列發出了至少一次瀏覽以使您的應用程序在其瀏覽光標下具有有效消息的情況下才有效。
如果要瀏覽消息,然后使用第二個隊列將其刪除。get要在瀏覽光標下刪除該消息,則第一個queue.get將需要在gmo.options上指定MQGMO_BROWSE_FIRST或MQGMO_BROWSE_NEXT。 然后第二個queue.get將需要提供MQGMO_MSG_UNDER_CURSOR作為不設置任何瀏覽選項的匹配選項,以破壞性地刪除瀏覽的消息。
MQQueue queue = queueManager.accessQueue(e.getIbmQueue().trim(), CMQC.MQOO_INPUT_SHARED | CMQC.MQOO_BROWSE | CMQC.MQOO_FAIL_IF_QUIESCING | CMQC.MQOO_INQUIRE, null, null, null);
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options = CMQC.MQGMO_ALL_MSGS_AVAILABLE | CMQC.MQGMO_WAIT | CMQC.MQGMO_PROPERTIES_AS_Q_DEF | CMQC.MQGMO_FAIL_IF_QUIESCING | CMQC.MQGMO_BROWSE_NEXT;
gmo.matchOptions = MQMO_MATCH_CORREL_ID;
gmo.waitInterval = 50000;
byte[] body = null;
while (true) {
try {
queue.get(msg, gmo);
body = new byte[msg.getMessageLength()];
String businessIdFromIbm = msg.getStringProperty("usr.uuid");
if (businessIdFromIbm.equals("123")) {
//delete message
MQGetMessageOptions gmo2 = new MQGetMessageOptions();
gmo2.options = CMQC.MQGMO_MSG_UNDER_CURSOR | CMQC.MQGMO_FAIL_IF_QUIESCING | CMQC.MQGMO_SYNCPOINT;
queue.get(msg, gmo2);
// Be prepared to handle the case where the message has been removed by another application (or expired) and so you receive MQRC 2033
queueManager.commit();
}
msg.clearMessage();
}
另一種方法(如果出現問題,則需要較少的隊列管理器調用)是使用JMS API到MQ,並在usr.uuid上使用選擇器,這樣僅將具有此設置的消息設置為123返回到應用程序。 請參閱https://www.ibm.com/support/knowledgecenter/zh-CN/SSFKSJ_9.1.0/com.ibm.mq.dev.doc/q031980_.htm
您可以在此處閱讀我的完整博客文章。 這是讀者的摘要版本。
關於基於MQ / JMS消息的過濾存在誤解。 有人認為IBM MQ隊列管理器對JMS應用程序做了一些特殊的事情,而對於普通Java或C / C ++ / C#/ COBOL應用程序則沒有。 這不是真的。 從知識中心閱讀JMS中“ 消息選擇器”的第一段,以獲取更多信息。 注意:對於C / C ++ / C#/ COBOL應用程序,他們可以使用MQOD結構中的SelectionString執行消息選擇。
我為POJO MQ應用程序創建了一個Message Selector類。
這是MQTest12MS的一個片段,向您展示如何使用MessageSelector類。
ms = new MessageSelector(qMgr);
ms.openQueue(inputQName);
ms.setFilter("SomeNum", MessageSelector.Conditions.GREATER_THAN_EQUAL, 123);
while (true)
{
receiveMsg = ms.getMessage(startAtBeginning);
// got the message, now go and do something with it.
// set flag to continue rather than restart at the beginning.
startAtBeginning = false;
}
ms.closeQueue();
這是MessageSelector類。
import java.io.IOException;
import com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
/**
* Class Name
* MessageSelector
*
* Description
* This java class will retrieve messages from a queue based on a filter.
*
* @author Roger Lacroix
* @version 1.0.0
* @license Apache 2 License
*/
public class MessageSelector
{
public enum Conditions
{
EQUAL, NOT_EQUAL, LESS_THAN, LESS_THAN_EQUAL, GREATER_THAN, GREATER_THAN_EQUAL;
}
private MQQueueManager qMgr = null;
private MQQueue inQ = null;
private String filterName = null;
private Conditions filterCondition;
private Object filterValue = null;
/**
* The constructor
* @param qMgr - must have a valid/active connection to the queue manager
*/
public MessageSelector(MQQueueManager qMgr)
{
super();
this.qMgr = qMgr;
}
/**
* Open the queue for both browsing and destructive gets.
* @param qName
* @throws MQException
*/
public void openQueue(String qName) throws MQException
{
inQ = qMgr.accessQueue(qName, CMQC.MQOO_INQUIRE + CMQC.MQOO_BROWSE + CMQC.MQOO_FAIL_IF_QUIESCING + CMQC.MQOO_INPUT_SHARED);
}
/**
* Close the queue.
* @throws MQException
*/
public void closeQueue() throws MQException
{
if (inQ != null)
inQ.close();
}
/**
* Set the filter name, condition and value.
* @param name
* @param condition
* @param value
* @throws IllegalArgumentException
*/
public void setFilter(String name, Conditions condition, Object value) throws IllegalArgumentException
{
if (name == null)
throw new IllegalArgumentException("Filter name cannot be null.");
else if ("".equals(name))
throw new IllegalArgumentException("Filter name cannot be blank.");
else if (value == null)
throw new IllegalArgumentException("Filter value cannot be null.");
if ( (value instanceof String) || (value instanceof Boolean) ||
(value instanceof Byte) || (value instanceof Byte[]) )
{
if ( (Conditions.EQUAL != condition) && (Conditions.NOT_EQUAL != condition) )
{
throw new IllegalArgumentException("Filter condition can only be EQUAL or NOT_EQUAL.");
}
}
else if ( (value instanceof Integer) || (value instanceof Long) ||
(value instanceof Double) || (value instanceof Float) )
{
if ( (Conditions.EQUAL != condition) && (Conditions.NOT_EQUAL != condition) &&
(Conditions.LESS_THAN != condition) && (Conditions.LESS_THAN_EQUAL != condition) &&
(Conditions.GREATER_THAN != condition) && (Conditions.GREATER_THAN_EQUAL != condition) )
{
throw new IllegalArgumentException("Filter condition must be one of the following: EQUAL, NOT_EQUAL, LESS_THAN, LESS_THAN_EQUAL, GREATER_THAN, GREATER_THAN_EQUAL.");
}
}
else
{
throw new IllegalArgumentException("Unknown Object type for Filter value.");
}
/**
* Pass the checks, save the values
*/
this.filterName = name;
this.filterCondition = condition;
this.filterValue = value;
}
/**
* Retrieve the next matching message from the queue.
* @param reset - Start over from the beginning of the queue.
* @return
* @throws MQException
* @throws IOException
*/
public MQMessage getMessage(boolean reset) throws MQException, IOException
{
MQGetMessageOptions gmo = new MQGetMessageOptions();
if (reset)
gmo.options = CMQC.MQGMO_BROWSE_FIRST + CMQC.MQGMO_NO_WAIT + CMQC.MQGMO_FAIL_IF_QUIESCING;
else
gmo.options = CMQC.MQGMO_BROWSE_NEXT + CMQC.MQGMO_NO_WAIT + CMQC.MQGMO_FAIL_IF_QUIESCING;
MQMessage getMsg = null;
while (true)
{
getMsg = new MQMessage();
inQ.get(getMsg, gmo);
if (performConditionalTest(getMsg))
{
deleteMessage();
break;
}
gmo.options = CMQC.MQGMO_BROWSE_NEXT + CMQC.MQGMO_NO_WAIT + CMQC.MQGMO_FAIL_IF_QUIESCING;
}
return getMsg;
}
/**
* Handle the conditional testing of the value.
* @param getMsg
* @return true/false
*/
private boolean performConditionalTest(MQMessage getMsg)
{
boolean flag = false;
try
{
if (filterValue instanceof String)
{
String value = getMsg.getStringProperty(filterName);
if (value != null)
{
if ( (Conditions.EQUAL == filterCondition) && (((String)filterValue).equals(value)) )
flag = true;
else if ( (Conditions.NOT_EQUAL == filterCondition) && (!(((String)filterValue).equals(value))) )
flag = true;
}
}
else if (filterValue instanceof Integer)
{
int value = getMsg.getIntProperty(filterName);
if ( (Conditions.EQUAL == filterCondition) && (value == (Integer)filterValue) )
flag = true;
else if ( (Conditions.NOT_EQUAL == filterCondition) && (value != (Integer)filterValue) )
flag = true;
else if ( (Conditions.LESS_THAN == filterCondition) && (value < (Integer)filterValue) )
flag = true;
else if ( (Conditions.LESS_THAN_EQUAL == filterCondition) && (value <= (Integer)filterValue) )
flag = true;
else if ( (Conditions.GREATER_THAN == filterCondition) && (value > (Integer)filterValue) )
flag = true;
else if ( (Conditions.GREATER_THAN_EQUAL == filterCondition) && (value >= (Integer)filterValue) )
flag = true;
}
else if (filterValue instanceof Long)
{
long value = getMsg.getLongProperty(filterName);
if ( (Conditions.EQUAL == filterCondition) && (value == (Long)filterValue) )
flag = true;
else if ( (Conditions.NOT_EQUAL == filterCondition) && (value != (Long)filterValue) )
flag = true;
else if ( (Conditions.LESS_THAN == filterCondition) && (value < (Long)filterValue) )
flag = true;
else if ( (Conditions.LESS_THAN_EQUAL == filterCondition) && (value <= (Long)filterValue) )
flag = true;
else if ( (Conditions.GREATER_THAN == filterCondition) && (value > (Long)filterValue) )
flag = true;
else if ( (Conditions.GREATER_THAN_EQUAL == filterCondition) && (value >= (Long)filterValue) )
flag = true;
}
else if (filterValue instanceof Double)
{
double value = getMsg.getDoubleProperty(filterName);
if ( (Conditions.EQUAL == filterCondition) && (value == (Double)filterValue) )
flag = true;
else if ( (Conditions.NOT_EQUAL == filterCondition) && (value != (Double)filterValue) )
flag = true;
else if ( (Conditions.LESS_THAN == filterCondition) && (value < (Double)filterValue) )
flag = true;
else if ( (Conditions.LESS_THAN_EQUAL == filterCondition) && (value <= (Double)filterValue) )
flag = true;
else if ( (Conditions.GREATER_THAN == filterCondition) && (value > (Double)filterValue) )
flag = true;
else if ( (Conditions.GREATER_THAN_EQUAL == filterCondition) && (value >= (Double)filterValue) )
flag = true;
}
else if (filterValue instanceof Float)
{
float value = getMsg.getFloatProperty(filterName);
if ( (Conditions.EQUAL == filterCondition) && (value == (Float)filterValue) )
flag = true;
else if ( (Conditions.NOT_EQUAL == filterCondition) && (value != (Float)filterValue) )
flag = true;
else if ( (Conditions.LESS_THAN == filterCondition) && (value < (Float)filterValue) )
flag = true;
else if ( (Conditions.LESS_THAN_EQUAL == filterCondition) && (value <= (Float)filterValue) )
flag = true;
else if ( (Conditions.GREATER_THAN == filterCondition) && (value > (Float)filterValue) )
flag = true;
else if ( (Conditions.GREATER_THAN_EQUAL == filterCondition) && (value >= (Float)filterValue) )
flag = true;
}
else if (filterValue instanceof Boolean)
{
Boolean value = getMsg.getBooleanProperty(filterName);
if ( (value != null) && ((Boolean)filterValue == value) )
flag = true;
}
else if (filterValue instanceof Byte)
{
byte value = getMsg.getByteProperty(filterName);
if ((Byte)filterValue == value)
flag = true;
}
else if (filterValue instanceof Byte[])
{
byte[] value = getMsg.getBytesProperty(filterName);
if ( (value != null) && (java.util.Arrays.equals((byte[])filterValue, value)) )
flag = true;
}
}
catch (Exception e)
{}
return flag;
}
/**
* Delete the message that the cursor is pointing to.
*/
private void deleteMessage()
{
MQMessage deleteMsg = new MQMessage();
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options = CMQC.MQGMO_MSG_UNDER_CURSOR + CMQC.MQGMO_NO_WAIT + CMQC.MQGMO_FAIL_IF_QUIESCING + CMQC.MQGMO_ACCEPT_TRUNCATED_MSG;
/**
* don't need it - because we already have the message
* just delete it.
*/
try
{
inQ.get(deleteMsg, gmo, 1); // only get 1 byte - who cares right!!
}
catch (MQException e)
{}
}
}
更新2019/06/25:我更新了MessageSelector類的setFilter方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.