javajmssolaceretry-logic

How to send NACK to Solace queue from Solace listener using JMS API?


Need your help to find the solution. Current implementation details:

SolConnectionFactory connectionFactory = SolJmsUtility.createConnectionFactory(); // for create connection factory using host , vpn,trust store,keystore with auth scheme AUTHENTICATION_SCHEME_CLIENT_CERTIFICATE
this.connection = connectionFactory.createConnection(); // connection creation
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); // session creation using client acknowledge

Using MessageListener to listen the queue

public class MyListener implements MessageListener 

    public void onMessage(Message message) // receive the message and process
    { 
        /* in this method validating the message (poison message) 
         * and publish to kafka, once receive the success message
         * from kafka acknowledge the message
         */
        message.acknowledge();
    }

Problem : If Kafka broker went down how to do retry? We had a discussion with internal Solace team.

We assume that if client is not calling the message.acknowledge() Solace will do the retry but internal Solace team clarified that it is using windowing mechanism, so if subsequent message is acknowledge then previous message will also acknowledged and deleted.

Their suggestion is to send back the NACK (negative acknowledgment) for failed message then Solace can do retry that message. How to send the NACK using Java API?

What are the suggested value for Max_Un_Ack_Message and Max_Redeliver_Count?

Maven Dependency for Solace:

<dependency>
    <groupId>com.solacesystems</groupId>
    <artifactId>sol-jms</artifactId>
    <version>10.0.0</version>
</dependency>

Solution

  • If you're using the JMS API and you want to trigger a redelivery then you have a couple of options.

    You can use a transacted session. When processing a message is successful you acknowledge the message and commit() the javax.jms.Session. When processing is unsuccessful you call rollback() on the javax.jms.Session.

    Alternatively, you can use javax.jms.Session.recover(). Here's what the JavaDoc says:

    Stops message delivery in this session, and restarts message delivery with the oldest unacknowledged message.

    All consumers deliver messages in a serial order. Acknowledging a received message automatically acknowledges all messages that have been delivered to the client.

    Restarting a session causes it to take the following actions:

    • Stop message delivery
    • Mark all messages that might have been delivered but not acknowledged as "redelivered"
    • Restart the delivery sequence including all unacknowledged messages that had been previously delivered. Redelivered messages do not have to be delivered in exactly their original delivery order.

    This, of course, assumes that the Solace JMS client actually implements the specified behavior here.