admin管理员组

文章数量:1406032

I am working on migrating a Spring Boot application from version 2 to 3.2.4. As part of this migration, we initially planned to use AWS SDK v2 and Spring Cloud AWS 3 for SQS functionality. However, due to issues with AWS SDK v2 and Spring Cloud AWS 3, we decided to stick with AWS SDK v1 and Spring Cloud AWS Messaging for queue services, while using Spring Boot 3.2.4.

public class QueueConfiguration {

    @Bean
    @Primary
    @Profile("local & !test")
    public AmazonSQSAsync amazonSQS() {
        AWSCredentials basicAWSCredentials = new BasicAWSCredentials("test", "test");
        AwsClientBuilder.EndpointConfiguration endpointConfiguration =
            new AwsClientBuilder.EndpointConfiguration("http://localhost:4566", "us-east-1");
        AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(basicAWSCredentials);

        AmazonSQSAsync amazonSqsClient = AmazonSQSAsyncClientBuilder.standard()
            .withEndpointConfiguration(endpointConfiguration)
            .withCredentials(credentialsProvider)
            .build();

        try {
            StreamEx.of(queueProperties.getQueues())
                .forEach(sqsServiceQueueName -> {
                    ListQueuesResult existingQueues = amazonSqsClient.listQueues(sqsServiceQueueName);
                    if (isEmpty(existingQueues.getQueueUrls())) {
                        amazonSqsClient.createQueue(new CreateQueueRequest().withQueueName(sqsServiceQueueName)
                            .addAttributesEntry("FifoQueue", "True"));
                    }
                });
        } catch (SdkClientException e) {
            log.warn("You need to run localstack to enable local amazon sqs functionality. " +
                "See and run docker-compose file.");
        }

        return amazonSqsClient;
    }

    @Bean("!test")
    @Primary
    public QueueMessageHandlerFactory queueMessageHandlerFactory(ObjectMapper objectMapper) {
        QueueMessageHandlerFactory factory = new QueueMessageHandlerFactory();
        MappingJackson2MessageConverter messageConverter = new MappingJackson2MessageConverter();
        messageConverter.setStrictContentTypeMatch(false);
        messageConverter.setObjectMapper(objectMapper);
        PayloadMethodArgumentResolver payloadResolver = new PayloadMethodArgumentResolver(messageConverter, null, false);
        AcknowledgmentHandlerMethodArgumentResolver acknowledgmentResolver = 
            new AcknowledgmentHandlerMethodArgumentResolver("Acknowledgment");

        factory.setArgumentResolvers(Arrays.asList(acknowledgmentResolver, payloadResolver));
        return factory;
    }

    @Bean
    public QueueMessagingTemplate queueMessagingTemplate(AmazonSQSAsync amazonSQSAsync) {
        return new QueueMessagingTemplate(amazonSQSAsync);
    }

    @Bean
    public QueueMessageChannel deadLetterQueueChannel(
        AmazonSQSAsync amazonSQSAsync,
        @Value("${amazon.sqs.queue.device-dlq}") String deadLetterQueue) {
        log.info("DLQueue is {}", deadLetterQueue);
        String queueUrl = amazonSQSAsync.getQueueUrl(deadLetterQueue)
            .getQueueUrl();

        return new QueueMessageChannel(amazonSQSAsync, queueUrl);
    }
}

Dependencies Used 

implementation("com.amazonaws:aws-java-sdk-sqs:1.12.1")
implementation(".springframework:spring-messaging:5.2.6.RELEASE")
implementation(".springframework.cloud:spring-cloud-aws-messaging:2.2.6.RELEASE")

1.The queue is a standard queue (not FIFO) in the eu-west-1 region.

2.The code works perfectly when running locally with LocalStack (endpoint: http://localhost:4566).

However, when deployed to an EC2 instance in AWS, it fails with the following error:

.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'deviceEventListener' defined in URL [jar:nested:/app/exchange/services/license-connector-service/license-connector-service.jar/!BOOT-INF/classes/!/com/epam/license/connector/listener/DeviceEventListener.class]: Unsatisfied dependency expressed through constructor parameter 1: Error creating bean with name 'deadLetterQueueChannel' defined in class path resource [com/epam/license/connector/configuration/QueueConfiguration.class]: Failed to instantiate [.springframework.cloud.aws.messaging.core.QueueMessageChannel]: Factory method 'deadLetterQueueChannel' threw exception with message: The specified queue does not exist for this wsdl version. (Service: AmazonSQS; Status Code: 400; Error Code: AWS.SimpleQueueService.NonExistentQueue; Request ID: 6f216X0X-23X5-X011-X696-0a467facc0e0; Proxy: null) ```

Problem 1.The queue exists in the eu-west-1 region, and I’ve verified its name matches the value injected into ${amazon.sqs.queue.device-dlq}.

2.The @Profile("local & !test") annotation on the amazonSQS() bean ensures it only applies locally, so in the EC2 environment, it should use the default AWS configuration (with IAM roles, not hardcoded credentials).

Despite this, the application fails to find the queue when running on EC2, throwing an AWS.SimpleQueueService.NonExistentQueue error.

What I’ve Tried Verified the queue name and region (eu-west-1) are correct. Confirmed the EC2 instance has an IAM role with sufficient SQS permissions. Checked that the queue is a standard queue and exists in the AWS console. Questions Why does this work locally with LocalStack but fail on EC2 with a real AWS queue? Could this be related to compatibility issues between Spring Boot 3.2.4, AWS SDK v1 (1.12.1), and Spring Cloud AWS Messaging (2.2.6.RELEASE)? How can I ensure the AmazonSQSAsync client correctly connects to the queue in eu-west-1 on EC2? Any insights or suggestions would be greatly appreciated!

本文标签: