You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SoapUI中MQQueueConnection读取JMS队列的技术问题咨询

解决SoapUI中JMS读取最新消息及超时阻塞问题

我来帮你搞定这两个棘手的问题,下面结合你的场景给出修改后的代码和详细解释:

问题1:读取队列最新消息

默认的MQQueueReceiver是按FIFO顺序读取最早的消息,要拿到队列里的最新消息,我们可以通过**消息浏览器(QueueBrowser)**遍历队列,定位到最后一条消息的ID,再通过这个ID精准接收这条最新消息,确保拿到队列最末尾的内容。

问题2:设置超时避免SoapUI挂起

你原来的代码里receive(1000000)设置了1000秒的超时,这跟无限阻塞没区别。我们需要把超时时间改短(比如5秒),同时在receive返回null(无消息或超时)时做针对性处理,避免空指针异常和程序挂死。


修改后的完整Groovy代码

import com.eviware.soapui.impl.wsdl.submit.transports.jms.JMSConnectionHolder
import com.eviware.soapui.impl.wsdl.submit.transports.jms.util.HermesUtils
import com.eviware.soapui.impl.wsdl.submit.transports.jms.JMSEndpoint
import hermes.Hermes
import javax.jms.*
import javax.jms.JMSException;
import javax.jms.Session;
import com.ibm.jms.JMSMessage;
import com.ibm.jms.JMSTextMessage;
import com.ibm.mq.jms.JMSC;
import com.ibm.mq.jms.MQQueue;
import com.ibm.mq.jms.MQQueueConnection;
import com.ibm.mq.jms.MQQueueConnectionFactory;
import com.ibm.mq.jms.MQQueueReceiver;
import com.ibm.mq.jms.MQQueueSender;
import com.ibm.mq.jms.MQQueueSession;

// 初始化接收消息的属性
context.testCase.testSteps["Properties"].setPropertyValue("receivedMessage","")

try {
    MQQueueConnectionFactory cf = new MQQueueConnectionFactory();
    // MQ连接配置
    cf.setHostName("agdevesb01");
    cf.setPort(14141);
    cf.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP); // 用常量替代硬编码,更清晰
    cf.setQueueManager("AGDEV1T1");
    cf.setChannel("CLIENTS.CARRIER");

    MQQueueConnection connection = (MQQueueConnection) cf.createQueueConnection();
    MQQueueSession session = (MQQueueSession) connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    MQQueue queue = (MQQueue) session.createQueue("queue:///QUEUE_NAME");

    // 启动连接
    connection.start();

    // ========== 解决问题1:获取最新消息 ==========
    String latestMessageId = null;
    QueueBrowser browser = session.createBrowser(queue);
    Enumeration msgEnum = browser.getEnumeration();
    
    // 遍历所有消息,记录最后一条的MessageID
    while (msgEnum.hasMoreElements()) {
        JMSMessage msg = (JMSMessage) msgEnum.nextElement();
        latestMessageId = msg.getJMSMessageID();
    }
    browser.close(); // 关闭浏览器

    JMSMessage receivedMessage = null;
    if (latestMessageId != null) {
        // 通过MessageID精准接收最新消息
        MQQueueReceiver receiver = (MQQueueReceiver) session.createReceiver(queue, "JMSMessageID='" + latestMessageId + "'");
        // ========== 解决问题2:设置5秒超时 ==========
        receivedMessage = (JMSMessage) receiver.receive(5000);
        receiver.close();
    }

    // 处理接收结果
    if (receivedMessage != null) {
        log.info "Received latest message: " + receivedMessage
        context.testCase.testSteps["Properties"].setPropertyValue("receivedMessage", receivedMessage.toString())
    } else {
        log.info "No messages found in queue or timeout reached"
        context.testCase.testSteps["Properties"].setPropertyValue("receivedMessage", "NO_MESSAGE")
    }

    // 关闭资源
    session.close();
    connection.close();
    log.info "SUCCESS"
} catch (JMSException jmsex) {
    log.error "JMS Exception occurred: " + jmsex.getMessage(), jmsex
} catch (Exception ex) {
    log.error "Unexpected error occurred: " + ex.getMessage(), ex
}

关键修改点说明

  1. 获取最新消息

    • 用QueueBrowser遍历队列所有消息,记录最后一条的JMSMessageID
    • 创建接收者时使用消息选择器"JMSMessageID='" + latestMessageId + "'",精准定位最新消息
    • 注:如果队列消息量极大,遍历可能有性能损耗,这种场景可以考虑调整MQ队列属性或采用其他消费模式,常规场景下这个方案足够好用
  2. 超时与阻塞处理

    • 将receive超时时间改为5000(5秒),你可以根据实际业务需求调整这个数值
    • 增加了receivedMessage为null的判断,避免空指针异常,同时输出明确日志
    • 队列无消息或超时后,程序会正常收尾,不会导致SoapUI挂起
  3. 其他优化

    • 用JMSC.MQJMS_TP_CLIENT_MQ_TCPIP常量替代硬编码的1,提升代码可读性
    • 异常日志改用log.error并打印堆栈,方便排查问题
    • 移除了无用的MQQueueSender代码,简化逻辑

内容的提问来源于stack exchange,提问作者Sagar Wadhwa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:43:49