lecousin / lc-spring-data-r2dbc

An extension of spring-data-r2dbc to provide features such as relationships, joins, cascading save/delete, lazy loading, sequence, schema generation, composite id
Apache License 2.0
48 stars 12 forks source link

Required property not found #9

Closed gdude2002 closed 2 years ago

gdude2002 commented 2 years ago

Hello! We're working on an application that has somewhat nested data, but we're having trouble figuring out how to handle the joins via SelectQuery.

Given the following two (Kotlin) tables:

@Table("cards")
data class Card(
    @Id
    val id: String,

    val deck: String,
    val ordinal: Short,

    @Version
    val version: Int = 0,

    @ForeignTable(joinKey = "id", optional = true)
    val data: Set<CardData>
)
@Table("card_data")
data class CardData(
    @ForeignKey
    val card: String,

    val column: String,
    val src: List<String>,
    val version: Int
)

And the following repository:

interface CardRepository : LcR2dbcRepository<Card, String> {
    fun findAllByDeck(deck: String): Flux<Card> =
        SelectQuery.from(Card::class.java, "card")
            .where(Criteria.property("card", "deck").`is`(deck))
            .join("card", "data", "card_data")
            .execute(lcClient)
}

The generated query: SELECT cards.id, cards.deck, cards.ordinal, cards.version FROM cards WHERE cards.deck = $1

Returns this error:

java.lang.IllegalStateException: Required property data not found for class com.benkyo.decks.data.Card!
    at org.springframework.data.mapping.PersistentEntity.getRequiredPersistentProperty(PersistentEntity.java:161) ~[spring-data-commons-2.5.4.jar:2.5.4]

We're stumped at this point - we feel like we've followed everything in the README and the wiki, and nothing we've tried is working.

lecousin commented 2 years ago

I see 2 problems in your table classes:

Can you try with those 2 modifications ?

gdude2002 commented 2 years ago

I see 2 problems in your table classes:

  • In CardData, your foreign key should have the type Card instead of String (internally it will understand that the foreign key is stored as a String in database, because the @id property of Card is a String, but the usage in Java is to access directly to the Card object)
  • In Card, in the ForeignTable annotation, the joinKey should be "card" because the foreign key is on the "card" property

Can you try with those 2 modifications ?

Thanks for the quick response - we're still quite new to this way of doing things!

I've just updated our classes:

@Table("cards")
data class Card(
    @Id
    val id: String,

    val deck: String,
    val ordinal: Short,

    @Version
    val version: Int = 0,

    @ForeignTable(joinKey = "card", optional = true)
    val data: Set<CardData>
)
@Table("card_data")
data class CardData(
    @ForeignKey
    val card: Card,

    val column: String,
    val src: List<String>,
    val version: Int
)

Unfortunately, I'm still getting the same error.

Required property data not found for class com.benkyo.decks.data.Card!

lecousin commented 2 years ago

Can you provide the full stack trace ? So I can better understand where the error comes from

gdude2002 commented 2 years ago

Sure thing, thanks for looking into this!

java.lang.IllegalStateException: Required property data not found for class com.benkyo.decks.data.Card!
    at org.springframework.data.mapping.PersistentEntity.getRequiredPersistentProperty(PersistentEntity.java:161) ~[spring-data-commons-2.5.4.jar:2.5.4]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    |_ checkpoint ⇢ Handler com.benkyo.decks.controller.CardController#getCards(String) [DispatcherHandler]
    |_ checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.web.cors.reactive.CorsWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
    |_ checkpoint ⇢ HTTP GET "/api/decks/0/cards" [ExceptionHandlingWebHandler]
Stack trace:
        at org.springframework.data.mapping.PersistentEntity.getRequiredPersistentProperty(PersistentEntity.java:161) ~[spring-data-commons-2.5.4.jar:2.5.4]
        at net.lecousin.reactive.data.relational.mapping.LcEntityReader$PropertiesSourceParameterValueProvider.getParameterValue(LcEntityReader.java:240) ~[core-0.8.1.jar:na]
        at org.springframework.data.relational.core.conversion.BasicRelationalConverter$ConvertingParameterValueProvider.getParameterValue(BasicRelationalConverter.java:268) ~[spring-data-relational-2.2.4.jar:2.2.4]
        at org.springframework.data.mapping.model.KotlinClassGeneratingEntityInstantiator$DefaultingKotlinClassInstantiatorAdapter.extractInvocationArguments(KotlinClassGeneratingEntityInstantiator.java:228) ~[spring-data-commons-2.5.4.jar:2.5.4]
        at org.springframework.data.mapping.model.KotlinClassGeneratingEntityInstantiator$DefaultingKotlinClassInstantiatorAdapter.createInstance(KotlinClassGeneratingEntityInstantiator.java:202) ~[spring-data-commons-2.5.4.jar:2.5.4]
        at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:89) ~[spring-data-commons-2.5.4.jar:2.5.4]
        at org.springframework.data.relational.core.conversion.BasicRelationalConverter.createInstance(BasicRelationalConverter.java:145) ~[spring-data-relational-2.2.4.jar:2.2.4]
        at net.lecousin.reactive.data.relational.mapping.LcEntityReader.getOrCreateInstance(LcEntityReader.java:211) ~[core-0.8.1.jar:na]
        at net.lecousin.reactive.data.relational.mapping.LcEntityReader.getOrCreateInstance(LcEntityReader.java:200) ~[core-0.8.1.jar:na]
        at net.lecousin.reactive.data.relational.mapping.LcEntityReader.read(LcEntityReader.java:88) ~[core-0.8.1.jar:na]
        at net.lecousin.reactive.data.relational.mapping.LcEntityReader.read(LcEntityReader.java:81) ~[core-0.8.1.jar:na]
        at net.lecousin.reactive.data.relational.mapping.LcMappingR2dbcConverter.read(LcMappingR2dbcConverter.java:39) ~[core-0.8.1.jar:na]
        at org.springframework.data.r2dbc.convert.EntityRowMapper.apply(EntityRowMapper.java:46) ~[spring-data-r2dbc-1.3.4.jar:1.3.4]
        at org.springframework.data.r2dbc.convert.EntityRowMapper.apply(EntityRowMapper.java:29) ~[spring-data-r2dbc-1.3.4.jar:1.3.4]
        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]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) ~[netty-codec-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:311) ~[netty-codec-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:432) ~[netty-codec-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-common-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.67.Final.jar:4.1.67.Final]
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.67.Final.jar:4.1.67.Final]
        at java.base/java.lang.Thread.run(Thread.java:831) ~[na:na]
lecousin commented 2 years ago

Thanks, I guess I found where the issue comes from. I will look into it. As a workaround before the fix, I think you can remove the data attribute from the constructor of your class Card and declare it outside the constructor, because the issue comes from having a foreigntable as a constructor argument. If not may be to declare all properties outside of the constructor, I didn't test this way of creating entities, but I will do it to make it work.

gdude2002 commented 2 years ago

That seems to have worked as far as resolving the error goes - we're still not actually getting a join in the SQL, but I think I may be misunderstanding how the query builder works.

Query function:

fun findAllByDeck(deck: String): Flux<Card> =
    SelectQuery.from(Card::class.java, "card")
        .where(Criteria.property("card", "deck").`is`(deck))
        .join("card", "data", "card_data")
        .execute(lcClient)

Generated query: SELECT cards.id, cards.deck, cards.ordinal, cards.version FROM cards WHERE cards.deck = $1

lecousin commented 2 years ago

You're right, the generated SQL should include a LEFT JOIN to the card_data table. In the Card instances returned by the function the data set does not contain the expected CardData ?

gdude2002 commented 2 years ago

The database does contain card_data entries that should match here - you can see that if we write a similar query ourselves, then the data is there.

image

The returned data looks something like this.

[{
    "id": "7",
    "ordinal": 0,
    "data": []
}, {
    "id": "8",
    "ordinal": 0,
    "data": []
}]

The data class looks like this right now. I thought it may be the default value, but using lateinit var just throws errors.

@Table("cards")
data class Card(
    @Id
    val id: String,

    val deck: String,
    val ordinal: Short,

    @Version
    val version: Int = 0
) {
    @ForeignTable(joinKey = "card", optional = true)
    val data: Set<CardData> = setOf()
}
lecousin commented 2 years ago

looks like the SelectQuery is not used, and the default Spring Data R2DBC query is made instead, may be due to the way Kotlin handle default methods in interfaces that is not supported in Spring Data repositories DATACMNS-1223 - Kotlin interface default methods are considered query methods. You may try to use the SelectQuery outside of the repository

gdude2002 commented 2 years ago

Ah, thanks for the hint - that issue mentioned @JvmDefault which should actually generate default methods.

And, yeah, it does seem to, but that gives us a new error...

SQL: SELECT card.id AS f0000, card.deck AS f0001, card.ordinal AS f0002, card.version AS f0003, card_data.card AS f0004, card_data.column AS f0005, card_data.src AS f0006, card_data.version AS f0007 FROM cards card LEFT OUTER JOIN card_data card_data ON card_data.card = card.id WHERE card.deck = $1 ORDER BY f0000

