Search code examples
spring-amqp

Spring AMQP Listener starts when autoStartup = false


Recently faced a weird issue with Spring AMQP @EventListener. Listener was declared like this, so autostartup was set to false

@RabbitListener(id = "MqMessageHandler", queues = "${rabbitMQ.in-queue-name}", autoStartup = "false")
public void receiveMessage(Message message) {

After application is fully initialized and i get a response from some other service, i'm manually starting the listener like this

MessageListenerContainer mqMessageHandler = registry.getListenerContainer(HANDLER_ID);
mqMessageHandler.start();

But it appears that listener is still starting on context initialization. Digging a bit in the code i found this piece of code inside RabbitListenerEndpointRegistry

    /**
     * Start the specified {@link MessageListenerContainer} if it should be started
     * on startup or when start is called explicitly after startup.
     * @param listenerContainer the container.
     * @see MessageListenerContainer#isAutoStartup()
     */
    private void startIfNecessary(MessageListenerContainer listenerContainer) {
        if (this.contextRefreshed || listenerContainer.isAutoStartup()) {
            listenerContainer.start();
        }
    }

That means that listener will be started once ContextRefreshed event is fired. I'd expect the condition to be this.contextRefreshed && listenerContainer.isAutoStartup() so && instead of || and then it should work as expected.

Does anybody knows if the condition is correct, and my assumptions are wrong? Spring AMQP version is 2.3.1 but the same i saw in 2.3.10

As a workaround for now i'm registering listener manually like this

        MessageListenerContainer mqMessageHandler = registry.getListenerContainer(HANDLER_ID);
        if (Objects.isNull(mqMessageHandler)) {
            SimpleRabbitListenerEndpoint endpoint = new SimpleRabbitListenerEndpoint();
            endpoint.setQueueNames(inQueueName);
            endpoint.setMessageListener(this.mqMessageHandler);
            endpoint.setId(HANDLER_ID);

            registry.registerListenerContainer(endpoint, factory);
            mqMessageHandler = registry.getListenerContainer(HANDLER_ID);
        }
        mqMessageHandler.start();

Solution

  • So after investigation it was found that:

    1. Spring AMQP works as expected and didn't start listener on startup as expected.
    2. In my case it was an issue that context.refresh() and context.start() was called manually from the code of in-hous platform. In that case contextRefreshed flag in RabbitListenerEndpointRegistry was set to true, and during 2nd call to startIfNecessary (beacause of context.start()) listener was started.