Skip to content

Unsubscribe of message handler while processing PostgresSubscribableChannel.notifyUpdate() #10362

@bertschneider

Description

@bertschneider

Describe the bug

We encountered a MessageDeliveryException during application shutdown.

The stack trace suggests that PostgresSubscribableChannel was still processing messages in its pollAndDispatchMessage loop while Spring had already unregistered the corresponding message handlers. This led to a org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers error.

From what I can tell, Spring shuts components down in the expected order, but any in-flight messages may no longer be dispatchable at that point.

Would it make sense for PostgresSubscribableChannel to block on unsubscribe calls while a message is being dispatched, and then exit the polling loop once the message handling has completed? Since this situation likely only occurs asynchronously during shutdown, relying on error handling seems fragile, as at that point Spring may have already stopped other required beans.

A test reproducing the situation can be found at https://github.com/bertschneider/spring-integration-notifyUpdate/blob/main/src/test/java/com/example/springintegration/SpringIntegrationITest.java

Stack trace:

org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
	at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:154) ~[spring-integration-core-6.5.1.jar:6.5.1]
	at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121) ~[spring-integration-core-6.5.1.jar:6.5.1]
	at org.springframework.integration.jdbc.channel.PostgresSubscribableChannel.dispatch(PostgresSubscribableChannel.java:231) ~[spring-integration-jdbc-6.5.1.jar:6.5.1]
	at org.springframework.integration.jdbc.channel.PostgresSubscribableChannel.lambda$doPollAndDispatchMessage$4(PostgresSubscribableChannel.java:220) ~[spring-integration-jdbc-6.5.1.jar:6.5.1]
	at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:357) ~[spring-retry-2.0.12.jar:na]
	at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:230) ~[spring-retry-2.0.12.jar:na]
	at org.springframework.integration.jdbc.channel.PostgresSubscribableChannel.lambda$doPollAndDispatchMessage$5(PostgresSubscribableChannel.java:220) ~[spring-integration-jdbc-6.5.1.jar:6.5.1]
	at java.base/java.util.Optional.map(Optional.java:260) ~[na:na]
	at org.springframework.integration.jdbc.channel.PostgresSubscribableChannel.doPollAndDispatchMessage(PostgresSubscribableChannel.java:220) ~[spring-integration-jdbc-6.5.1.jar:6.5.1]
	at org.springframework.integration.jdbc.channel.PostgresSubscribableChannel.pollAndDispatchMessage(PostgresSubscribableChannel.java:190) ~[spring-integration-jdbc-6.5.1.jar:6.5.1]
	at org.springframework.integration.jdbc.channel.PostgresSubscribableChannel.lambda$notifyUpdate$0(PostgresSubscribableChannel.java:183) ~[spring-integration-jdbc-6.5.1.jar:6.5.1]
	at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]

Expected behavior

Processing of in-flight messages is finished.

In what version(s) of Spring Integration are you seeing this issue?

6.5.1

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions