The DockerComposeLifecycleManager#start() method is called twice on startup of a spring boot application, resulting in an error:
The bean 'jdbcConnectionDetailsForDemoPostgres' could not be registered. A bean with that name has already been defined and overriding is disabled.
I get it that this is a problem, the cause however I'm a bit in the dark about.
I discovered that the DockerComposeLifecycleManager#start() method is called twice. Both times from DockerComposeListener#onApplicationEvent(ApplicationPreparedEvent event).
Going up the stack the first call originates from SpringApplication#310 (prepareContext) and the second from SpringApplication#311 (refreshContext).
It only happens with spring-cloud-starter-config as a dependency.
Possible casue
Digging on the internet I suspect it has something to do with the applicationContext now being in a hierarchy :
Why Spring Boot Application logs that it started twice after adding spring-cloud-bus dependency
So if this is the case I think the mentioned check (if (event.getApplicationContext().equals(this.applicationContext)) {) should be in DockerComposeListener, but I could be totally wrong and this is something else, I'm not that familiar with cloud config yet.
About ApplicationEvent and BootStrap #1119 and Best way in custom Spring Boot Starter library to read current properties and set new ones based on values might also be related.
Reproduce
To reproduce create a Maven Spring Boot 3.1.0 with 'Docker Compose Support', 'Config Client' and 'Web' on start.spring.io
Replace compose.yaml with:
version: "3.8"
services:
postgresql:
image: 'postgres:15.3-bullseye'
container_name: 'demo-postgres'
restart: always
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DB=demodb
ports:
- "5432:5432"
user: root
volumes:
- 'pg_data:/var/lib/postgresql/data'
volumes:
pg_data:
Add the following to application.properties:
spring.config.import=optional:configserver:
To 'fix' the problem comment the line added to application.properties and comment the dependency spring-cloud-starter-config in pom.xml.
I'm impressed with the feature set of spring-boot-docker-compose by the way, it will make a lot of things easier for us!
Comment From: wilkinsona
Thanks for the report. There's no longer a context hierarchy when using Spring Cloud in this way. In this case, the problem's occurring because Spring Cloud's RestartListener is re-publishing the ApplicationPreparedEvent when it receives the ContextRefreshedEvent. I'll discuss this with the Spring Cloud team.
Comment From: spencergibb
From a slack conversation
It appears, moving to a custom event, rather than saving the original AppliclationPreparedEvent fixes the test failures
So I have a fix in spring-cloud-commons ready.
Comment From: wilkinsona
Thanks, @spencergibb. I'll close this one in favor of the fix in Spring Cloud. Is there an issue tracking the changes?
Comment From: spencergibb
No. I'll create one shortly
Comment From: spencergibb
https://github.com/spring-cloud/spring-cloud-commons/issues/1248