Skip to content

#1587 Support routing for Message<T> parameters in @SqsHandler#1644

Open
alexisgra wants to merge 1 commit into
awspring:mainfrom
alexisgra:1587-route-message-envelope-payload-in-sqs-handler
Open

#1587 Support routing for Message<T> parameters in @SqsHandler#1644
alexisgra wants to merge 1 commit into
awspring:mainfrom
alexisgra:1587-route-message-envelope-payload-in-sqs-handler

Conversation

@alexisgra

Copy link
Copy Markdown
Contributor

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

When using @SqsListener with multiple @SqsHandler methods, routing is unable to route messages to a handler with Message<T> envelope as parameter.

The cause is in CompositeInvocableHandler.isPayloadAssignable: for a Message<T> parameter it compared
the payload against Message.class, which never matches a concrete payload. So the handler was never selected. Following Tomas comment in #1587 , the fix detects a Message typed parameter and resolves its generic type, then matches the payload against that generic instead.

⚠️ Known breaking change — open for discussion.

Because a Message<T> parameter is now considered payload-assignable, a single handler that declares both the Pojo and its Message (the workaround suggested in #1587) now resolves two payload-assignable parameters and throws "Ambiguous payload parameter for ..." instead of routing on the Pojo.

Handler (payload = Pojo) Before This PR
handle(Pojo) matches 🟢 matches 🟢
handle(Message<Pojo>) no match 🔴 matches 🟢
handle(Pojo, Message<Pojo>) matches 🟢 throws (breaking change) ⚠️

A change in findCandidate method can make the last case route on the Pojo again (treat Message<T> as the
envelope, not a second payload). I've left it out so you can decide the intended semantics.
The behavior is pinned by throwsWhenPayloadAndMessageParametersOnSameMethod.

💡 Motivation and Context

Fix #1587

💚 How did you test it?

  • Added unit tests in CompositeInvocableHandlerTest covering :

    • Message<T> routing.
    • Ambiguity across handlers when a plain and a Message<T> handler match the same payload type.
    • Ambiguity within one method declaring both a plain and a Message<T> parameter of the same type.
  • Added integration test in SqsIntegrationTests, asserting a Message<String> handler is selected and the default handler is not invoked.

📝 Checklist

  • I reviewed submitted code
  • I added tests to verify changes
  • I updated reference documentation to reflect the change
  • All tests passing
  • No breaking changes

🔮 Next steps

Decide the intended behavior for a handler declaring both a Pojo and a Message<Pojo> as parameters:

  1. Keep it as an ambiguity error (current behavior - breaking change)
  2. Route on the Pojo and treat the Message<T> as the envelope.

In my opinion, handle(Message<Pojo>) should now replace handle(Pojo, Message<Pojo>); the dual-parameter
form becomes redundant once the envelope routes on its own. However, since the workaround was publicly
documented, I understand you may prefer to avoid a breaking change here.

I'm happy to push an adjustment for 2, if that's preferred.

@github-actions github-actions Bot added component: sqs SQS integration related issue type: documentation Documentation or Samples related issue labels Jun 30, 2026
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 type: documentation Documentation or Samples related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support @SqsHandler routing for Message<T> parameters

1 participant