Je vois l'exception suivante lorsque j'essaie de consommer un message SQS:
org.springframework.messaging.converter.MessageConversionException:
Cannot convert from [Java.lang.String] to [com.example.demo.Foo] for GenericMessage [payload={}, headers={LogicalResourceId=my-queue, ApproximateReceiveCount=1, SentTimestamp=1529021258825, ReceiptHandle=xxxx, Visibility=org.springframework.cloud.aws.messaging.listener.QueueMessageVisibility@47ce6922, SenderId=xxxx, lookupDestination=my-queue, ApproximateFirstReceiveTimestamp=1529021264456, MessageId=xxxx}]
at org.springframework.messaging.handler.annotation.support.PayloadArgumentResolver.resolveArgument(PayloadArgumentResolver.Java:144)
at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.Java:116)
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.Java:137)
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.Java:109)
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.Java:515)
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.Java:473)
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.Java:409)
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer.executeMessage(SimpleMessageListenerContainer.Java:205)
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer$MessageExecutor.run(SimpleMessageListenerContainer.Java:342)
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer$SignalExecutingRunnable.run(SimpleMessageListenerContainer.Java:397)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1149)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:624)
at Java.lang.Thread.run(Thread.Java:748)
Le code Spring Boot est le suivant:
@Configuration
@EnableSqs
public class AmazonSqsConfiguration {
@Bean
public AmazonSQS amazonSQSAsync() {
return AmazonSQSAsyncClientBuilder.standard()
.withRegion(Regions.US_WEST_2)
.build();
}
}
@Service
public class MyService {
// Throws MessageConversionException
@SqsListener("my-queue")
public void listen(Foo payload) {
}
// Works fine
@SqsListener("my-queue")
public void listen(String payload) {
}
}
J'utilise org.springframework.cloud:spring-cloud-aws-messaging:2.0.0.RC2
J'ai des bibliothèques Jackson 2 sur mon chemin de classe, donc PayloadArgumentResolver
essaie d'utiliser MappingJackson2MessageConverter
pour désérialiser la charge utile de mon message. Cependant, comme le message SQS manque un en-tête contentType
et que strictContentTypeMatch
est défini sur true, canConvertFrom
renvoie false.
Je ne vois pas comment il est possible de définir l'en-tête contentType
pour les messages SQS - manque-t-il quelque chose?
Spring Cloud QueueMessageHandler
doit-il définir strictContentTypeMatch
sur true?
Ran dans le même problème, et je répondrais à la question de deux façons en fonction de qui génère le message
Oui, il est possible de définir contentType
sur le message, et si vous contrôlez les messages générés, cela est préférable. Dans la console AWS, lorsque vous envoyez un message à la main, il existe un onglet pour les "attributs de message". Vous ajouteriez un attribut avec le nom contentType
et la valeur application/json
. Les appels AWS SDK devraient vous permettre de faire de même à partir du code d'application.
Pour les messages générés par AWS sans type de contenu spécifié, comme les événements S3, vous devez en fait définir strictContentMatch
sur false. Ceci est documenté ici: http://cloud.spring.io/spring-cloud-static/spring-cloud-aws/2.0.0.RELEASE/multi/multi__messaging.html#_consuming_aws_event_messages_with_Amazon_sqs
Le document est déroutant car il dit "sans l'en-tête de type MIME" mais le nom réel de l'en-tête est contentType
, comme vous vous en êtes aperçu.