Skip to content

Improve Documentation on Mixed use of AcknowledgementMode and MessageListenerContainerFactory #971

Open
@iparadiso

Description

@iparadiso

Type: Bug

Component:

Describe the bug
The new addition of acknowledgementMode in @SqsListener is great, but it fails on startup if there are any usage of MessageListenerContainerFactory beans in the app. For example, I may be listening to two different queues. One using MessageListenerContainerFactory via the factory annotation param, and another queue using acknowledgementMode annotation param.

The failure exception is

java.lang.IllegalArgumentException: No MessageListenerContainerFactory bean with name defaultSqsListenerContainerFactory found for endpoint names [test-queue]
at org.springframework.util.Assert.isTrue(Assert.java:129)
at io.awspring.cloud.sqs.config.EndpointRegistrar.createContainerFor(EndpointRegistrar.java:223)
at io.awspring.cloud.sqs.config.EndpointRegistrar.process(EndpointRegistrar.java:218)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at io.awspring.cloud.sqs.config.EndpointRegistrar.afterSingletonsInstantiated(EndpointRegistrar.java:213)
at io.awspring.cloud.sqs.annotation.AbstractListenerAnnotationBeanPostProcessor.afterSingletonsInstantiated(AbstractListenerAnnotationBeanPostProcessor.java:256)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:984)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:946)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:616)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1342)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1331)

This is because SqsAutoConfiguration has a @CondituionalOnMissingBean, so it is never created if the same bean type exists in the app.

	@ConditionalOnMissingBean
	@Bean
	public SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory(...)

Perhaps this can be conditional on a named bean instead to allow both to exist in an app?

Sample
The following example can reproduce the issue.

@Configuration
public class MyAppConfig {
    @ConditionalOnMissingBean(name = "ACK_ON_SUCCESS_FACTORY_BEAN_NAME")
    @Bean(name = "ACK_ON_SUCCESS_FACTORY_BEAN_NAME")
    SqsMessageListenerContainerFactory<Object> acknowledgeOnSuccessFactory(SqsAsyncClient sqsAsyncClient) {
        return SqsMessageListenerContainerFactory.builder()
                .configure(options -> options.acknowledgementMode(AcknowledgementMode.ALWAYS))
                .sqsAsyncClient(sqsAsyncClient)
                .build();
    }
}

@Component 
public class SqsConsumers {
    @SqsListener(value = "test-queue-2", factory = "ACK_ON_SUCCESS_FACTORY_BEAN_NAME")
    public void consumeSqsQueue2(String message) {

    }
    
     @SqsListener(value = "test-queue", acknowledgementMode = SqsListenerAcknowledgementMode.ON_SUCCESS)
    public void consumeSqsQueue(String message) {
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions