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