如何修改 Spring Cloud AWS 用来反序列化 SQS 消息的对象映射器?
Posted
技术标签:
【中文标题】如何修改 Spring Cloud AWS 用来反序列化 SQS 消息的对象映射器?【英文标题】:How to modify the object mapper that Spring Cloud AWS uses to deserialize SQS messages? 【发布时间】:2018-04-01 05:50:36 【问题描述】:我需要修改 Spring Cloud AWS 在反序列化 JSON 并使用它注册 JavaTime 模块时使用的 Jackson2 对象映射器。这是因为 SQS 有效负载包含 Java Instant 类的实例,该实例必须使用 JavaTime 模块进行反序列化。
详情:
这是 SQS 监听方法:
@SqsListener(value = "mysqs",deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
public void handleChangedEventFromSqsQueue(@NotificationMessage ChangeEvent event)
try
// Handle ChangeEvent object here
catch (Throwable t)
// Do something
这是 ChangedEvent 类:
public class ChangeEvent
private final Long oldValue;
private final Long newValue;
private final Instant changedAt;
// This is the ID of the user who performed the change
private final Long changedBy;
// Constructors, getters, and setters omitted
这是我得到的错误:
org.springframework.messaging.MessagingException: An exception occurred while invoking the handler method; nested exception is org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Can not construct instance of java.time.Instant: no String-argument constructor/factory method to deserialize from String value ('2017-10-20T01:58:09.298Z')
at [Source: "oldValue": 1,"newValue": 2,"changedAt":"2017-10-20T01:58:09.298Z","changedBy":20116; line: 1, column: 124] (through reference chain: com.company.ChangeEvent["changedAt"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.time.Instant: no String-argument constructor/factory method to deserialize from String value ('2017-10-20T01:58:09.298Z')
at [Source: "oldValue": 1,"newValue": 2,"changedAt":"2017-10-20T01:58:09.298Z","changedBy":20116; line: 1, column: 124] (through reference chain: com.company.ChangeEvent["changedAt"])
at org.springframework.cloud.aws.messaging.listener.QueueMessageHandler.processHandlerMethodException(QueueMessageHandler.java:195) ~[spring-cloud-aws-messaging-1.1.0.RELEASE.jar:1.1.0.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:506) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:451) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:389) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer.executeMessage(SimpleMessageListenerContainer.java:181) ~[spring-cloud-aws-messaging-1.1.0.RELEASE.jar:1.1.0.RELEASE]
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer$MessageExecutor.run(SimpleMessageListenerContainer.java:314) ~[spring-cloud-aws-messaging-1.1.0.RELEASE.jar:1.1.0.RELEASE]
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer$SignalExecutingRunnable.run(SimpleMessageListenerContainer.java:368) [spring-cloud-aws-messaging-1.1.0.RELEASE.jar:1.1.0.RELEASE]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]
Caused by: org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Can not construct instance of java.time.Instant: no String-argument constructor/factory method to deserialize from String value ('2017-10-20T01:58:09.298Z')
at [Source: "oldValue": 1,"newValue": 2,"changedAt":"2017-10-20T01:58:09.298Z","changedBy":20116; line: 1, column: 124] (through reference chain: com.company.ChangeEvent["changedAt"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.time.Instant: no String-argument constructor/factory method to deserialize from String value ('2017-10-20T01:58:09.298Z')
at [Source: "oldValue": 1,"newValue": 2,"changedAt":"2017-10-20T01:58:09.298Z","changedBy":20116; line: 1, column: 124] (through reference chain: com.company.ChangeEvent["changedAt"])
at org.springframework.messaging.converter.MappingJackson2MessageConverter.convertFromInternal(MappingJackson2MessageConverter.java:223) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.converter.AbstractMessageConverter.fromMessage(AbstractMessageConverter.java:175) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.converter.AbstractMessageConverter.fromMessage(AbstractMessageConverter.java:167) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.converter.CompositeMessageConverter.fromMessage(CompositeMessageConverter.java:55) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.cloud.aws.messaging.support.converter.NotificationRequestConverter.fromMessage(NotificationRequestConverter.java:80) ~[spring-cloud-aws-messaging-1.1.0.RELEASE.jar:1.1.0.RELEASE]
at org.springframework.cloud.aws.messaging.support.NotificationMessageArgumentResolver.resolveArgument(NotificationMessageArgumentResolver.java:45) ~[spring-cloud-aws-messaging-1.1.0.RELEASE.jar:1.1.0.RELEASE]
at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:98) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:138) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:107) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:490) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
... 8 common frames omitted
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.time.Instant: no String-argument constructor/factory method to deserialize from String value ('2017-10-20T01:58:09.298Z')
at [Source: "oldValue": 1,"newValue": 2,"changedAt":"2017-10-20T01:58:09.298Z","changedBy":20116; line: 1, column: 124] (through reference chain: com.company.ChangeEvent["changedAt"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1456) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1012) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:370) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:315) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1282) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:159) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:150) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:499) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:511) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:396) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1198) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:314) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:499) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:101) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:357) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3798) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2880) ~[jackson-databind-2.8.5.jar:2.8.5]
at org.springframework.messaging.converter.MappingJackson2MessageConverter.convertFromInternal(MappingJackson2MessageConverter.java:218) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
... 17 common frames omitted
附加信息:
Jackson JSR-310 模块位于类路径中。 应用程序的其他部分正在无缝地使用 JSR-310。事实上,我不需要为 JSR-310 进行任何配置 - 我所做的只是将 Jackson JSR-310 模块添加到类路径中,一切正常。我第一次尝试修复它(失败)
在我第一次尝试解决这个问题时,我尝试公开一个 QueueMessageHandlerFactory
类型的 bean 并使用我自己的 ObjectMapper 对其进行配置。不幸的是,这也不起作用。此故障的详细信息如下。我不确定他们是否会帮助调试。
这是我暴露的bean:
@Configuration
public class AwsSqsConfig
@Bean
public QueueMessageHandlerFactory queueMessageHandlerFactory(AmazonSQS amazonSQS,
BeanFactory beanFactory)
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
MappingJackson2MessageConverter mappingJackson2MessageConverter = new MappingJackson2MessageConverter();
mappingJackson2MessageConverter.setSerializedPayloadClass(String.class);
mappingJackson2MessageConverter.setObjectMapper(objectMapper);
Assert.notNull(amazonSQS);
Assert.notNull(beanFactory);
QueueMessageHandlerFactory factory = new QueueMessageHandlerFactory();
factory.setAmazonSqs(amazonSQS);
factory.setBeanFactory(beanFactory);
factory.setArgumentResolvers(Arrays.asList(new PayloadArgumentResolver(mappingJackson2MessageConverter)));
return factory;
我让监听器方法和 ChangeEvent 类保持不变,但这次我得到了不同的错误:
org.springframework.messaging.MessagingException: An exception occurred while invoking the handler method; nested exception is org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Unrecognized field "Type" (class com.company.ChangeEvent), not marked as ignorable
at [Source:
"Type" : "Notification",
"MessageId" : "e9e26416-ae16-5c60-b3a3-36752ebc3512",
"TopicArn" : "arn:aws:sns:us-east-1:799735207477:matchStatusUpdated-dev",
"Message" : "\"oldValue\":1,\"newValue\":2,\"changedAt\":\"2017-10-20T04:41:15.024Z\",\"changedBy\":20116",
"Timestamp" : "2017-10-20T04:41:14.667Z",
"SignatureVersion" : "1",
"Signature" : "XXD+IAuCr6TUzkG1RIrreqf6OjAdvy7Bi/xZTBWOJI/LsTz5HG4QdTiTD4pZYI6jgupEhsG8BWYR8krKrwdSjfpYLD2z8pxBl4hEjgmgcCOHatKR7Hk9Sydsecr4yagrs0LUSjItB3EGv5O5Qfilps//swNaQnC+1VuIVedmaHxQi8McWBBzdBjFVs5WBHzItbRhC1KIsbf08Fnhc/XK9iAJTjY+09wUzVRs8x60NpaPoTQOYPJ1Yl7UNk4s8TQFd/pnWvRZpxv3hlh+Cz6CqwluER65lHol1tzCgAM60NcbxM+wqXE4IxfYHVG2PRKnE05x4mdjBqyVodOOXJYhtQ==",
"SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-433026a4050d206028891664da859041.pem",
"UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:799735207477:matchStatusUpdated-dev:135541fc-37de-40b3-84bc-d54cee36a10f",
"MessageAttributes" :
"id" : "Type":"String","Value":"1d18420f-bfcc-81b5-be6e-b7be543d5247",
"contentType" : "Type":"String","Value":"application/json;charset=UTF-8",
"timestamp" : "Type":"Number.java.lang.Long","Value":"1508474475049"
; line: 2, column: 13] (through reference chain: com.company.ChangeEvent["Type"]); nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Type" (class com.company.ChangeEvent), not marked as ignorable)
at [Source:
"Type" : "Notification",
"MessageId" : "e9e26416-ae16-5c60-b3a3-36752ebc3512",
"TopicArn" : "arn:aws:sns:us-east-1:799735207477:matchStatusUpdated-dev",
"Message" : "\"oldValue\":1,\"newValue\":2,\"changedAt\":\"2017-10-20T04:41:15.024Z\",\"changedBy\":20116",
"Timestamp" : "2017-10-20T04:41:14.667Z",
"SignatureVersion" : "1",
"Signature" : "XXD+IAuCr6TUzkG1RIrreqf6OjAdvy7Bi/xZTBWOJI/LsTz5HG4QdTiTD4pZYI6jgupEhsG8BWYR8krKrwdSjfpYLD2z8pxBl4hEjgmgcCOHatKR7Hk9Sydsecr4yagrs0LUSjItB3EGv5O5Qfilps//swNaQnC+1VuIVedmaHxQi8McWBBzdBjFVs5WBHzItbRhC1KIsbf08Fnhc/XK9iAJTjY+09wUzVRs8x60NpaPoTQOYPJ1Yl7UNk4s8TQFd/pnWvRZpxv3hlh+Cz6CqwluER65lHol1tzCgAM60NcbxM+wqXE4IxfYHVG2PRKnE05x4mdjBqyVodOOXJYhtQ==",
"SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-433026a4050d206028891664da859041.pem",
"UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:799735207477:matchStatusUpdated-dev:135541fc-37de-40b3-84bc-d54cee36a10f",
"MessageAttributes" :
"id" : "Type":"String","Value":"1d18420f-bfcc-81b5-be6e-b7be543d5247",
"contentType" : "Type":"String","Value":"application/json;charset=UTF-8",
"timestamp" : "Type":"Number.java.lang.Long","Value":"1508474475049"
; line: 2, column: 13] (through reference chain: com.company.ChangeEvent["Type"])
at org.springframework.cloud.aws.messaging.listener.QueueMessageHandler.processHandlerMethodException(QueueMessageHandler.java:195) ~[spring-cloud-aws-messaging-1.1.0.RELEASE.jar:1.1.0.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:506) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:451) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:389) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer.executeMessage(SimpleMessageListenerContainer.java:181) ~[spring-cloud-aws-messaging-1.1.0.RELEASE.jar:1.1.0.RELEASE]
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer$MessageExecutor.run(SimpleMessageListenerContainer.java:314) ~[spring-cloud-aws-messaging-1.1.0.RELEASE.jar:1.1.0.RELEASE]
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer$SignalExecutingRunnable.run(SimpleMessageListenerContainer.java:368) [spring-cloud-aws-messaging-1.1.0.RELEASE.jar:1.1.0.RELEASE]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]
Caused by: org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Unrecognized field "Type" (class com.company.ChangeEvent), not marked as ignorable
at [Source:
"Type" : "Notification",
"MessageId" : "e9e26416-ae16-5c60-b3a3-36752ebc3512",
"TopicArn" : "arn:aws:sns:us-east-1:799735207477:matchStatusUpdated-dev",
"Message" : "\"oldValue\":1,\"newValue\":2,\"changedAt\":\"2017-10-20T04:41:15.024Z\",\"changedBy\":20116",
"Timestamp" : "2017-10-20T04:41:14.667Z",
"SignatureVersion" : "1",
"Signature" : "XXD+IAuCr6TUzkG1RIrreqf6OjAdvy7Bi/xZTBWOJI/LsTz5HG4QdTiTD4pZYI6jgupEhsG8BWYR8krKrwdSjfpYLD2z8pxBl4hEjgmgcCOHatKR7Hk9Sydsecr4yagrs0LUSjItB3EGv5O5Qfilps//swNaQnC+1VuIVedmaHxQi8McWBBzdBjFVs5WBHzItbRhC1KIsbf08Fnhc/XK9iAJTjY+09wUzVRs8x60NpaPoTQOYPJ1Yl7UNk4s8TQFd/pnWvRZpxv3hlh+Cz6CqwluER65lHol1tzCgAM60NcbxM+wqXE4IxfYHVG2PRKnE05x4mdjBqyVodOOXJYhtQ==",
"SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-433026a4050d206028891664da859041.pem",
"UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:799735207477:matchStatusUpdated-dev:135541fc-37de-40b3-84bc-d54cee36a10f",
"MessageAttributes" :
"id" : "Type":"String","Value":"1d18420f-bfcc-81b5-be6e-b7be543d5247",
"contentType" : "Type":"String","Value":"application/json;charset=UTF-8",
"timestamp" : "Type":"Number.java.lang.Long","Value":"1508474475049"
; line: 2, column: 13] (through reference chain: com.company.ChangeEvent["Type"]); nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Type" (class com.company.ChangeEvent), not marked as ignorable
at [Source:
"Type" : "Notification",
"MessageId" : "e9e26416-ae16-5c60-b3a3-36752ebc3512",
"TopicArn" : "arn:aws:sns:us-east-1:799735207477:matchStatusUpdated-dev",
"Message" : "\"oldValue\":1,\"newValue\":2,\"changedAt\":\"2017-10-20T04:41:15.024Z\",\"changedBy\":20116",
"Timestamp" : "2017-10-20T04:41:14.667Z",
"SignatureVersion" : "1",
"Signature" : "XXD+IAuCr6TUzkG1RIrreqf6OjAdvy7Bi/xZTBWOJI/LsTz5HG4QdTiTD4pZYI6jgupEhsG8BWYR8krKrwdSjfpYLD2z8pxBl4hEjgmgcCOHatKR7Hk9Sydsecr4yagrs0LUSjItB3EGv5O5Qfilps//swNaQnC+1VuIVedmaHxQi8McWBBzdBjFVs5WBHzItbRhC1KIsbf08Fnhc/XK9iAJTjY+09wUzVRs8x60NpaPoTQOYPJ1Yl7UNk4s8TQFd/pnWvRZpxv3hlh+Cz6CqwluER65lHol1tzCgAM60NcbxM+wqXE4IxfYHVG2PRKnE05x4mdjBqyVodOOXJYhtQ==",
"SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-433026a4050d206028891664da859041.pem",
"UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:799735207477:matchStatusUpdated-dev:135541fc-37de-40b3-84bc-d54cee36a10f",
"MessageAttributes" :
"id" : "Type":"String","Value":"1d18420f-bfcc-81b5-be6e-b7be543d5247",
"contentType" : "Type":"String","Value":"application/json;charset=UTF-8",
"timestamp" : "Type":"Number.java.lang.Long","Value":"1508474475049"
; line: 2, column: 13] (through reference chain: com.company.ChangeEvent["Type"])
at org.springframework.messaging.converter.MappingJackson2MessageConverter.convertFromInternal(MappingJackson2MessageConverter.java:223) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.converter.AbstractMessageConverter.fromMessage(AbstractMessageConverter.java:175) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.annotation.support.PayloadArgumentResolver.resolveArgument(PayloadArgumentResolver.java:115) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:98) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:138) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:107) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:490) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
... 8 common frames omitted
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Type" (class com.company.ChangeEvent), not marked as ignorable
at [Source:
"Type" : "Notification",
"MessageId" : "e9e26416-ae16-5c60-b3a3-36752ebc3512",
"TopicArn" : "arn:aws:sns:us-east-1:799735207477:matchStatusUpdated-dev",
"Message" : "\"oldValue\":1,\"newValue\":2,\"changedAt\":\"2017-10-20T04:41:15.024Z\",\"changedBy\":20116",
"Timestamp" : "2017-10-20T04:41:14.667Z",
"SignatureVersion" : "1",
"Signature" : "XXD+IAuCr6TUzkG1RIrreqf6OjAdvy7Bi/xZTBWOJI/LsTz5HG4QdTiTD4pZYI6jgupEhsG8BWYR8krKrwdSjfpYLD2z8pxBl4hEjgmgcCOHatKR7Hk9Sydsecr4yagrs0LUSjItB3EGv5O5Qfilps//swNaQnC+1VuIVedmaHxQi8McWBBzdBjFVs5WBHzItbRhC1KIsbf08Fnhc/XK9iAJTjY+09wUzVRs8x60NpaPoTQOYPJ1Yl7UNk4s8TQFd/pnWvRZpxv3hlh+Cz6CqwluER65lHol1tzCgAM60NcbxM+wqXE4IxfYHVG2PRKnE05x4mdjBqyVodOOXJYhtQ==",
"SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-433026a4050d206028891664da859041.pem",
"UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:799735207477:matchStatusUpdated-dev:135541fc-37de-40b3-84bc-d54cee36a10f",
"MessageAttributes" :
"id" : "Type":"String","Value":"1d18420f-bfcc-81b5-be6e-b7be543d5247",
"contentType" : "Type":"String","Value":"application/json;charset=UTF-8",
"timestamp" : "Type":"Number.java.lang.Long","Value":"1508474475049"
; line: 2, column: 13] (through reference chain: com.company.ChangeEvent["Type"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:62) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:834) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1093) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1477) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1455) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:282) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3798) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2880) ~[jackson-databind-2.8.5.jar:2.8.5]
at org.springframework.messaging.converter.MappingJackson2MessageConverter.convertFromInternal(MappingJackson2MessageConverter.java:218) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
... 14 common frames omitted
基本上,所有这些堆栈跟踪意味着我错误配置了 QueueMessageHandler,导致无法反序列化 NotificationMessage。
总结
就像我之前说的,我需要知道如何修改 Spring Cloud AWS 用来反序列化 SQS 消息的对象映射器。有谁知道怎么做?
谢谢!
【问题讨论】:
【参考方案1】:您正在尝试侦听 SQS 队列上的 SNS 消息。因为它们基本上是 SNS 消息,所以负载被包装在 Notification 消息中(这就是为什么在 SQSListener 上设置了 @NotificationMessage 注释)。
这实际上是让监听器使用 NotificationMessageArgumentResolver 而不是 PayloadArgumentResolver 来解析消息。 NotificationMessageArgumentResolver 需要一个 NotificationRequestConverter 来完成这项工作。
请试试这个配置,我自己在SNS上测试过-->SQS消息成功:
@Configuration
public class AwsSqsConfig
@Bean
public QueueMessageHandlerFactory queueMessageHandlerFactory(
AmazonSQSAsync amazonSQS, BeanFactory beanFactory)
ObjectMapper objectMapper = new ObjectMapper();
// This is the java time module needed in the mapper (can be read in the question)
objectMapper.registerModule(new JavaTimeModule());
// Wrapped in this
MappingJackson2MessageConverter jacksonMessageConverter =
new MappingJackson2MessageConverter();
jacksonMessageConverter.setSerializedPayloadClass(String.class);
jacksonMessageConverter.setObjectMapper(objectMapper);
jacksonMessageConverter.setStrictContentTypeMatch(true);
// Wrapped in this
List<MessageConverter> payloadArgumentConverters = new ArrayList<>();
payloadArgumentConverters.add(jacksonMessageConverter);
// This is the converter that is invoked on SNS messages on SQS listener
NotificationRequestConverter notificationRequestConverter =
new NotificationRequestConverter(jacksonMessageConverter);
payloadArgumentConverters.add(notificationRequestConverter);
payloadArgumentConverters.add(new SimpleMessageConverter());
// It needs to be wrapped in this
CompositeMessageConverter compositeMessageConverter =
new CompositeMessageConverter(payloadArgumentConverters);
Assert.notNull(amazonSQS);
Assert.notNull(beanFactory);
QueueMessageHandlerFactory factory = new QueueMessageHandlerFactory();
factory.setAmazonSqs(amazonSQS);
factory.setBeanFactory(beanFactory);
// The factory has this method for custom resolvers (can be read in the question)
factory.setArgumentResolvers(Arrays.asList(
new NotificationMessageArgumentResolver(compositeMessageConverter)));
return factory;
您的尝试是正确的,它实际上对上述解决方案有很大帮助,谢谢。如果它是一条简单的 SQS 消息,而不是 SQS 上的 SNS,那么您的解决方案绝对有效(也尝试过)。
【讨论】:
以上是关于如何修改 Spring Cloud AWS 用来反序列化 SQS 消息的对象映射器?的主要内容,如果未能解决你的问题,请参考以下文章
如何集成 AWS + ELB + AutoScale + Docker + Spring Cloud
如何使用 Spring Cloud AWS 从 S3 中删除文件?
如何使用AWS Lambda和SNS事件触发Spring Cloud功能的重试
Spring Cloud 应用程序与 AWS Parameter Store 的集成测试