0
votes

I am doing the following steps:

  1. MessageListener receives the message from queue Q1
  2. Validate the message
  3. If validation fails, call channel.basicReject() and move it to dead letter queue
  4. Else, lets say, email server fails. I call channel.basicReject() with requeue true and throw an exception. It goes to retry template and after maxAttempts, is recovered(RepublishMessageRecoverer) and goes to dead letter queue.

But it does not remove the message from Q1.

public void onMessage(Message message, Channel channel) throws Exception {
        try {
            validateMessage();

            processMessage(message);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        }
        catch (DataValidationException ex){
            channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);

        }
        catch(DownstreamAppException ex) {
            channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
            throw ex;
        }
    }

    void validMessage() {
        ..
        throw new DataValidationException();
    }

    void processMessage() {

        ...
        throw new DownstreamAppException();
    }

I do not want to requeue messages that failed validation, but want to requeue those that were not processed because of some downstream app failure for retries.

A couple of questions: 1. If I don't throw exception in catch of DownstreamAppException, message does not go throw retryTemplate and recoverer. Is it because requeuing a rejected message is a new message?

  1. Why is the message not removed from Q1 ? and how can I fix it ?

Thanks

1

1 Answers

0
votes

You are responsible for acking when using manual acks (regardless of retry). If your code never acks, the message will (eventually) be requeued; but you don't have access to the channel in the recoverer.

The real question is why are you using manual acks and a ChannelAwareMessageListener? Your use case is straightforward. Using AUTO ackmode, the container will ack the message on success and reject it on any exception.

Since the recoverer republishes the message, that is considered success and the message will be ack'd by the container.

To selectively retry/requeue, you will need a customized error handler see this answer for more information.