0

I want to process an AMQP message then send it to another queue for further processing.

I'm using Spring integration DSL to archive it as below,

@Bean
public IntegrationFlow ocr(ConnectionFactory connectionFactory, AmqpTemplate amqpTemplate,
                           OCRService ocrService) {
    return IntegrationFlows.from(Amqp.inboundGateway(connectionFactory, NOTE_INCOMING_QUEUE)
            .concurrentConsumers(2))
            .transform(new JsonToObjectTransformer(Note.class))
            .handle(msg -> {
                // doing ocr here
                amqpTemplate.convertAndSend(NOTE_EXCHANGE, NOTE_OCRED_BINDING, note);
            })
            .get();
}

@Bean
public IntegrationFlow typeProcess(ConnectionFactory connectionFactory) {
    return IntegrationFlows.from(Amqp.inboundGateway(connectionFactory, NOTE_OCRED_QUEUE)
            .concurrentConsumers(4))
            .transform(new JsonToObjectTransformer(Note.class))
            .handle(msg -> {
                // doing some work for type processing
            }).get();
}

However I found that the message in NOTE_INCOMING_QUEUE queue still unacked when the new message is handling in type process phase. See below screenshot of rabbitmq management.

enter image description here

I'm wondering why the message in NOTE_INCOMING_QUEUE still unacked even though the handler already was executed successfully. Is it the design of spring integration amqp or something wrong in my code?

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
Kane
  • 8,035
  • 7
  • 46
  • 75

1 Answers1

1

Use Amqp.inboundAdapter() instead of the gateway - the gateway is waiting for a reply that will never arrive.

Gateways are for request/reply scenarios; channel adapters are for one-way scenarios.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Gary, do you mean `Amqp.inboundAdapter`? I tried to use `Amqp.inboundAdapter` instead of gateway, but the behavior still is unexpected. I set breakpoint in handler of `typeProcess`, the message in **incoming** queue still was unacked until the message was properly processed by handler of `typeProcess`. – Kane May 16 '17 at 08:41
  • Yes, sorry, I meant `inboundAdapter()`. I don't see how what you are describing can possibly happen, the container within the inbound adapter will automatically acknowledge the message (by default) when the thread returns to the container after executing the flow. Of course, if you have a breakpoint, it won't be ack'd until you release the thread. – Gary Russell May 16 '17 at 12:05
  • In my code snippet, I do have two inbound adapters and two handlers. Will different handlers use different threads to execute the flow? As you said, the msg will be acked after the thread returns. In my use case the msg firstly comes in `note.incoming` queue, the flow executed successfully then I sent another msg to queue `note.ocred`. I set the breakpoint in handler of queue `note.ocred` to pause the procession, why the msg in queue `note.incoming` still is unacked? – Kane May 16 '17 at 13:12
  • Yes, they will run on separate threads. I can't explain why you still have an un-acked message in the input queue; when the thread returns to the container it will be ack'd. I suggest you turn on DEBUG logging; if you still can't figure it out; post an example that shows the behavior. – Gary Russell May 16 '17 at 14:55
  • Gary, it's my fault. The breakpoint of second queue stopped entire JVM, which definitely also stopped the incoming msg to be acked. One more question, is there any more element way(comparing to directly call `amqpTemplate.convertAndSend()`) to send a message to another queue after processed msg from incoming queue? – Kane May 17 '17 at 08:38