-
Notifications
You must be signed in to change notification settings - Fork 38.6k
Description
#32271 introduced the automatic registration of DynamicPropertyRegistry
as a bean that can be used in tests, along with support for @DynamicPropertySource
on bean methods. This unfortunately caused spring-projects/spring-boot#41839 due to the fact that Spring Boot already registers a DynamicPropertyRegistry
.
In hindsight, I think Spring Boot should not have directly used DynamicPropertyRegistry
for Testcontainers support, but instead should have created a new interface that deals with the subtle lifecycle issues we're trying to overcome by triggering container events. I would like to change this in Spring Boot 3.4, but it's hard to do in a back compatible way because DynamicPropertyRegistry
is not a Spring Boot interface.
Ideally, in Spring Boot 3.4 we would create a new interface and also create a DynamicPropertyRegistry
bean that logs a warning telling folks to migrate. With Spring Framework also adding DynamicPropertyRegistry
bean support, this is not possible.
Given that there can be very subtle lifecycle issues with using DynamicPropertyRegistry
in a bean (you need to ensure that the bean is created before something else accesses the property). I wonder if we can reconsider the way that Spring Framework will handle this. With the current design, it's quite easy to miss that you should annotate your @Bean
method with @DynamicPropertySource
to ensure that it gets created early enough. It's also quite easy to miss that the registry is updated as a side-effect of creating the bean. One final problem is that it's a little hard to see how you can update a DynamicPropertyRegistry
for an existing bean (rather than one you're creating).
I wonder if we might have time consider a dedicated DynamicPropertyRegistrar
interface instead? The interface would accept the DynamicPropertyRegistry
to be updated.
In code, I anticipate something like this:
@Bean
DynamicPropertyRegistrar apiServerProperties(ApiServer apiServer) {
return (registry) -> registry.add("api.url", apiServer::getUrl);
}
I'm not 100% sure if this will work, but if it does it would free up the DynamicPropertyRegistrar
bean for Spring Boot to create and use to log migration tips. It would also make it impossible to use DynamicPropertyRegistrar
and forget to add @DynamicPropertySource
. Finally, it would give a good place to document how a DynamicPropertyRegistrar
is created early and to be aware of lifecycle issues. Typically, Testcontainer properties aren't a big problem because the Container
beans are distinct from the application. For regular app, the lifecycle issues could be very hard to track down.