micronaut-data icon indicating copy to clipboard operation
micronaut-data copied to clipboard

R2DBC Tests startup fail with Postgresql

Open bzolivereckle opened this issue 2 years ago • 6 comments

Expected Behavior

Tests running

Actual Behaviour

While starting the tests io.r2dbc.spi.NoSuchOptionException: No value found for host is throwsn.

Steps To Reproduce

Having this configuration

micronaut:
  security:
    enabled: false
  metrics:
    enabled: false
datasources:
  default:
    url: jdbc:tc:postgresql:12:///postgres
    driverClassName: org.testcontainers.jdbc.ContainerDatabaseDriver
    default-schema: myschema
    schema: myschema

r2dbc:
  datasources:
    default:
      url: r2dbc:tc:postgresql:///postgres?TC_IMAGE_TAG=12
      options:
        currentSchema: myschema

the startup of the tests fail within IntelliJ Thowing that exception

Bean definition [io.r2dbc.spi.ConnectionFactory] could not be loaded: Error instantiating bean of type  [io.r2dbc.spi.ConnectionFactory]

Message: No value found for host
Path Taken: ConnectionFactory.connectionFactory(ConnectionFactoryOptions options)
io.micronaut.context.exceptions.BeanInstantiationException: Bean definition [io.r2dbc.spi.ConnectionFactory] could not be loaded: Error instantiating bean of type  [io.r2dbc.spi.ConnectionFactory]

Message: No value found for host
Path Taken: ConnectionFactory.connectionFactory(ConnectionFactoryOptions options)
	at app//io.micronaut.context.DefaultBeanContext.initializeContext(DefaultBeanContext.java:1921)
	at app//io.micronaut.context.DefaultApplicationContext.initializeContext(DefaultApplicationContext.java:249)
	at app//io.micronaut.context.DefaultBeanContext.readAllBeanDefinitionClasses(DefaultBeanContext.java:3326)
	at app//io.micronaut.context.DefaultBeanContext.finalizeConfiguration(DefaultBeanContext.java:3684)
	at app//io.micronaut.context.DefaultBeanContext.start(DefaultBeanContext.java:341)
	at app//io.micronaut.context.DefaultApplicationContext.start(DefaultApplicationContext.java:194)
	at app//io.micronaut.test.extensions.AbstractMicronautExtension.startApplicationContext(AbstractMicronautExtension.java:433)
	at app//io.micronaut.test.extensions.AbstractMicronautExtension.beforeClass(AbstractMicronautExtension.java:314)
	at app//io.micronaut.test.extensions.junit5.MicronautJunit5Extension.beforeAll(MicronautJunit5Extension.java:84)
	at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$12(ClassBasedTestDescriptor.java:395)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:395)
	at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:211)
	at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:84)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:148)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at [email protected]/java.util.ArrayList.forEach(ArrayList.java:1511)
	at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
	at app//org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at app//org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at app//org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at app//org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
	at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at [email protected]/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at [email protected]/java.lang.reflect.Method.invoke(Method.java:568)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at jdk.proxy2/jdk.proxy2.$Proxy5.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: io.micronaut.context.exceptions.BeanInstantiationException: Error instantiating bean of type  [io.r2dbc.spi.ConnectionFactory]

Message: No value found for host
Path Taken: ConnectionFactory.connectionFactory(ConnectionFactoryOptions options)
	at app//io.micronaut.context.DefaultBeanContext.resolveByBeanFactory(DefaultBeanContext.java:2367)
	at app//io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:2305)
	at app//io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:2251)
	at app//io.micronaut.context.DefaultBeanContext.createRegistration(DefaultBeanContext.java:3016)
	at app//io.micronaut.context.SingletonScope.getOrCreate(SingletonScope.java:80)
	at app//io.micronaut.context.DefaultBeanContext.findOrCreateSingletonBeanRegistration(DefaultBeanContext.java:2918)
	at app//io.micronaut.context.DefaultBeanContext.loadContextScopeBean(DefaultBeanContext.java:2737)
	at app//io.micronaut.context.DefaultBeanContext.initializeContext(DefaultBeanContext.java:1915)
	... 66 more
