为什么 JMS 确认模式不能在 ibm mq 中正常工作?

Why does JMS acknowledge mode not work in wildly with ibm mq?

我想在通过 JMS 从 ibm 队列传递消息时使用确认模式。

所以,我这样配置上下文:

 private JMSContext createJmsContext() throws JMSException {
        JmsConnectionFactory cf;
        JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
        cf = ff.createConnectionFactory();
        cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, props.getProperty(Q_HOST));
        cf.setIntProperty(WMQConstants.WMQ_PORT, Integer.valueOf(props.getProperty(Q_PORT)));
        cf.setStringProperty(WMQConstants.WMQ_CHANNEL, props.getProperty(Q_CHANNEL));
        cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
        cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, props.getProperty(Q_MANAGER));
        cf.setStringProperty(WMQConstants.WMQ_APPLICATIONNAME, "JmsPutGet (JMS)");
        cf.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
        cf.setIntProperty(WMQConstants.ACKNOWLEDGE_MODE, WMQConstants.CLIENT_ACKNOWLEDGE);
        return cf.createContext();
    }

这里是特殊参数:

cf.setIntProperty(WMQConstants.ACKNOWLEDGE_MODE, WMQConstants.CLIENT_ACKNOWLEDGE);

在代码逻辑中,我使用处理消息的消息侦听器:

consumer.setMessageListener(message -> {

            try {
                // business logic
                message.acknowledge();
            } catch (Throwable e) {

                try {
                    // saving unsuccessful message to special database
                } catch (Throwable e) {
                    // if database does not work, we want message to return back to queue and try process it again when database will work
                    sleep(60_000); // to prevent too many process requests, there is only one working thread, so we can pause it
                }

            }

        });

现在这段代码不起作用:如果数据库出现故障,消息将丢失。我们无法通过 JMS 浏览找到它。为什么?

您在创建上下文时没有使用 sessionMode 参数。据我所知,在未指定 sessionMode 的情况下创建的上下文与 AUTO_ACKNOWLEDGE 相同,其中 JMS 客户端将在消息传递到应用程序后自动确认消息。因此,对于您的情况,您需要使用:

cf.createContext(JMSContext.CLIENT_ACKNOWLEDGE);

我试过了,它对我有用,这意味着如果 message.acknowlege() 没有被调用,同样的消息会再次发送。