org.springframework.data.mapping.MappingException: Error mapping result for entity com.benkyo.decks.data.CardData
    at net.lecousin.reactive.data.relational.query.SelectExecution$RowHandler.fillLinkedEntities(SelectExecution.java:615) ~[core-0.8.1.jar:na]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ SELECT FROM Card AS card JOIN card_data WHERE card.deck EQUALS 0
    |_ checkpoint ⇢ Handler com.benkyo.decks.controller.CardController#getCards(String) [DispatcherHandler]
    *__checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.web.cors.reactive.CorsWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
    *__checkpoint ⇢ HTTP GET "/api/decks/0/cards" [ExceptionHandlingWebHandler]
Original Stack Trace:
        at net.lecousin.reactive.data.relational.query.SelectExecution$RowHandler.fillLinkedEntities(SelectExecution.java:615) ~[core-0.8.1.jar:na]
        at net.lecousin.reactive.data.relational.query.SelectExecution$RowHandler.handleRow(SelectExecution.java:586) ~[core-0.8.1.jar:na]
        at reactor.core.publisher.LambdaSubscriber.onNext(LambdaSubscriber.java:160) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxUsingWhen$UsingWhenSubscriber.onNext(FluxUsingWhen.java:345) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxFlatMap$FlatMapMain.tryEmit(FluxFlatMap.java:543) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxFlatMap$FlatMapInner.onNext(FluxFlatMap.java:984) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:119) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onNext(FluxHandleFuseable.java:184) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:854) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:854) ~[reactor-core-3.4.16.jar:3.4.16]
        at io.r2dbc.postgresql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onNext(FluxDiscardOnCancel.java:86) ~[r2dbc-postgresql-0.8.12.RELEASE.jar:0.8.12.RELEASE]
        at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onNext(FluxDoFinally.java:130) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:119) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxCreate$BufferAsyncSink.drain(FluxCreate.java:793) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxCreate$BufferAsyncSink.next(FluxCreate.java:718) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxCreate$SerializedFluxSink.next(FluxCreate.java:154) ~[reactor-core-3.4.16.jar:3.4.16]
        at io.r2dbc.postgresql.client.ReactorNettyClient$Conversation.emit(ReactorNettyClient.java:654) ~[r2dbc-postgresql-0.8.12.RELEASE.jar:0.8.12.RELEASE]
        at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.emit(ReactorNettyClient.java:906) ~[r2dbc-postgresql-0.8.12.RELEASE.jar:0.8.12.RELEASE]
        at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onNext(ReactorNettyClient.java:780) ~[r2dbc-postgresql-0.8.12.RELEASE.jar:0.8.12.RELEASE]
        at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onNext(ReactorNettyClient.java:686) ~[r2dbc-postgresql-0.8.12.RELEASE.jar:0.8.12.RELEASE]
        at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:119) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:854) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:220) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:220) ~[reactor-core-3.4.16.jar:3.4.16]
        at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:279) ~[reactor-netty-core-1.0.17.jar:1.0.17]
        at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:388) ~[reactor-netty-core-1.0.17.jar:1.0.17]
        at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:404) ~[reactor-netty-core-1.0.17.jar:1.0.17]
        at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:93) ~[reactor-netty-core-1.0.17.jar:1.0.17]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:327) ~[netty-codec-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:314) ~[netty-codec-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:435) ~[netty-codec-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279) ~[netty-codec-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-common-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.75.Final.jar:4.1.75.Final]
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.75.Final.jar:4.1.75.Final]
        at java.base/java.lang.Thread.run(Thread.java:831) ~[na:na]
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [com.benkyo.decks.data.Card]
    at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:322) ~[spring-core-5.3.18.jar:5.3.18]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195) ~[spring-core-5.3.18.jar:5.3.18]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175) ~[spring-core-5.3.18.jar:5.3.18]
    at net.lecousin.reactive.data.relational.mapping.LcEntityReader$PropertiesSourceParameterValueProvider.getParameterValue(LcEntityReader.java:253) ~[core-0.8.1.jar:na]
    at org.springframework.data.relational.core.conversion.BasicRelationalConverter$ConvertingParameterValueProvider.getParameterValue(BasicRelationalConverter.java:291) ~[spring-data-relational-2.3.3.jar:2.3.3]
    at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.extractInvocationArguments(ClassGeneratingEntityInstantiator.java:276) ~[spring-data-commons-2.6.3.jar:2.6.3]
    at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(ClassGeneratingEntityInstantiator.java:248) ~[spring-data-commons-2.6.3.jar:2.6.3]
    at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:89) ~[spring-data-commons-2.6.3.jar:2.6.3]
    at org.springframework.data.relational.core.conversion.BasicRelationalConverter.createInstance(BasicRelationalConverter.java:148) ~[spring-data-relational-2.3.3.jar:2.3.3]
    at net.lecousin.reactive.data.relational.mapping.LcEntityReader.getOrCreateInstance(LcEntityReader.java:211) ~[core-0.8.1.jar:na]
    at net.lecousin.reactive.data.relational.mapping.LcEntityReader.getOrCreateInstance(LcEntityReader.java:200) ~[core-0.8.1.jar:na]
    at net.lecousin.reactive.data.relational.mapping.LcEntityReader.read(LcEntityReader.java:88) ~[core-0.8.1.jar:na]
    at net.lecousin.reactive.data.relational.query.SelectExecution$JoinStatus.readNewInstance(SelectExecution.java:549) ~[core-0.8.1.jar:na]
    at net.lecousin.reactive.data.relational.query.SelectExecution$RowHandler.fillLinkedEntity(SelectExecution.java:633) ~[core-0.8.1.jar:na]
    at net.lecousin.reactive.data.relational.query.SelectExecution$RowHandler.fillLinkedEntities(SelectExecution.java:613) ~[core-0.8.1.jar:na]
    at net.lecousin.reactive.data.relational.query.SelectExecution$RowHandler.handleRow(SelectExecution.java:586) ~[core-0.8.1.jar:na]
    at reactor.core.publisher.LambdaSubscriber.onNext(LambdaSubscriber.java:160) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxUsingWhen$UsingWhenSubscriber.onNext(FluxUsingWhen.java:345) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxFlatMap$FlatMapMain.tryEmit(FluxFlatMap.java:543) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxFlatMap$FlatMapInner.onNext(FluxFlatMap.java:984) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:119) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onNext(FluxHandleFuseable.java:184) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:854) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:854) ~[reactor-core-3.4.16.jar:3.4.16]
    at io.r2dbc.postgresql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onNext(FluxDiscardOnCancel.java:86) ~[r2dbc-postgresql-0.8.12.RELEASE.jar:0.8.12.RELEASE]
    at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onNext(FluxDoFinally.java:130) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:119) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxCreate$BufferAsyncSink.drain(FluxCreate.java:793) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxCreate$BufferAsyncSink.next(FluxCreate.java:718) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxCreate$SerializedFluxSink.next(FluxCreate.java:154) ~[reactor-core-3.4.16.jar:3.4.16]
    at io.r2dbc.postgresql.client.ReactorNettyClient$Conversation.emit(ReactorNettyClient.java:654) ~[r2dbc-postgresql-0.8.12.RELEASE.jar:0.8.12.RELEASE]
    at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.emit(ReactorNettyClient.java:906) ~[r2dbc-postgresql-0.8.12.RELEASE.jar:0.8.12.RELEASE]
    at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onNext(ReactorNettyClient.java:780) ~[r2dbc-postgresql-0.8.12.RELEASE.jar:0.8.12.RELEASE]
    at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onNext(ReactorNettyClient.java:686) ~[r2dbc-postgresql-0.8.12.RELEASE.jar:0.8.12.RELEASE]
    at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:119) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:854) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:220) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:220) ~[reactor-core-3.4.16.jar:3.4.16]
    at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:279) ~[reactor-netty-core-1.0.17.jar:1.0.17]
    at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:388) ~[reactor-netty-core-1.0.17.jar:1.0.17]
    at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:404) ~[reactor-netty-core-1.0.17.jar:1.0.17]
    at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:93) ~[reactor-netty-core-1.0.17.jar:1.0.17]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:327) ~[netty-codec-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:314) ~[netty-codec-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:435) ~[netty-codec-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279) ~[netty-codec-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-common-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.75.Final.jar:4.1.75.Final]
    at java.base/java.lang.Thread.run(Thread.java:831) ~[na:na]
gdude2002 commented 2 years ago

If there's anything we can do to help with any of these issues, I'd be happy to try!

lecousin commented 2 years ago

Can you try to upgrade version to 0.9.0 ? I publish this new version to fix your issue, and add support for array columns with postgresql.

lecousin commented 2 years ago

This is solved since version 0.9, as I don't have feedback I close this issue. Please re-open if the same bug still occurs for you.