cockroachdbspring-data-r2dbcr2dbcr2dbc-postgresqlcockroachcloud

Can't connect to CockroachCloud Free (beta) Cluster from a Spring Data R2DBC driver


I created CrockroachCloud Free (beta) Cluster and I was able to connect to the DB with the command line. But when I tried to connect from a Spring Data R2DBC driver I get an exception.

I'm using following connection string in my application.yml:

server:
  port: ${PORT:8080}
spring:
  r2dbc:
    url: r2dbc:postgres://{username}:{password}@free-tier.gcp-us-central1.cockroachlabs.cloud:26257/{dbname}?ssl=true&sslmode=verify-full&sslrootcert=cc-ca.crt&options=--cluster={clustername}-554
    username: {username}
    password: {password}

then I get the following exception:

"Failed to obtain R2DBC Connection; nested exception is io.r2dbc.postgresql.client.ReactorNettyClient$PostgresConnectionClosedException: Connection unexpectedly closed"

complete stack trace:

org.springframework.dao.DataAccessResourceFailureException: Failed to obtain R2DBC Connection; nested exception is io.r2dbc.postgresql.client.ReactorNettyClient$PostgresConnectionClosedException: Connection unexpectedly closed\r\n\tat org.springframework.data.r2dbc.connectionfactory.ConnectionFactoryUtils.lambda$getConnection$0(ConnectionFactoryUtils.java:70)\r\n\tSuppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: \nError has been observed at the following site(s):\n\t|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]\n\t|_ checkpoint ⇢ HTTP POST \"/api/countries\" [ExceptionHandlingWebHandler]\nStack trace:\r\n\t\tat org.springframework.data.r2dbc.connectionfactory.ConnectionFactoryUtils.lambda$getConnection$0(ConnectionFactoryUtils.java:70)\r\n\t\tat reactor.core.publisher.Mono.lambda$onErrorMap$30(Mono.java:3325)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:88)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:100)\r\n\t\tat reactor.core.publisher.FluxRetry$RetrySubscriber.onError(FluxRetry.java:88)\r\n\t\tat reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onError(FluxPeekFuseable.java:227)\r\n\t\tat reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:165)\r\n\t\tat reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:214)\r\n\t\tat reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:214)\r\n\t\tat reactor.pool.AbstractPool$Borrower.fail(AbstractPool.java:427)\r\n\t\tat reactor.pool.SimpleDequePool.lambda$drainLoop$5(SimpleDequePool.java:310)\r\n\t\tat reactor.core.publisher.FluxDoOnEach$DoOnEachSubscriber.onError(FluxDoOnEach.java:172)\r\n\t\tat reactor.core.publisher.FluxMap$MapConditionalSubscriber.onError(FluxMap.java:252)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:100)\r\n\t\tat reactor.core.publisher.Operators.error(Operators.java:196)\r\n\t\tat reactor.core.publisher.MonoError.subscribe(MonoError.java:52)\r\n\t\tat reactor.core.publisher.Mono.subscribe(Mono.java:4252)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:97)\r\n\t\tat reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:165)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:100)\r\n\t\tat reactor.core.publisher.Operators.error(Operators.java:196)\r\n\t\tat reactor.core.publisher.MonoError.subscribe(MonoError.java:52)\r\n\t\tat reactor.core.publisher.Mono.subscribe(Mono.java:4252)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:97)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:100)\r\n\t\tat reactor.core.publisher.Operators.error(Operators.java:196)\r\n\t\tat reactor.core.publisher.MonoError.subscribe(MonoError.java:52)\r\n\t\tat reactor.core.publisher.Mono.subscribe(Mono.java:4252)\r\n\t\tat reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:97)\r\n\t\tat reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:126)\r\n\t\tat reactor.core.publisher.MonoDelayUntil$DelayUntilTrigger.onError(MonoDelayUntil.java:330)\r\n\t\tat reactor.core.publisher.FluxHandle$HandleSubscriber.onError(FluxHandle.java:196)\r\n\t\tat reactor.core.publisher.FluxHandle$HandleConditionalSubscriber.onError(FluxHandle.java:406)\r\n\t\tat reactor.core.publisher.FluxCreate$BaseSink.error(FluxCreate.java:452)\r\n\t\tat reactor.core.publisher.FluxCreate$BufferAsyncSink.drain(FluxCreate.java:781)\r\n\t\tat reactor.core.publisher.FluxCreate$BufferAsyncSink.error(FluxCreate.java:726)\r\n\t\tat reactor.core.publisher.FluxCreate$SerializedSink.drainLoop(FluxCreate.java:229)\r\n\t\tat reactor.core.publisher.FluxCreate$SerializedSink.drain(FluxCreate.java:205)\r\n\t\tat reactor.core.publisher.FluxCreate$SerializedSink.error(FluxCreate.java:181)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient$Conversation.onError(ReactorNettyClient.java:746)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.close(ReactorNettyClient.java:1018)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient.drainError(ReactorNettyClient.java:518)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient.handleClose(ReactorNettyClient.java:506)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient.access$200(ReactorNettyClient.java:94)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onComplete(ReactorNettyClient.java:909)\r\n\t\tat reactor.core.publisher.FluxHandle$HandleSubscriber.onComplete(FluxHandle.java:206)\r\n\t\tat reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onComplete(FluxPeekFuseable.java:931)\r\n\t\tat reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:262)\r\n\t\tat reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:262)\r\n\t\tat reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:450)\r\n\t\tat reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:256)\r\n\t\tat reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:387)\r\n\t\tat reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:373)\r\n\t\tat reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:429)\r\n\t\tat reactor.netty.channel.ChannelOperations.onInboundClose(ChannelOperations.java:390)\r\n\t\tat reactor.netty.channel.ChannelOperationsHandler.channelInactive(ChannelOperationsHandler.java:76)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\t\tat io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)\r\n\t\tat io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\t\tat io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)\r\n\t\tat io.r2dbc.postgresql.client.ReactorNettyClient$EnsureSubscribersCompleteChannelHandler.channelInactive(ReactorNettyClient.java:535)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\t\tat io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)\r\n\t\tat io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)\r\n\t\tat io.netty.handler.ssl.SslHandler.channelInactive(SslHandler.java:1121)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\t\tat io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\t\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\t\tat io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)\r\n\t\tat io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:819)\r\n\t\tat io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)\r\n\t\tat io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)\r\n\t\tat io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497)\r\n\t\tat io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)\r\n\t\tat io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)\r\n\t\tat io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)\r\n\t\tat java.base/java.lang.Thread.run(Thread.java:834)\r\nCaused by: io.r2dbc.postgresql.client.ReactorNettyClient$PostgresConnectionClosedException: Connection unexpectedly closed\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient.lambda$static$0(ReactorNettyClient.java:100)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.close(ReactorNettyClient.java:1018)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient.drainError(ReactorNettyClient.java:518)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient.handleClose(ReactorNettyClient.java:506)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient.access$200(ReactorNettyClient.java:94)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onComplete(ReactorNettyClient.java:909)\r\n\tat reactor.core.publisher.FluxHandle$HandleSubscriber.onComplete(FluxHandle.java:206)\r\n\tat reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onComplete(FluxPeekFuseable.java:931)\r\n\tat reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:262)\r\n\tat reactor.core.publisher.FluxMap$MapConditionalSubscriber.onComplete(FluxMap.java:262)\r\n\tat reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:450)\r\n\tat reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:256)\r\n\tat reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:387)\r\n\tat reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:373)\r\n\tat reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:429)\r\n\tat reactor.netty.channel.ChannelOperations.onInboundClose(ChannelOperations.java:390)\r\n\tat reactor.netty.channel.ChannelOperationsHandler.channelInactive(ChannelOperationsHandler.java:76)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\tat io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)\r\n\tat io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\tat io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81)\r\n\tat io.r2dbc.postgresql.client.ReactorNettyClient$EnsureSubscribersCompleteChannelHandler.channelInactive(ReactorNettyClient.java:535)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\tat io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389)\r\n\tat io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354)\r\n\tat io.netty.handler.ssl.SslHandler.channelInactive(SslHandler.java:1121)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241)\r\n\tat io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248)\r\n\tat io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901)\r\n\tat io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:819)\r\n\tat io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)\r\n\tat io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)\r\n\tat io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497)\r\n\tat io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)\r\n\tat io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)\r\n\tat io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)\r\n\tat java.base/java.lang.Thread.run(Thread.java:834)\r\n

Any help would be appreciated.


Solution

  • I suspect the problem is with your url parameter. I've found that the options=--cluster={clustername}-554 syntax doesn't quite work as expected. Instead, please remove the options parameter and change the way you specify the database name.

    So for example, you currently have this...

    url: r2dbc:postgres://{username}:{password}@free-tier.gcp-us-central1.cockroachlabs.cloud:26257/{dbname}?ssl=true&sslmode=verify-full&sslrootcert=cc-ca.crt&options=--cluster={clustername}-554
    

    please try something like this instead...

    url: r2dbc:postgres://{username}:{password}@free-tier.gcp-us-central1.cockroachlabs.cloud:26257/{clustername}-554.defaultdb?ssl=true&sslmode=verify-full&sslrootcert=cc-ca.crt
    

    notice that the database should be your unique cluster id + .defaultdb and the options parameter has been removed completely.