@SQSListen导致异常,无法正常工作。

huangapple go评论114阅读模式
英文:

@SQSListen results in an exception and not working

问题

这是您提供的内容的翻译:

  1. package com.demo.arf.testsqsboot;
  2. import com.amazonaws.services.sqs.AmazonSQSAsync;
  3. import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder;
  4. import org.springframework.beans.factory.annotation.Value;
  5. import org.springframework.cloud.aws.messaging.config.SimpleMessageListenerContainerFactory;
  6. import org.springframework.cloud.aws.messaging.core.QueueMessagingTemplate;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import com.amazonaws.auth.AWSStaticCredentialsProvider;
  10. import com.amazonaws.auth.BasicAWSCredentials;
  11. import com.amazonaws.regions.Regions;
  12. @Configuration
  13. public class SQSConfig {
  14. @Value("${cloud.aws.region.static}")
  15. private String region;
  16. @Value("${cloud.aws.credentials.access-key}")
  17. private String awsAccessKey;
  18. @Value("${cloud.aws.credentials.secret-key}")
  19. private String awsSecretKey;
  20. @Bean
  21. public QueueMessagingTemplate queueMessagingTemplate() {
  22. return new QueueMessagingTemplate(amazonSQSAsync());
  23. }
  24. public AmazonSQSAsync amazonSQSAsync() {
  25. return AmazonSQSAsyncClientBuilder.standard().withRegion(Regions.US_EAST_1)
  26. .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(awsAccessKey, awsSecretKey)))
  27. .build();
  28. }
  29. @Bean
  30. public SimpleMessageListenerContainerFactory simpleMessageListenerContainerFactory(AmazonSQSAsync amazonSQS){
  31. SimpleMessageListenerContainerFactory factory = new SimpleMessageListenerContainerFactory();
  32. factory.setAmazonSqs(amazonSQS);
  33. factory.setMaxNumberOfMessages(10);
  34. return factory;
  35. }
  36. }
  1. package com.demo.arf.testsqsboot.controller;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.cloud.aws.messaging.core.QueueMessagingTemplate;
  6. import org.springframework.cloud.aws.messaging.listener.annotation.SqsListener;
  7. import org.springframework.messaging.support.MessageBuilder;
  8. import org.springframework.web.bind.annotation.GetMapping;
  9. import org.springframework.web.bind.annotation.RestController;
  10. @RestController
  11. public class SQSController {
  12. @Autowired
  13. private QueueMessagingTemplate queueMessagingTemplate;
  14. private static final Logger LOG = LoggerFactory.getLogger(SQSController.class);
  15. @GetMapping("/send-sqs-message")
  16. public String sendMessage() {
  17. String sqsEndPoint = "https://sqs.us-east-2.amazonaws.com/1234567879/my_queue";
  18. queueMessagingTemplate.convertAndSend(sqsEndPoint, MessageBuilder.withPayload("hello from Spring Boot").build());
  19. return "Hello SQS";
  20. }
  21. @SqsListener("my_queue")
  22. public void getMessage(String message) {
  23. LOG.info(" *********** Message from SQS Queue - " + message);
  24. }
  25. }
  1. server:
  2. port: 9001
  3. cloud:
  4. aws:
  5. region:
  6. static: us-east-1
  7. auto: false
  8. credentials:
  9. access-key: "asdmnasdn"
  10. secret-key: "sfkjsdjksdkj"
  11. end-point:
  12. uri: https://sqs.us-east-2.amazonaws.com/1234567879/my_queue

在启动时,您可能会遇到以下错误:

  1. WARNING: An illegal reflective access operation has occurred...
  2. WARNING: Please consider reporting this to the maintainers of com.amazonaws.util.XpathUtils...
  3. ...
  4. s.c.a.m.l.SimpleMessageListenerContainer : Ignoring queue with name 'my_queue': The queue does not exist.; nested exception is com.amazonaws.services.sqs.model.QueueDoesNotExistException...

另外,关于 @SqsListener 如何知道 AWS 账户信息和 SQS URI 的基本问题,是因为在您的配置文件中,您已经提供了 AWS 账户的访问密钥和所需的队列 URI。@SqsListener 注解通过 Spring Cloud AWS 集成自动将这些信息用于监听 SQS 队列上的消息。

英文:

I've a very simple Spring cloud aws project. I'm using Java 11.
here is the pom:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.2.5.RELEASE</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.demo.arf</groupId>
  12. <artifactId>testsqs-boot</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>testsqs-boot</name>
  15. <description>Demo project for Spring Boot</description>
  16. <dependencies>
  17. <dependency>
  18. <groupId>org.springframework.cloud</groupId>
  19. <artifactId>spring-cloud-dependencies</artifactId>
  20. <version>Hoxton.SR3</version>
  21. <type>pom</type>
  22. <scope>runtime</scope>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-web</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-starter-test</artifactId>
  31. <scope>test</scope>
  32. <exclusions>
  33. <exclusion>
  34. <groupId>org.junit.vintage</groupId>
  35. <artifactId>junit-vintage-engine</artifactId>
  36. </exclusion>
  37. </exclusions>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.springframework.cloud</groupId>
  41. <artifactId>spring-cloud-starter-aws</artifactId>
  42. <version>2.2.1.RELEASE</version>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.springframework.cloud</groupId>
  46. <artifactId>spring-cloud-starter-aws-messaging</artifactId>
  47. <version>2.2.1.RELEASE</version>
  48. </dependency>
  49. </dependencies>
  50. <build>
  51. <plugins>
  52. <plugin>
  53. <groupId>org.springframework.boot</groupId>
  54. <artifactId>spring-boot-maven-plugin</artifactId>
  55. </plugin>
  56. </plugins>
  57. </build>
  58. </project>

Config class:

  1. package com.demo.arf.testsqsboot;
  2. import com.amazonaws.services.sqs.AmazonSQSAsync;
  3. import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder;
  4. import org.springframework.beans.factory.annotation.Value;
  5. //import org.springframework.cloud.aws.messaging.core.QueueMessagingTemplate;
  6. import org.springframework.cloud.aws.messaging.config.SimpleMessageListenerContainerFactory;
  7. import org.springframework.cloud.aws.messaging.core.QueueMessagingTemplate;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.context.annotation.Configuration;
  10. import com.amazonaws.auth.AWSStaticCredentialsProvider;
  11. import com.amazonaws.auth.BasicAWSCredentials;
  12. import com.amazonaws.regions.Regions;
  13. //import com.amazonaws.services.sqs.AmazonSQSAsync;
  14. //import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder;
  15. @Configuration
  16. public class SQSConfig {
  17. @Value("${cloud.aws.region.static}")
  18. private String region;
  19. @Value("${cloud.aws.credentials.access-key}")
  20. private String awsAccessKey;
  21. @Value("${cloud.aws.credentials.secret-key}")
  22. private String awsSecretKey;
  23. @Bean
  24. public QueueMessagingTemplate queueMessagingTemplate() {
  25. return new QueueMessagingTemplate(amazonSQSAsync());
  26. }
  27. public AmazonSQSAsync amazonSQSAsync() {
  28. return AmazonSQSAsyncClientBuilder.standard().withRegion(Regions.US_EAST_1)
  29. .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(awsAccessKey, awsSecretKey)))
  30. .build();
  31. }
  32. @Bean
  33. public SimpleMessageListenerContainerFactory simpleMessageListenerContainerFactory(AmazonSQSAsync amazonSQS){
  34. SimpleMessageListenerContainerFactory factory = new SimpleMessageListenerContainerFactory();
  35. factory.setAmazonSqs(amazonSQS);
  36. factory.setMaxNumberOfMessages(10);
  37. return factory;
  38. }
  39. }

the controller class which send/receive message:

  1. package com.demo.arf.testsqsboot.controller;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.cloud.aws.messaging.core.QueueMessagingTemplate;
  6. import org.springframework.cloud.aws.messaging.listener.annotation.SqsListener;
  7. import org.springframework.messaging.support.MessageBuilder;
  8. import org.springframework.web.bind.annotation.GetMapping;
  9. import org.springframework.web.bind.annotation.RestController;
  10. @RestController
  11. public class SQSController {
  12. @Autowired
  13. private QueueMessagingTemplate queueMessagingTemplate;
  14. private static final Logger LOG = LoggerFactory.getLogger(SQSController.class);
  15. @GetMapping("/send-sqs-message")
  16. public String sendMessage() {
  17. String sqsEndPoint= "https://sqs.us-east-2.amazonaws.com/1234567879/my_queue";
  18. queueMessagingTemplate.convertAndSend(sqsEndPoint, MessageBuilder.withPayload("hello from Spring Boot").build());
  19. return "Hello SQS";
  20. }
  21. @SqsListener("my_queue")
  22. public void getMessage(String message) {
  23. LOG.info(" *********** Message from SQS Queue - "+message);
  24. }
  25. }

application.yml:

  1. server:
  2. port: 9001
  3. cloud:
  4. aws:
  5. region:
  6. static: us-east-1
  7. auto: false
  8. credentials:
  9. access-key: "asdmnasdn"
  10. secret-key: "sfkjsdjksdkj"
  11. end-point:
  12. uri: https://sqs.us-east-2.amazonaws.com/1234567879/my_queue

