Search code examples
postgresqlspring-bootspring-datajooqr2dbc

JOOQ r2dbc fetching data: Cannot decode value of type java.lang.String with OID 51968


I use jooq 3.15 with r2dbc in my Spring application and have a problem by fetching data from DB.

I use nu.studer.jooq with version 6.0.1 for set up jooq in my gradle file:

jooq {
    version.set("3.15.1")
    edition.set(nu.studer.gradle.jooq.JooqEdition.OSS)
    configurations {
        create("main") {
            generateSchemaSourceOnCompilation.set(false)
            jooqConfiguration.apply {
                logging = org.jooq.meta.jaxb.Logging.WARN
                jdbc.apply {
                    driver = "org.postgresql.Driver"
                    url = "jdbc:postgresql://localhost:15432/core_ticker"
                    user = ""
                    password = ""
                }
                generator.apply {
                    database.apply {
                        name = "org.jooq.meta.postgres.PostgresDatabase"
                        inputSchema = "public"
                        includes = ".*"
                        excludes =
                            "flyway_schema_history"
                    }
                    generate.apply {
                        isRelations = true
                        isDeprecated = false
                        isRecords = true
                        isImmutablePojos = true
                        isFluentSetters = true
                    }
                    target.apply {
                        packageName = "rc.core.ticker.domain.db"
                        directory = "src/main/java"
                    }
                }
            }
        }
    }
}

I have next code for fetching currency rate:

fun getRate(
        fromCurrency: Currency,
        toCurrency: Currency,
        source: CurrencySource,
        date: LocalDate?
    ) = Mono.from(
        context.selectFrom(Tables.CURRENCY_RATE)
            .where(Tables.CURRENCY_RATE.CURRENCY_FROM.eq(fromCurrency.value))
            .and(Tables.CURRENCY_RATE.CURRENCY_TO.eq(toCurrency.value))
            .limit(1)
    ).mapNotNull(CurrencyRate.Mapper::map).awaitSingle()

But I wouldn't fetch data because of exception in code inside Mono.from with next stacktrace:

java.lang.IllegalArgumentException: Cannot decode value of type java.lang.String with OID 51968
    at io.r2dbc.postgresql.codec.DefaultCodecs.decode(DefaultCodecs.java:158) ~[r2dbc-postgresql-0.8.8.RELEASE.jar:0.8.8.RELEASE]
    at io.r2dbc.postgresql.PostgresqlRow.decode(PostgresqlRow.java:90) ~[r2dbc-postgresql-0.8.8.RELEASE.jar:0.8.8.RELEASE]
    at io.r2dbc.postgresql.PostgresqlRow.get(PostgresqlRow.java:67) ~[r2dbc-postgresql-0.8.8.RELEASE.jar:0.8.8.RELEASE]
    at org.jooq.impl.R2DBC$R2DBCResultSet$DefaultRow.get(R2DBC.java:1110) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.R2DBC$R2DBCResultSet.nullable(R2DBC.java:989) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.R2DBC$R2DBCResultSet.nullable(R2DBC.java:985) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.R2DBC$R2DBCResultSet.getString(R2DBC.java:1050) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.DefaultBinding$DefaultEnumTypeBinding.get0(DefaultBinding.java:2560) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.DefaultBinding$DefaultEnumTypeBinding.get0(DefaultBinding.java:2527) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.DefaultBinding$AbstractBinding.get(DefaultBinding.java:942) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.R2DBC$ResultSubscriber.lambda$onNext$0(R2DBC.java:327) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.RecordDelegate.operate(RecordDelegate.java:143) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.R2DBC$ResultSubscriber.lambda$onNext$1(R2DBC.java:313) ~[jooq-3.15.1.jar:na]
    at io.r2dbc.postgresql.PostgresqlResult.lambda$map$1(PostgresqlResult.java:111) ~[r2dbc-postgresql-0.8.8.RELEASE.jar:0.8.8.RELEASE]
    at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:103) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onNext(FluxHandleFuseable.java:184) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:854) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:854) ~[reactor-core-3.4.9.jar:3.4.9]
    at io.r2dbc.postgresql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onNext(FluxDiscardOnCancel.java:86) ~[r2dbc-postgresql-0.8.8.RELEASE.jar:0.8.8.RELEASE]
    at reactor.core.publisher.FluxCreate$BufferAsyncSink.drain(FluxCreate.java:793) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.core.publisher.FluxCreate$BufferAsyncSink.next(FluxCreate.java:718) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.core.publisher.FluxCreate$SerializedFluxSink.next(FluxCreate.java:154) ~[reactor-core-3.4.9.jar:3.4.9]
    at io.r2dbc.postgresql.client.ReactorNettyClient$Conversation.emit(ReactorNettyClient.java:735) ~[r2dbc-postgresql-0.8.8.RELEASE.jar:0.8.8.RELEASE]
    at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.emit(ReactorNettyClient.java:986) ~[r2dbc-postgresql-0.8.8.RELEASE.jar:0.8.8.RELEASE]
    at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onNext(ReactorNettyClient.java:860) ~[r2dbc-postgresql-0.8.8.RELEASE.jar:0.8.8.RELEASE]
    at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onNext(ReactorNettyClient.java:767) ~[r2dbc-postgresql-0.8.8.RELEASE.jar:0.8.8.RELEASE]
    at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:119) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:854) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:220) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:220) ~[reactor-core-3.4.9.jar:3.4.9]
    at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:279) ~[reactor-netty-core-1.0.10.jar:1.0.10]
    at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:388) ~[reactor-netty-core-1.0.10.jar:1.0.10]
    at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:404) ~[reactor-netty-core-1.0.10.jar:1.0.10]
    at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:93) ~[reactor-netty-core-1.0.10.jar:1.0.10]

I think that main reason of my problem is hiding in next block of trace:

at org.jooq.impl.R2DBC$R2DBCResultSet$DefaultRow.get(R2DBC.java:1110) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.R2DBC$R2DBCResultSet.nullable(R2DBC.java:989) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.R2DBC$R2DBCResultSet.nullable(R2DBC.java:985) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.R2DBC$R2DBCResultSet.getString(R2DBC.java:1050) ~[jooq-3.15.1.jar:na]
    at org.jooq.impl.DefaultBinding$DefaultEnumTypeBinding.get0(DefaultBinding.java:2560) ~[jooq-3.15.1.jar:na]

I have one enum column in my table but It's not nullable.


Solution

  • There's a known limitation of the r2dbc-postgresql driver, which currently can't deserialise enum types without you registering them manually beforehand: https://github.com/pgjdbc/r2dbc-postgresql/issues/429

    Here are some instructions on how to do that: https://github.com/pgjdbc/r2dbc-postgresql#postgres-enum-types