0

I have a spring-boot application using the spring-boot AMQP library.

pom.xml :

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

How can I make it process and acknowledge a single message then gracefully exit ?

Can make it exit without acknowledge but cannot seem to work out how to acknowledge the message then exit !

Manse
  • 37,765
  • 10
  • 83
  • 108
  • So, you want to ack and process only one message? What if the queue has 100 messages? – Darshan Mehta Nov 08 '17 at 16:49
  • @DarshanMehta Yes i want to process a single message and exit even if the queue has 100 messages. – Manse Nov 08 '17 at 16:51
  • you can use similar approach as this one : https://stackoverflow.com/questions/41035454/how-to-stop-consuming-messages-with-rabbitlistener. Maybe add an `AtomicInteger` and stop consuming once the count reaches 1? As far as the ack is concerned, Spring will only send an ack if your `listener` method exits gracefully. If you call `stop()`, it won't ack and hence, the message will be available for other users to consume. – Darshan Mehta Nov 08 '17 at 16:55
  • @DarshanMehta perhaps i could increment the count at the end of processing the first message and then exit at the start of processing the second should the count reach my specified limit (of 1 in my case) – Manse Nov 08 '17 at 16:57
  • Exactly, `incrementAndGet()` is the method you would like to use with `AtomicInteger` and yes, incrementing the count in the end of the method and checking in the beginning is a good idea. I would use `@Value` to configure the number of messages the app needs to read before exiting. – Darshan Mehta Nov 08 '17 at 17:00
  • @DarshanMehta Thanks - stick that in an answer and i will mark it as accepted – Manse Nov 08 '17 at 17:42
  • I think it would be easier to use the `RabbitTemplate` instead. – Gary Russell Nov 08 '17 at 18:05
  • @ManseUK done.. – Darshan Mehta Nov 09 '17 at 09:38

2 Answers2

4

You can simply use one of the RabbitTemplate.receive() (or receiveAndConvert()) methods instead of using a listener container.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • So this would consumer a message based on request rather then listen for messages - nice idea – Manse Nov 09 '17 at 13:38
3

You can follow the below steps:

  • Use Spring's RabbitListener as listener (Refer to this SO answer for the complete example)
  • Declare an AtomicInteger as counter in your listener class
  • Increment the counter once you listen to the message (i.e. listen method executes without any Exception). Spring will only send an ack when the method executes successfully
  • If the value of counter is more than 0 (or more than the configured threshold), stop listening by calling stop() method
  • Use @Value to configure the threshold and use incrementAndget() method to atomically increment the counter
Darshan Mehta
  • 30,102
  • 11
  • 68
  • 102