1
@EnableRabbit
@Service
public class RabbitMqListenerWithReply {


@Autowired
RabbitTemplate rabbitTemplate;

@Value("${test.rabbitmq.exchange}")
private String rabbitMQExchange;


@Value("${test.rabbitmq.routingkey}")
private String rabbitMQRoutingKey;

@RabbitListener(queues = "${test.rabbitmq.queue}")
public void receiveMessage(String message, Channel channel, 
@Header(AmqpHeaders.DELIVERY_TAG)long tag) throws IOException {
    System.out.println(message.toString());
    channel.basicAck(tag, false);
    System.out.println("Ackd"); 
    
}
}

I am trying to implement a listener which acknowledge the message after I consume it, however the console would return this error so can someone guide me on where I could have went wrong.

This is the error that I am getting right now whenever I run the publisher to publish the message to the exchange.

2022-01-03 09:35:33.192 ERROR 27280 --- [ 127.0.0.1:5672] o.s.a.r.c.CachingConnectionFactory       : Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - unknown delivery tag 1, class-id=60, method-id=80)

2022-01-03 09:35:34.208  INFO 27280 --- [ntContainer#0-1] o.s.a.r.l.SimpleMessageListenerContainer : Restarting Consumer@52d7ab79: tags=[[amq.ctag-0pIM_-TROTIxXRsAJpmOrw]], channel=Cached Rabbit Channel: AMQChannel(amqp://guest@127.0.0.1:5672/,1), conn: Proxy@71369e1a Shared Rabbit Connection: SimpleConnection@60b616c8 [delegate=amqp://guest@127.0.0.1:5672/, localPort= 57660], acknowledgeMode=AUTO local queue size=0

This is how I am publishing my message at the moment.

@RestController
@RequestMapping("api/test")
public class RestAPIController {
@Autowired
RabbitTemplate rabbitTemplate;

@Value("${test.rabbitmq.exchange}")
private String rabbitMQExchange;

@Value("${test.rabbitmq.routingkey}")
private String rabbitMQRoutingKey;

@Value("${test.rabbitmq.queue}")
private String rabbitMQQueue;



@GetMapping("{message}")
public String testAPI(@PathVariable("message") String message) {
    System.out.println("Message sent: " + message);
    rabbitTemplate.convertAndSend(rabbitMQExchange, rabbitMQRoutingKey , message);
    return "The message was sent";
}

}

1 Answers1

2

@RabbitListener use AUTO-ACK by default.

The container acknowledges the message automatically, unless the MessageListener throws an exception.

So if you ack once in listener, the framework will ack once, and repeating ack causes this exception.

Try:

@RabbitListener(queues = "xxx", ackMode = "MANUAL")
zysaaa
  • 1,777
  • 2
  • 8
  • 19
  • Thanks for the clarifications on the error, sorry if I may clarify further. Would I be required to use : channel.basicConsume to properly acknowledge the message after using channel.basicAck – Back2Basics Jan 03 '22 at 03:34
  • The listener container is already a consumer. You can not use ```basicConsume``` in the listener. You can take a look at this quesition: [link](https://stackoverflow.com/a/38775174/9690075) – zysaaa Jan 03 '22 at 03:54
  • Hi Zysaaa, I kinda understand what you meant when you mention that the container is already a consumer. I have visited the link which you posted, in my case am I using my channel.basicAck wrongly to acknowledge the messages? – Back2Basics Jan 03 '22 at 06:17
  • If you set ackMode = "AUTO"(which is by default), you don't have to call```channel.basicAck``` in your listener method. If you want to manually ack or uack message, then the current approach is correct, you only need to set the ackMode = MANUAL of the current listener to avoid double ack. – zysaaa Jan 03 '22 at 06:36
  • I see, in that case how can I verify that my message has already been manually acknowledged using my code snippets? Thanks in advance for the advise Zysaaa, if you happened to have any Rabbitmq Tutorial I would gladly be happy to join it to enhance my knowledge of it. – Back2Basics Jan 03 '22 at 06:46
  • What do you mean by ```message has already been manually acknowledged```. I think official [Tutorials](https://www.rabbitmq.com/getstarted.html) and [Spring-Amqp-Doc](https://docs.spring.io/spring-amqp/docs/current/reference/html/#introduction) is a good start – zysaaa Jan 03 '22 at 07:49
  • Thanks Zysaaa for the pointers I have figured out the reason of not using a consumer inside a consumer. Appreciate your help! – Back2Basics Jan 05 '22 at 01:57
  • Please consider [accept](https://stackoverflow.com/help/someone-answers) the answer if it helped you! – zysaaa Jan 05 '22 at 02:48
  • Opps totally forget about checking the tick right beside! – Back2Basics Jan 05 '22 at 02:57