spring-projects / spring-boot

Spring Boot
https://spring.io/projects/spring-boot
Apache License 2.0
74.41k stars 40.51k forks source link

@RestartScope can cause 'Recursive update' exceptions when used with container beans #41571

Closed piotrooo closed 4 days ago

piotrooo commented 1 month ago

After updating Spring Boot from 3.3.1 to 3.3.2, I receive an exception with the following configuration:

@TestConfiguration(proxyBeanMethods = false)
public class ContainersConfiguration {

    @Bean
    @ServiceConnection
    @RestartScope
    PostgreSQLContainer<?> postgresContainer() {
        return new PostgreSQLContainer<>("postgres:16");
    }

    @Bean
    @ServiceConnection
    @RestartScope
    RabbitMQContainer rabbitContainer() {
        try (RabbitMQContainer rabbitMQContainer = new RabbitMQContainer("rabbitmq:3.13")) {
            return rabbitMQContainer
                    .withExposedPorts(5672, 15672);
        }
    }

}

Exception:

Caused by: org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'rabbitContainer': Scope 'restart' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:385)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleBeanPostProcessor.getBeans(TestcontainersLifecycleBeanPostProcessor.java:154)
    at org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleBeanPostProcessor.initializeStartables(TestcontainersLifecycleBeanPostProcessor.java:107)
    at org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleBeanPostProcessor.postProcessAfterInitialization(TestcontainersLifecycleBeanPostProcessor.java:93)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:438)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1809)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
    ... 66 more
Caused by: java.lang.IllegalStateException: Recursive update
    at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1763)
    at org.springframework.boot.devtools.restart.Restarter.getOrAddAttribute(Restarter.java:443)
    at org.springframework.boot.devtools.restart.RestartScopeInitializer$RestartScope.get(RestartScopeInitializer.java:44)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:373)
    ... 73 more

When I remove the @RestartScope from the rabbitContainer bean, everything works as expected. It seems to be related to issue https://github.com/spring-projects/spring-boot/issues/41238.

wilkinsona commented 1 month ago

https://github.com/spring-projects/spring-boot/issues/41552, which describes a problem with @RestartScope and DynamicPropertyRegistry, may also be related.

eddumelendez commented 1 month ago

@piotrooo Can you share a project that reproduces the issue, please? I tried with one of my examples but couldn't reproduce it.

piotrooo commented 1 month ago

Can you share a project that reproduces the issue, please?

@eddumelendez yes! Sure, I even saw you tweet about it recently :wink:

Here is a minimal repro: https://github.com/piotrooo/spring-boot-restart-scope You just need to run DemoApplicationTests.