1
votes

I have a spring application where we are publishing and listening messages from Rabbitmq using spring-amqp. I want to modify my Rabbitmq message if my listener throws an exception. When the listener throws an exception, it will be retied using a recoverer and retry handler. I am modifying the message in a catch block which is present in the listener class. Once the message is modified, I am throwing an exception, so that the message will be retried again after some fixed duration of time.

Here is the code which I am using to modifying a message.

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

            if(message.getMessageProperties().getHeaders().get("x-retried-header") != null)//self defined header
            {
                throw new MyException();
            }
            else
            {
                //some logic
            }
        }
        catch(MyException e)
        {
            MyClass myObject = new MyClass();
            myObject.setMessage("Hello Message Is Being Retried");
            MessageProperties properties = message.getMessageProperties();
            properties.setHeader("x-retried-header", 1);
            message = MessageBuilder.withBody(myObject.toByteArray()).andProperties(properties).build();
            throw new Exception();

        }
    }

When my recoverer received RabbitMq message, the body of the message is not changed whereas, the headers which I have added to the modified message are getting reflecting properly. I can also handle or modify my message in a rabbit handler, but I don't want to change anything in recoverer and retry handler, as those were used by other listeners too. Can someone please assist me with this problem. Why I am receiving the original message body instead of a modified message body? Is Spring-amqp is using any cloned object here?

Is there any other approach to modified my RabbitMq message body using spring-amqp when a listener throws an exception?

1

1 Answers

1
votes

You cannot modify the message body once it is sent to the RabbitMQ Queue.

If it is accepted by the consumer, i.e. on no error, it deletes the Message from the Queue. If it is not consumed properly by Consumer, i.e. on error, RabbitMQ re-queues the Message (if auto-re-queue is enabled).

Workaround:

You can inform RabbitMQ as message was consumed successfully, but You can clone the message and re-send the Message as New Message.

Hope, it helps.