Skip to content

@ServiceConnection on a PostgreSQL container produces JdbcConnectionDetails but not R2dbcConnectionDetails #51502

Description

@dreamstar-enterprises

@ServiceConnection on a PostgreSQLContainer produces JdbcConnectionDetails but not R2dbcConnectionDetails

Spring Boot version: 4.0.0
Testcontainers version: reproduced on both 2.0.4 and 1.21.2
Java: 25 · Kotlin: 2.4.10 · Build: Gradle, io.spring.dependency-management
Docker: 28.3.2 (macOS, aarch64)

Summary

A PostgreSQLContainer @Bean annotated @ServiceConnection in a @TestConfiguration supplies connection
details to Flyway (JDBC) but not to R2DBC. Flyway connects to the container and migrates successfully, proving
JdbcConnectionDetails is published. In the same context, the application's ConnectionFactory ignores the
container and uses whatever spring.r2dbc.url resolves to, which means R2dbcConnectionDetails is absent.

Because the fallback is a working property rather than an error, this fails as an obscure connection error to
whatever host the property names, rather than as a missing-bean or misconfiguration message.

Reproduction

@TestConfiguration(proxyBeanMethods = false)
class ContainerConfiguration {

    @Bean
    @ServiceConnection
    fun postgres(): PostgreSQLContainer = PostgreSQLContainer("postgres:17")
}

@SpringBootApplication
@Import(ContainerConfiguration::class)
class TestApplication
@SpringBootTest(classes = [TestApplication::class])
@ActiveProfiles("test")
class SomeIntegrationTest { /* autowires a repository backed by R2DBC */ }

application-test.yaml:

spring:
  r2dbc:
    url: r2dbc:postgresql://ignored.invalid:5432/ignored   # deliberately unreachable
    pool:
      enabled: true

Expected: the container's R2dbcConnectionDetails takes precedence and the application connects to the
container, as it does for Flyway over JDBC.

Actual:

org.springframework.dao.DataAccessResourceFailureException: Failed to obtain R2DBC Connection
Caused by: io.r2dbc.postgresql.PostgresqlConnectionFactory$PostgresConnectionException:
          [08003] Cannot connect to ignored.invalid/<unresolved>:5432
Caused by: java.net.UnknownHostException: ignored.invalid

The container is running and healthy throughout.

Evidence that R2dbcConnectionDetails is genuinely absent

R2dbcAutoConfiguration.propertiesR2dbcConnectionDetails is annotated
@ConditionalOnMissingBean(R2dbcConnectionDetails.class). The properties-backed implementation is therefore
created only when no other R2dbcConnectionDetails bean exists. Since the application demonstrably uses the
property value, the container's bean is not present.

Cross-check: removing spring.r2dbc.url from the test profile and giving the placeholder in the main
application.yaml an unreachable default made the application connect to that default instead — again showing
the property is being consulted rather than overridden.

Flyway, in the same context and from the same container bean, connects correctly and migrates the full schema.
So @ServiceConnection processing is working; only the R2DBC side produces nothing.

What was ruled out

Each of these was changed independently and the behaviour did not change:

variable values tried
Testcontainers version 2.0.4 (org.testcontainers.postgresql.PostgreSQLContainer) and 1.21.2 (org.testcontainers.containers.PostgreSQLContainer)
container image custom image built via ImageFromDockerfile + asCompatibleSubstituteFor("postgres"), and stock postgres:17
where the configuration is imported @Import on the @SpringBootApplication class named in @SpringBootTest(classes = …), and @Import directly on the test class
connection name default, and explicit @ServiceConnection("postgresql")
Flyway enabled and disabled, to remove it as a factor

The factory itself appears correctly wired:

  • org.springframework.boot.r2dbc.testcontainers.PostgresR2dbcContainerConnectionDetailsFactory is present in
    spring-boot-r2dbc-4.0.0.jar
  • it is registered in that jar's META-INF/spring.factories
  • its generic parameter is org.testcontainers.postgresql.PostgreSQLContainer — the exact class of the bean
  • its required class, io.r2dbc.spi.ConnectionFactoryOptions, is on the test runtime classpath
    (io.r2dbc:r2dbc-spi:1.0.0.RELEASE, org.postgresql:r2dbc-postgresql:1.1.1.RELEASE)

Note the jar also ships DeprecatedPostgresR2dbcContainerConnectionDetailsFactory, whose generic parameter is the
1.x org.testcontainers.containers.PostgreSQLContainer<?>. Neither path produced details in our testing.

spring-boot-testcontainers-4.0.0.jar itself contains no Postgres classes; the factories live in the
technology-specific modules, which may be relevant to how they are discovered.

Workaround

Publishing the connection as system properties from the container works, since system properties outrank
configuration files:

init {
    CONTAINER.start()
    System.setProperty("spring.r2dbc.url",
        "r2dbc:postgresql://${CONTAINER.host}:${CONTAINER.firstMappedPort}/$DATABASE_NAME")
    System.setProperty("spring.r2dbc.username", CONTAINER.username)
    System.setProperty("spring.r2dbc.password", CONTAINER.password)
}

Notes

  • The application is WebFlux with spring.main.web-application-type: none in the test profile.
  • Dependency versions are managed by io.spring.dependency-management; the org.testcontainers coordinates are
    not managed by it under Boot 4 and carry explicit versions.
  • We did not test the static-field / @ImportTestcontainers style of declaring the container, only the
    @Bean + @ServiceConnection style shown above.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions