Skip to content

Bind a fresh instance before resetting a rebound bean - #1781

Merged
ryanjbaxter merged 1 commit into
spring-cloud:5.0.xfrom
ryanjbaxter:bind-a-fresh-instance-before-resetting
Nov 2, 2026
Merged

ryanjbaxter merged 1 commit into
spring-cloud:5.0.xfrom
ryanjbaxter:bind-a-fresh-instance-before-resetting

Conversation

@ryanjbaxter

@ryanjbaxter ryanjbaxter commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1727

Since 5.0.2 (#1680), ConfigurationPropertiesRebinder resets the live @ConfigurationProperties bean to its class-level defaults and only then re-binds it. Between those two steps a concurrent reader sees the unbound state

  • A new instance of the bean's class is created, autowired and bound through ConfigurationPropertiesBindingPostProcessor before the live bean is touched. Its state is then copied onto the live bean with the existing resetProperties walk.
  • The fresh instance is autowired deliberately. Otherwise an injected setter (for example @Autowired) would be copied onto the live bean as null and reopen the window.
  • Getter-only collections and maps are no longer cleared and refilled during the copy. Equal contents are left alone, a list gets the new elements before the stale ones are removed, a set gets addAll then retainAll, and a map gets putAll then keySet().retainAll.

Known limitation:

The bean is initialized again after the copy, and Spring Boot's CollectionBinder.merge updates an existing, modifiable collection by clearing it and adding the bound elements. A collection property that has a value in the Environment can therefore still be briefly empty during a rebind. Maps are not affected. This is documented in the reference docs and the class Javadoc. Addressing this that would mean re-implementing initializeBean without the binding post-processor, which is not something I think we should do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

resetBeanToDefaults transiently nulls nested @ConfigurationProperties objects, NPEing concurrent request threads

2 participants