Skip to content

Fix Event Hubs dedicated builder polluting shared section injection #49254

Merged
rujche merged 9 commits into
mainfrom
rujche/main/fix-dedicated-builder-in-one-section-pollutes-shared-section
May 26, 2026
Merged

Fix Event Hubs dedicated builder polluting shared section injection #49254
rujche merged 9 commits into
mainfrom
rujche/main/fix-dedicated-builder-in-one-section-pollutes-shared-section

Conversation

@rujche
Copy link
Copy Markdown
Member

@rujche rujche commented May 25, 2026

Description

This PR fix #49245

This pull request refactors the Event Hubs auto-configuration in the spring-cloud-azure-autoconfigure module to resolve issues with bean selection and ensure correct wiring of shared and dedicated EventHubClientBuilder beans. 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:

  • The root EventHubClientBuilder is now registered by the explicit bean name springCloudAzureEventHubsClientBuilder instead of by type. Shared EventHubConsumerClient and EventHubProducerClient now 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]
  • The CHANGELOG.md is 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:

All SDK Contribution checklist:

  • The pull request does not introduce [breaking changes]
  • CHANGELOG is updated for new features, bug fixes or other significant changes.
  • I have read the contribution guidelines.

General Guidelines and Best Practices

  • Title of the pull request is clear and informative.
  • There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, see this page.

Testing Guidelines

  • Pull request includes test coverage for the included changes.

…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.
Copilot AI review requested due to automatic review settings May 25, 2026 07:33
@rujche rujche requested review from a team, Netyyyy, moarychan and saragluna as code owners May 25, 2026 07:33
@rujche rujche self-assigned this May 25, 2026
@rujche rujche added azure-spring All azure-spring related issues azure-spring-eventhubs Spring event hubs related issues. labels May 25, 2026
@rujche rujche moved this from Todo to In Progress in Spring Cloud Azure May 25, 2026
@rujche rujche added this to the 2026-06 milestone May 25, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 EventHubClientBuilder bean (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.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

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.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

rujche added 2 commits May 25, 2026 16:19
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.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@rujche rujche requested a review from Copilot May 25, 2026 08:26
@rujche rujche requested a review from j7nw4r May 25, 2026 08:26
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Comment thread sdk/spring/CHANGELOG.md
rujche added 2 commits May 25, 2026 16:35
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.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

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.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

…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.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Copy link
Copy Markdown
Member

@Netyyyy Netyyyy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@rujche rujche merged commit 33e50b4 into main May 26, 2026
31 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Spring Cloud Azure May 26, 2026
@rujche rujche deleted the rujche/main/fix-dedicated-builder-in-one-section-pollutes-shared-section branch May 26, 2026 02:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

azure-spring All azure-spring related issues azure-spring-eventhubs Spring event hubs related issues.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Spring Event Hubs: dedicated builder in one section pollutes shared section's EventHubClientBuilder injection

3 participants