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

Nikita Sokolov :

I want to use acknowledge mode in delivering messages from ibm queue via JMS.

So, I configure context in this way:

 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();
    }

Here is special parameter:

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

In code logic I use message listener which processes messages:

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
                }

            }

        });

Now this code does not work: if database fails, message will be lost. We can not find it via JMS browsing. Why?

Shashi :

You are not using sessionMode parameter when creating context. As far as I know a context created without specifying sessionMode is same as AUTO_ACKNOWLEDGE where JMS client will automatically acknowledge message after it is delivered to application. So for your case you will need to use:

cf.createContext(JMSContext.CLIENT_ACKNOWLEDGE);

I tried and it works for me, meaning if message.acknowlege() is not called, the same message is delivered again.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=21255&siteId=1