I can get the send working fine. but when I add the listener, I get the following error during startup and listener does not receive messages:

  1. 2020-03-15 01:02:00.677 INFO 15423 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3853 ms
  2. 2020-03-15 01:02:01.109 INFO 15423 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
  3. **WARNING: An illegal reflective access operation has occurred
  4. WARNING: Illegal reflective access by com.amazonaws.util.XpathUtils (file:/Users/arf/.m2/repository/com/amazonaws/aws-java-sdk-core/1.11.415/aws-java-sdk-core-1.11.415.jar) to method com.sun.org.apache.xpath.internal.XPathContext.getDTMManager()
  5. WARNING: Please consider reporting this to the maintainers of com.amazonaws.util.XpathUtils
  6. WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
  7. WARNING: All illegal access operations will be denied in a future release
  8. 2020-03-15 01:02:01.749 WARN 15423 --- [ main]**
  9. s.c.a.m.l.SimpleMessageListenerContainer : Ignoring queue with name 'my_queue': The queue does not exist.; nested exception is com.amazonaws.services.sqs.model.QueueDoesNotExistException: The specified queue does not exist for this wsdl version. (Service: AmazonSQS; Status Code: 400; Error Code: AWS.SimpleQueueService.NonExistentQueue; Request ID: 62821505-3f34-5434-a6ee)
  10. 2020-03-15 01:02:01.749 INFO 15423 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService

Also, one basic question. How does the @SQSListener know where to find the aws account info and sqs uri?

答案1

得分: 1

  1. @Bean
  2. public QueueMessagingTemplate queueMessagingTemplate(AmazonSQSAsync amazonSQS) {
  3. return new QueueMessagingTemplate(amazonSQS);
  4. }
  5. @Bean
  6. @Primary
  7. public AmazonSQSAsync amazonSQS(AWSCredentialsProvider credentials) {
  8. return AmazonSQSAsyncClientBuilder.standard()
  9. .withCredentials(credentials)
  10. .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(localStackSqsUrl, awsRegion))
  11. .build();
  12. }
  13. @Bean
  14. @Primary
  15. public AWSCredentialsProvider awsCredentialsProvider() {
  16. return new AWSCredentialsProviderChain(
  17. new AWSStaticCredentialsProvider(
  18. new BasicAWSCredentials("local", "stack")));
  19. }
英文:

I've made it work with the following change in config class. However, I wonder, how most of the sample programs online without this code(which construct AmazonSQSAsync with withEndpointConfiguration) is working.

  1. public QueueMessagingTemplate queueMessagingTemplate(AmazonSQSAsync amazonSQS) {
  2. return new QueueMessagingTemplate(amazonSQS);
  3. }
  4. @Bean
  5. @Primary
  6. public AmazonSQSAsync amazonSQS(AWSCredentialsProvider credentials) {
  7. return AmazonSQSAsyncClientBuilder.standard()
  8. .withCredentials(credentials)
  9. .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(localStackSqsUrl, awsRegion))
  10. .build();
  11. }
  12. @Bean
  13. @Primary
  14. public AWSCredentialsProvider awsCredentialsProvider() {
  15. return new AWSCredentialsProviderChain(
  16. new AWSStaticCredentialsProvider(
  17. new BasicAWSCredentials("local", "stack")));
  18. }```
  19. </details>
  20. # 答案2
  21. **得分**: 1
  22. 第一点。
  23. - 首先,永远不要将您的AK/SK存储在属性或yml文件中。我可以看出那些是虚假值,但您总是希望从~/.aws/credentials或实例元数据中获取这些值。如果您只是调用`.standard()`,那么像AmazonSqSAsyncClientBuilder这样的AWS客户端会自动执行。不需要凭证提供程序。
  24. - 其次,区域也是如此。
  25. - 第三,我相信`@SqsListener`将使用您之前定义的`ContainerFactory` bean,至少`@JmsListener`是这样工作的。
  26. - 您收到的错误消息是您的队列名称在您选择的区域中未找到。您告诉我们是us-east-1,但在您的发送代码中,您指定了us-east-2。根据您的帖子,我猜您的队列位于us-east-2,因为您的问题与`@SqsListener`有关,而不是`queueMessagingTemplate`。
  27. <details>
  28. <summary>英文:</summary>
  29. A couple things.
  30. - First NEVER store your AK/SK in a property or yml file like that. I can tell those are fake values, but you&#39;ll always want to pull these from ~/.aws/credentials or instance metadata. The AWS clients like AmazonSqSAsyncClientBuilder will do automatically if you just call .standard(). No need for the credential provider.
  31. - Second, same with region
  32. - Third, I believe @SqsListener will use the ContainerFactory bean you defined earlier, at least that&#39;s how the @JmsListener works.
  33. - The error message you received was that your queue name was not found in your account in your selected region. You told it us-east-1, but in your send code you specified us-east-2. My guess based on your post is that your queue is in us-east-2 since your question came up about @SqsListener, not the queueMessagingTemplate.
  34. </details>

huangapple
  • 本文由 发表于 2020年3月15日 14:16:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/60690269.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定