Caused by: io.r2dbc.spi.NoSuchOptionException: No value found for host
	at app//io.r2dbc.spi.ConnectionFactoryOptions.getRequiredValue(ConnectionFactoryOptions.java:165)
	at app//io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider.lambda$fromConnectionFactoryOptions$4(PostgresqlConnectionFactoryProvider.java:284)
	at app//io.r2dbc.postgresql.OptionMapper$Otherwises$2.otherwise(OptionMapper.java:207)
	at app//io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider.fromConnectionFactoryOptions(PostgresqlConnectionFactoryProvider.java:283)
	at app//io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider.builder(PostgresqlConnectionFactoryProvider.java:229)
	at app//io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider.create(PostgresqlConnectionFactoryProvider.java:234)
	at app//io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider.create(PostgresqlConnectionFactoryProvider.java:51)
	at app//io.r2dbc.spi.ConnectionFactories.find(ConnectionFactories.java:110)
	at app//io.r2dbc.pool.PoolingConnectionFactoryProvider.buildConfiguration(PoolingConnectionFactoryProvider.java:189)
	at app//io.r2dbc.pool.PoolingConnectionFactoryProvider.create(PoolingConnectionFactoryProvider.java:167)
	at app//io.r2dbc.pool.PoolingConnectionFactoryProvider.create(PoolingConnectionFactoryProvider.java:43)
	at app//io.r2dbc.spi.ConnectionFactories.find(ConnectionFactories.java:110)
	at app//io.r2dbc.spi.ConnectionFactories.get(ConnectionFactories.java:140)
	at app//io.micronaut.r2dbc.R2dbcConnectionFactoryBean.connectionFactory(R2dbcConnectionFactoryBean.java:68)
	at app//io.micronaut.r2dbc.$R2dbcConnectionFactoryBean$ConnectionFactory2$Definition.build(Unknown Source)
	at app//io.micronaut.context.BeanDefinitionDelegate.build(BeanDefinitionDelegate.java:161)
	at app//io.micronaut.context.DefaultBeanContext.resolveByBeanFactory(DefaultBeanContext.java:2354)
	... 73 more

having that gradle dependencies

    implementation("io.micronaut:micronaut-http-client")
    implementation("io.micronaut:micronaut-runtime")
    implementation("javax.annotation:javax.annotation-api")
    runtimeOnly("ch.qos.logback:logback-classic:1.4.1")

    // validation
    kapt("io.micronaut:micronaut-http-validation")
    implementation("io.micronaut:micronaut-validation")
    // kotlin
    runtimeOnly("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4")
    implementation("org.jetbrains.kotlin:kotlin-reflect:1.7.10")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10")
    implementation("io.micronaut.kotlin:micronaut-kotlin-runtime")
    // data jdbc
    runtimeOnly("io.micronaut.sql:micronaut-jdbc-hikari")
    kapt("io.micronaut.data:micronaut-data-processor")
    runtimeOnly("org.postgresql:postgresql:42.5.0")
    implementation("jakarta.annotation:jakarta.annotation-api")
    compileOnly("jakarta.persistence:jakarta.persistence-api:3.1.0")
    // flyway
    implementation("io.micronaut.flyway:micronaut-flyway")
    // R2DBC
    implementation("io.micronaut.r2dbc:micronaut-r2dbc-core")
    implementation("io.micronaut.data:micronaut-data-r2dbc")
    runtimeOnly("org.postgresql:r2dbc-postgresql")
    implementation("io.r2dbc:r2dbc-pool:0.9.2.RELEASE")
    // kafka
    implementation("io.micronaut.kafka:micronaut-kafka")
    // doc
    kapt("io.micronaut.openapi:micronaut-openapi")
    implementation("io.swagger.core.v3:swagger-annotations")
    // caching
    implementation("io.micronaut.cache:micronaut-cache-caffeine")
    // security
    implementation("io.micronaut.security:micronaut-security")
    kapt("io.micronaut.security:micronaut-security-annotations")
    // testcontainer
    testImplementation("org.testcontainers:junit-jupiter")
    testImplementation("org.testcontainers:postgresql")
    testImplementation("org.testcontainers:r2dbc")
    testImplementation("org.testcontainers:testcontainers")
    // co routines
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
    // location
    implementation("de.grundid.opendatalab:geojson-jackson:1.14")
    // reactor
    implementation("io.micronaut.reactor:micronaut-reactor")
    implementation("io.micronaut.reactor:micronaut-reactor-http-client")
    // monitoring
    implementation("io.micronaut:micronaut-management")
    implementation("io.micronaut.micrometer:micronaut-micrometer-core")
    implementation("io.micronaut.micrometer:micronaut-micrometer-registry-prometheus")

P.S i have to add the implementation("io.r2dbc:r2dbc-pool:0.9.2.RELEASE") caused by having micrometer enabled. But thats another story.

Environment Information

Windows 10 Kotlin 1.7.10 OpenJDK Runtime Environment Temurin-17.0.4+8 (build 17.0.4+8) JUnit 5.9.0

Example Application

No response

Version

