GH-3203 Skip standalone bindings in supplierInitializer to avoid ClassCastException for output-only bindings#3204
Closed
seonwooj0810 wants to merge 1 commit into
Conversation
An output-only binding has no backing Supplier/Function bean, but since spring-cloudgh-3166 stopped null-ing out BindableFunctionProxyFactory.getFunctionDefinition(), its function definition is now the binding name. In supplierInitializer that name is looked up in the function catalog, the plain output channel is wrapped, isSupplier() reports true and a SourcePollingChannelAdapter is built on top of the channel. The first poll then casts the channel to Supplier and throws a ClassCastException, breaking output-only bindings that worked in 5.0.1. Guard the supplier initialization with proxyFactory.isFunctionExist() so that standalone bindings (functionExist == false) are skipped, restoring the 5.0.1 behavior without reverting the getFunctionDefinition() change required by spring-cloudgh-3166. Signed-off-by: seonwoo_jung <79202163+seonwooj0810@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3203
Problem
After upgrading to 5.0.2, an output-only binding (e.g.
spring.cloud.stream.output-bindings=testOutput) with no backingSupplier/Functionbean intermittently fails on startup with:Root cause
Commit f042adb (GH-3166) changed
BindableFunctionProxyFactory.getFunctionDefinition()to always return the function definition instead ofisFunctionExist() ? functionDefinition : null:For a standalone output binding the "function definition" is the binding name, so
supplierInitializernow doesfunctionCatalog.lookup("testOutput"), which resolves the plain output channel bean.isSupplier()reportstrue, aSourcePollingChannelAdapteris built on top of the channel, and the first poll casts the channel toSupplier→ClassCastException. In 5.0.1getFunctionDefinition()returnednullfor these bindings, solookup(null)returnednulland they were skipped.Fix
Guard the supplier initialization loop with
proxyFactory.isFunctionExist(). Standalone bindings are constructed withfunctionExist == false(seecreateStandAloneBindingsIfNecessary, wherenew BindableFunctionProxyFactory(..., sourceFunc != null)andsourceFunc == nullfor a binding without a backing function), so they are now skipped — exactly the 5.0.1 behavior. Declared functions are constructed withfunctionExist == true, so real suppliers are unaffected. The change is local tosupplierInitializerand does not revert thegetFunctionDefinition()change that GH-3166 relies on for dynamic binding creation.Test evidence
Added
OutputOnlyBindingSupplierTestswhich starts an app with an output-only binding and asserts noSourcePollingChannelAdapteris created.Expecting empty but was: {"testOutput_spca"=bean 'testOutput_spca'}(the SPCA that triggers the CCE on poll).core/spring-cloud-streammodule test suite is green:Tests run: 32, Failures: 0, Errors: 0, Skipped: 1(pre-existing skip).Verification done: (1) no in-flight PR (
gh pr listsearch empty); (2) no self-claim on the issue; (4) greppedmainand confirmed the commented-out guard ingetFunctionDefinition()and the unguardedsupplierInitializer; reproduced theSourcePollingChannelAdaptercreation deterministically in a test on currentmain.