F. K.
F. K.

Reputation: 964

why jms Client acknowledge is not working

I am trying to retrieve messages from an ActiveMQ queue. I set the session to Session.CLIENT_ACKNOWLEDGE. When I receive the message from the server it is auto-acknowledged although I have not called acknowledge on the message. Below is sample code of what I am doing:

connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Destination destination = session.createQueue(queue);
consumer = session.createConsumer(destination);
connection.start();
Message message = consumer.receive(1);

The code snippet above works and I do get the message from the queue. The problem is that messages disappear from the queue although I have not acknowledged the message. Any pointers why this is happening. I have been debugging this issue almost all this afternoon with no luck. This is a Spring boot application.

I got the client_ack to work in jmsTemplate. Below is the code.

public Object retrieve() {
        return this.jmsTemplate.execute(session -> {
            session.recover();
            MessageConsumer consumer = session.createConsumer(
                    this.jmsTemplate.getDestinationResolver().resolveDestinationName(session, queue, false));
            try {
                Message received = consumer.receive(1);
                if (received != null) {
                    return this.messageConverter.fromMessage(received);
                }
            }
            catch (Exception e) {
                return null;
            }
            finally {
                consumer.close();
            }
            return null;
        }, true);
    }

The issue I am now seeing is that my app does not see these messages after it restarts. I tried running session.recover() but it is not making any difference. Thanks for your help.

The working code using jmsTemplate is as below:

public Object retrieve() {
        return this.jmsTemplate.execute(session -> {
            MessageConsumer consumer = session.createConsumer(
                    this.jmsTemplate.getDestinationResolver().resolveDestinationName(session, queue, false));
            try {
                Message received = consumer.receive(1);
                session.recover();
                if (received != null) {
                    return this.messageConverter.fromMessage(received);
                }
            }
            catch (Exception e) {
                return null;
            }
            finally {
                consumer.close();
            }
            return null;
        }, true);
    }

Upvotes: 0

Views: 2065

Answers (2)

Ken Cowrs
Ken Cowrs

Reputation: 11

This appears to be a problem with the springframework Constants class. It uses introspection to get the integer value of CLIENT_ACKNOWLEDGE but always return a value of 1, so session is always AUTO_ACKNOWLEDGE

Upvotes: 1

F. K.
F. K.

Reputation: 964

To anybody who might run into this issue, I did the following to resolve the issue:

  1. Set the session to non-transacted. This is the default and only option if you are using jmsTemplate. If you are creating your own consumer, you need to create the session as non-transacted when creating the jms connection
  2. If you are creating your own consumer, you need to set the session to CLIENT_ACKNOWLEDGE.
  3. Check the maximum number of redeliveries to the required value. This will differ depending on the product: ActiveMQ, IBM MQ, etc.
  4. call session.recover() after retrieving the message.

I updated the working code that is using jmsTemplate in the original post.

Upvotes: 0

Related Questions