Fix Event Hubs dedicated builder polluting shared section injection #49254
Merged
rujche merged 9 commits intoMay 26, 2026
Merged
Conversation
…49245) The root EventHubClientBuilder used a type-based @ConditionalOnMissingBean, so when either DedicatedConsumerConnectionConfiguration or DedicatedProducerConnectionConfiguration activated, its named-but-EventHubClientBuilder-typed bean suppressed the root builder. The opposite section's SharedConsumer/SharedProducerConnectionConfiguration then satisfied its @ConditionalOnBean(EventHubClientBuilder.class) against the dedicated bean and injected it via type, so the shared client targeted the wrong event hub. - Name the root builder springCloudAzureEventHubsClientBuilder and use @ConditionalOnMissingBean(name = ...) so dedicated builders no longer suppress it. - Switch SharedConsumer/SharedProducerConnectionConfiguration to @ConditionalOnBean(name = ...) and inject EventHubClientBuilder via @qualifier(EVENT_HUB_CLIENT_BUILDER_BEAN_NAME). - Add regression tests for asymmetric (one-side dedicated, one-side shared) configurations in both consumer and producer test classes.
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a Spring Event Hubs autoconfiguration wiring bug where a dedicated (consumer/producer) EventHubClientBuilder bean could suppress the root builder and then be incorrectly injected into the opposite “shared” section, causing clients to target the wrong Event Hub.
Changes:
- Names the root
EventHubClientBuilderbean (springCloudAzureEventHubsClientBuilder) and switches the root builder registration to a name-based@ConditionalOnMissingBean. - Updates shared consumer/producer configurations to gate on, and inject, the specifically named root builder via
@ConditionalOnBean(name=...)+@Qualifier. - Adds regression tests for asymmetric “one side dedicated, other side shared” scenarios and documents the fix in the Spring changelog.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsClientBuilderConfiguration.java | Registers the root builder under a fixed bean name and changes missing-bean condition to be name-based. |
| sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsConsumerClientConfiguration.java | Ensures shared consumer path requires and injects the named root builder, preventing cross-section pollution. |
| sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProducerClientConfiguration.java | Ensures shared producer path requires and injects the named root builder, preventing cross-section pollution. |
| sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureContextUtils.java | Introduces a constant for the root Event Hubs client builder bean name. |
| sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsConsumerClientConfigurationTests.java | Adds consumer-side asymmetric regression tests and updates shared-path builder bean registration to use the new name. |
| sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProducerClientConfigurationTests.java | Adds producer-side asymmetric regression tests and updates shared-path builder bean registration to use the new name. |
| sdk/spring/CHANGELOG.md | Adds a bugfix entry describing the autoconfiguration issue and the fix. |
…ic regression assertions - Make root EventHubClientBuilderFactory @ConditionalOnMissingBean name-based, consistent with the dedicated factory beans, so a user-provided differently-named factory does not suppress the named one. - Strengthen the four asymmetric regression tests to assert the opposite-side DedicatedXxxConnectionConfiguration is actually activated, and assert multiple EventHubClientBuilder beans coexist in the shared-injection cases, so the tests truly exercise the failure mode the fix targets.
The previous name-based @ConditionalOnMissingBean broke backward compatibility: a user-defined EventHubClientBuilder bean registered under a custom name no longer suppressed the auto-configured root builder. Add a custom condition that ignores only the three reserved auto-config bean names (root, consumer-dedicated, producer-dedicated) so any other EventHubClientBuilder bean is treated as a user override and suppresses auto-configuration, while still allowing the dedicated builders to coexist with the root one.
Spring Boot's @ConditionalOnMissingBean defaults to SearchStrategy.ALL, which walks the entire bean factory hierarchy. Use BeanFactoryUtils.beanNamesForTypeIncludingAncestors so the custom condition matches that behavior and detects a user-defined EventHubClientBuilder bean registered in a parent ApplicationContext.
…tion-pollutes-shared-section
Remove the custom OnMissingUserDefinedEventHubClientBuilderCondition and rely solely on @ConditionalOnMissingBean(name = EVENT_HUB_CLIENT_BUILDER_BEAN_NAME). The override contract is now uniformly name-based: to replace the auto-configured root builder (and have shared EventHubConsumerClient/EventHubProducerClient pick up the override) the user must register their bean under springCloudAzureEventHubsClientBuilder. A user-supplied bean under any other name no longer suppresses the auto-configured root and is not wired into the shared clients. Update userDefinedEventHubsClientBuilderProvidedShouldNotAutoconfigure to register under the reserved name, add a new userDefinedEventHubsClientBuilderUnderCustomNameShouldNotSuppressAutoconfigure asserting the new coexistence behavior, and tighten the CHANGELOG breaking-change entry.
Copilot review (PR #49254) flagged two asymmetric regression tests that only assert non-activation of the opposite shared section when its event-hub-name property is absent. Because the opposite AzureEventHubs{Consumer,Producer}ClientConfiguration is gated by @ConditionalOnAnyProperty, it cannot load in those scenarios regardless of the builder-pollution fix, so the tests are false positives that would pass even on buggy code. The true regression scenarios remain covered by sharedConsumerInjectsRootBuilderWhenProducerHasDedicatedOverride and sharedProducerInjectsRootBuilderWhenConsumerHasDedicatedOverride, which set the global event-hub-name and verify the shared section binds to the root builder.
…tions Per Copilot review on PR #49254: the existing sharedConsumerInjectsRootBuilderWhenProducerHasDedicatedOverride and sharedProducerInjectsRootBuilderWhenConsumerHasDedicatedOverride tests only verified that multiple EventHubClientBuilder beans coexist and that a single shared client is created. They did not directly assert that the shared client was built from the root (base-eventhub) builder rather than the opposite section's dedicated (override-eventhub) builder, so a future regression of type-based wiring could still pass. Add EventHubProducerClient.getEventHubName() / EventHubConsumerClient.getEventHubName() (and the async client counterparts) assertions equal to base-eventhub to pin the actual #49245 invariant.
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.
Description
This PR fix #49245
This pull request refactors the Event Hubs auto-configuration in the
spring-cloud-azure-autoconfiguremodule to resolve issues with bean selection and ensure correct wiring of shared and dedicatedEventHubClientBuilderbeans. The changes introduce name-based bean registration and injection, preventing accidental suppression or miswiring of shared clients when dedicated consumer or producer overrides are present. Additional tests are added to guard against regressions and verify correct behavior.Event Hubs auto-configuration improvements:
EventHubClientBuilderis now registered by the explicit bean namespringCloudAzureEventHubsClientBuilderinstead of by type. SharedEventHubConsumerClientandEventHubProducerClientnow inject this bean by name, ensuring user-defined builders under other names do not override or interfere with the auto-configured root builder. [1] [2] [3] [4] [5] [6] [7] [8]CHANGELOG.mdis updated to document this change and clarify how to override the root builder using the new bean name. It also describes the bug fix for incorrect builder injection when dedicated overrides are present.Testing and regression coverage:
EventHubClientBuilder, and new tests are added to verify that shared consumers and producers always inject the root builder, even when dedicated overrides exist. This ensures the fix for issue Spring Event Hubs: dedicated builder in one section pollutes shared section's EventHubClientBuilder injection #49245 is covered and prevents future regressions. [1] [2] [3] [4] [5] [6]All SDK Contribution checklist:
General Guidelines and Best Practices
Testing Guidelines