Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@SqsListener Exception while handling pojo class #967

Closed
czujnik81 opened this issue Nov 23, 2023 · 3 comments
Closed

@SqsListener Exception while handling pojo class #967

czujnik81 opened this issue Nov 23, 2023 · 3 comments
Labels
component: sqs SQS integration related issue

Comments

@czujnik81
Copy link

Type: Bug

Component:
SQS

Context
I'm doing an upgrade from 2.x to 3.x with also Spring Boot upgrade from 2.X to 3.x)
I have a config where we are publishing Sns messages using SnsTemplate. Sns topic has one subscription to Sqs queue.
In v2 we have a dedicated config for SnsTemaplate migrated to v3 like this

@Bean
fun notificationMessagingTemplate(objectMapper: ObjectMapper, snsClient: SnsClient): SnsTemplate {
    val messageConverter = MappingJackson2MessageConverter()
    messageConverter.objectMapper = objectMapper
    messageConverter.serializedPayloadClass = String::class.java
    val notificationMessageTemplate = SnsTemplate(snsClient)
    notificationMessageTemplate.messageConverter = messageConverter
    return notificationMessageTemplate
}

We consume from the Sqs using @SqsListener without any other dedicated config.

Describe the bug
Once the message is delivered to the listener method I face the following Exception:

Caused by: com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class CommandEvent] value failed for JSON property commandId due to missing (therefore NULL) value for creator parameter commandId which is a non-nullable type
 at [Source: (String)"{"Type": "Notification", "MessageId": "47ccfd0e-8df6-428d-afac-58df2fd327bf", "TopicArn": "arn:aws:sns:eu-central-1:000000000000:payment-creation-event", "Message": "{\"commandId\":\"0ebf6027-0cb9-45e0-bbe1-e6e4f7734cf9\"}", "Timestamp": "2023-11-23T18:14:34.308Z", "SignatureVersion": "1", "Signature": "EXAMPLEpH+..", "SigningCertURL": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-0000000000000000000000.pem", "UnsubscribeURL": "http://localhost:4566/?Action=Unsubscribe&Subscript"[truncated 342 chars]; line: 1, column: 842] (through reference chain: io.east2.km.reward_service.shared.PaymentCreationCommandEvent["commandId"])
	at com.fasterxml.jackson.module.kotlin.KotlinValueInstantiator.createFromObjectWith(KotlinValueInstantiator.kt:101) ~[jackson-module-kotlin-2.16.0.jar:2.16.0]
	

The CommandEvent class looks like this:

sealed class BusinessEvent()

data class CommandEvent(
    val commandId: UUID,
) : BusinessEvent()

The body in the exception looks like this:

{"Type": "Notification", "MessageId": "47ccfd0e-8df6-428d-afac-58df2fd327bf", "TopicArn": "arn:aws:sns:eu-central-1:000000000000:payment-creation-event", "Message": "{\"commandId\":\"0ebf6027-0cb9-45e0-bbe1-e6e4f7734cf9\"}", "Timestamp": "2023-11-23T18:14:34.308Z", "SignatureVersion": "1", "Signature": "EXAMPLEpH+..", "SigningCertURL": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-0000000000000000000000.pem", "UnsubscribeURL": "http://localhost:4566/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-central-1:000000000000:payment-creation-event:962cb686-bd6f-4c45-8e13-536a5ea20b31", "MessageAttributes": {"id": {"Type": "String", "Value": "e9e32580-395f-7d38-6ea3-b62746c3b316"}, "contentType": {"Type": "String", "Value": "application/json"}, "timestamp": {"Type": "Number.java.lang.Long", "Value": "1700763274292"}}}

Listener Method signature:

@SqsListener(PAYMENT_CREATION_EVENT_SUBSCRIBER)
fun handleCommand(event: CommandEvent)

I tried also adding defaultSqsListenerContainerFactory, but this didn't helped out:

   @Bean
    fun defaultSqsListenerContainerFactory(objectMapper: ObjectMapper, asyncClient: SqsAsyncClient): SqsMessageListenerContainerFactory<Any> {
        val messageConverter = SqsMessagingMessageConverter()
        messageConverter.setObjectMapper(objectMapper)

        return SqsMessageListenerContainerFactory
            .builder<Any>()
            .configure {
                it.messageConverter(messageConverter)
            }
            .sqsAsyncClient(asyncClient)
            .build()
    }

The same code is successfully working on Spring Boot 2 & Spring Cloud Aws Sqs 2

Maybe I missed some additional config in 3.x version.

@tomazfernandes
Copy link
Contributor

Hi @czujnik81, we have this WIP PR for consuming SQS messages from SNS.

Hopefully we should be able to merge it sooner rather than later.

In the meantime as a workaround you can try implementing a NotificationMessageArgumentResolver.

Let me know if that works for you.

@czujnik81
Copy link
Author

@tomazfernandes the idea is good, I'll just need small help on how I can connect the created NotificationMessageArgumentResolver properly?
I tried with dedicated SqsListenerContainerFactory with the created message converter connected but it didn't helped as well.

@tomazfernandes tomazfernandes added the component: sqs SQS integration related issue label Dec 6, 2023
@tomazfernandes
Copy link
Contributor

@czujnik81, you can use the SqsListenerConfigurer for that.

I'll close this issue since we have this one for the same feature, but feel free to ask further questions here if you have them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: sqs SQS integration related issue
Projects
None yet
Development

No branches or pull requests

2 participants