3.7.0

bzolivereckle avatar Sep 22 '22 07:09 bzolivereckle

It looks like something is wrong with your configuration, you should see TestcontainersR2DBCConnectionFactoryProvider if testcontainers were picked up.

dstepanov avatar Sep 22 '22 08:09 dstepanov

so where could i check the configuration? i try to create some stub it with launch.micronaut.io and adopt it to mine. gradle config, application.yml anything else?

bzolivereckle avatar Sep 22 '22 08:09 bzolivereckle

Do you have test resources Gradle plugin applied? You can debug ConnectionFactories to see why it is picked up.

dstepanov avatar Sep 22 '22 08:09 dstepanov

Yes i have id("io.micronaut.test-resources") version "3.6.0"

When i debug ConnectionFactories i have two providers

  • TestcontainersR2DBCConnectionFactoryProvider which is not supporting ConnectionFactoryOptions
  • PoolingConnectionFactoryProvider which is supporting ConnectionFactoryOptions

bzolivereckle avatar Sep 22 '22 10:09 bzolivereckle

Please try without the plugin.

dstepanov avatar Sep 22 '22 10:09 dstepanov

deactivating the plugin solved the issue.

May i ask one more thing. I am using flyway and a custom database schema, lets call it 'myschema' I can see from the logs that within the test the flyway stuff is running and using the correct schema.

But when i access the database using R2DBC i get an Exception

io.r2dbc.postgresql.ExceptionFactory$PostgresqlBadGrammarException: [42P01] relation "xyz" does not exist

That happens only within testing. When i run the application, everything is fine. I also have an example for that: https://github.com/Black-Forrest-Development/ReactiveCrudExample

Edit: seems to me its setting up two testcontainers one for flyway and one for r2dbc, thats why the schema is not there.

bzolivereckle avatar Sep 22 '22 11:09 bzolivereckle

I'm facing the same issue, when trying to use test-containers with a R2DBC (to interact with the DB) AND JDBC (To execute migrations with flyway or Liquibase, there are 2 different containers being created.

Here's the properties I'm using

datasources:
  default:
    url: jdbc:tc:postgresql:///postgres?TC_IMAGE_TAG=13.5
    driverClassName: org.testcontainers.jdbc.ContainerDatabaseDriver
    dialect: postgres

liquibase:
  datasources:
    default:
      change-log: 'classpath:db/liquibase-changelog.xml'

r2dbc:
  datasources:
    default:
      url: r2dbc:tc:postgresql:///postgres?TC_IMAGE_TAG=13.5
      dialect: postgres

And two different containers are being created: image

It should only create one container DB and use it for both (R2DBC and JDBC)

@bzolivereckle , did you find any solution/workaround for this=

luisospina-sealed avatar Oct 12 '22 15:10 luisospina-sealed

it works if you use the new built in test resources support instead of TC urls

graemerocher avatar Oct 12 '22 20:10 graemerocher

@luisospina-sealed we figured something out based on that solution https://www.zsiegel.com/2022/01/25/Micronaut-JDBC-R2DBC-Flyway-multiple-schemas but thats not an elegant solution

@graemerocher where could i read something about the test resources support the only thing i found was that https://micronaut-projects.github.io/micronaut-test-resources/latest/guide/#modules-databases but thats not realy helping me in that case

bzolivereckle avatar Nov 11 '22 17:11 bzolivereckle

@bzolivereckle Perhaps report an issue here https://github.com/micronaut-projects/micronaut-test-resources/issues with how the documentation can be improved

graemerocher avatar Nov 11 '22 18:11 graemerocher

@graemerocher okay, thx

bzolivereckle avatar Nov 11 '22 19:11 bzolivereckle

I'm facing the same issue, when trying to use test-containers with a R2DBC (to interact with the DB) AND JDBC (To execute migrations with flyway or Liquibase, there are 2 different containers being created.

Here's the properties I'm using

datasources:
  default:
    url: jdbc:tc:postgresql:///postgres?TC_IMAGE_TAG=13.5
    driverClassName: org.testcontainers.jdbc.ContainerDatabaseDriver
    dialect: postgres

liquibase:
  datasources:
    default:
      change-log: 'classpath:db/liquibase-changelog.xml'

r2dbc:
  datasources:
    default:
      url: r2dbc:tc:postgresql:///postgres?TC_IMAGE_TAG=13.5
      dialect: postgres

And two different containers are being created: image

It should only create one container DB and use it for both (R2DBC and JDBC)

@bzolivereckle , did you find any solution/workaround for this=

Did you find a solution for this?

gitorko avatar May 07 '24 18:05 gitorko