Skip to content

Enum values used through @Query not converted to String #465

Closed
@Tienisto

Description

@Tienisto

Hello,

I wanted to fetch data from the database by a specific enum. It works fine if I don't use the custom @Query annotation.
But if I do so, then I get a this error:

Cannot encode parameter of type com.example.demo.MyType

It does not work in CoroutineCrudRepository nor does it in ReactiveCrudRepository.

Here is an example:

// enum
public enum MyType {
    HOUSE,
    STREET,
    ROAD,
    CITY
}

// model
@Table("my_table")
public class MyEntity {

    @Id
    private Integer id;
    private MyType type;

    // getters and setters
}

// repository
interface MyRepository extends ReactiveCrudRepository<MyEntity, Integer> {

    Flux<MyEntity> findByType(MyType type); // works fine

    @Query("SELECT * FROM my_table WHERE type = :type")
    Flux<MyEntity> findCustom(MyType type); // error
}


// controller
@RestController
public class MyController {

    private final MyRepository repository;

    public MyController(MyRepository repository) {
        this.repository = repository;
    }

    @GetMapping("/a")
    public Flux<MyEntity> getA() {
        return repository.findByType(MyType.HOUSE);
    }

    @GetMapping("/b")
    public Flux<MyEntity> getB() {
        return repository.findCustom(MyType.HOUSE); // error
    }
}
-- table
CREATE TABLE my_table (
    id SERIAL PRIMARY KEY,
    type TEXT NOT NULL
);

Version: 1.2.0-RC1
Database: PostgreSQL

Activity

mp911de

mp911de commented on Sep 21, 2020

@mp911de
Member

Can you provide also a stack trace?

Tienisto

Tienisto commented on Sep 21, 2020

@Tienisto
Author

Sure

java.lang.IllegalArgumentException: Cannot encode parameter of type com.example.demo.MyType
	at io.r2dbc.postgresql.codec.DefaultCodecs.encode(DefaultCodecs.java:165) ~[r2dbc-postgresql-0.8.5.RELEASE.jar:0.8.5.RELEASE]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	|_ checkpoint ⇢ Handler com.example.demo.MyController#getB() [DispatcherHandler]
	|_ checkpoint ⇢ HTTP GET "/b" [ExceptionHandlingWebHandler]
Stack trace:
		at io.r2dbc.postgresql.codec.DefaultCodecs.encode(DefaultCodecs.java:165) ~[r2dbc-postgresql-0.8.5.RELEASE.jar:0.8.5.RELEASE]
		at io.r2dbc.postgresql.ExtendedQueryPostgresqlStatement.bind(ExtendedQueryPostgresqlStatement.java:84) ~[r2dbc-postgresql-0.8.5.RELEASE.jar:0.8.5.RELEASE]
		at io.r2dbc.postgresql.ExtendedQueryPostgresqlStatement.bind(ExtendedQueryPostgresqlStatement.java:45) ~[r2dbc-postgresql-0.8.5.RELEASE.jar:0.8.5.RELEASE]
		at org.springframework.r2dbc.core.DefaultDatabaseClient$StatementWrapper.bind(DefaultDatabaseClient.java:551) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at org.springframework.r2dbc.core.binding.IndexedBindMarkers$IndexedBindMarker.bind(IndexedBindMarkers.java:86) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at org.springframework.r2dbc.core.NamedParameterUtils$ExpandedQuery.bind(NamedParameterUtils.java:555) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at org.springframework.r2dbc.core.NamedParameterUtils$ExpandedQuery.bindTo(NamedParameterUtils.java:618) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at org.springframework.r2dbc.core.DefaultDatabaseClient$DefaultGenericExecuteSpec.lambda$execute$2(DefaultDatabaseClient.java:363) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at org.springframework.r2dbc.core.DefaultDatabaseClient$DefaultGenericExecuteSpec.lambda$execute$3(DefaultDatabaseClient.java:380) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at org.springframework.r2dbc.core.ConnectionFunction.apply(ConnectionFunction.java:46) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at org.springframework.r2dbc.core.ConnectionFunction.apply(ConnectionFunction.java:31) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at org.springframework.r2dbc.core.DefaultFetchSpec.lambda$all$2(DefaultFetchSpec.java:91) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at org.springframework.r2dbc.core.ConnectionFunction.apply(ConnectionFunction.java:46) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at org.springframework.r2dbc.core.ConnectionFunction.apply(ConnectionFunction.java:31) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at org.springframework.r2dbc.core.DefaultDatabaseClient.lambda$inConnectionMany$6(DefaultDatabaseClient.java:145) ~[spring-r2dbc-5.3.0-RC1.jar:5.3.0-RC1]
		at reactor.core.publisher.FluxUsingWhen.deriveFluxFromResource(FluxUsingWhen.java:119) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxUsingWhen.access$000(FluxUsingWhen.java:53) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxUsingWhen$ResourceSubscriber.onNext(FluxUsingWhen.java:194) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:120) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxRetry$RetrySubscriber.onNext(FluxRetry.java:86) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:210) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1783) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1783) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:148) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.pool.AbstractPool$Borrower.deliver(AbstractPool.java:415) ~[reactor-pool-0.2.0-RC1.jar:0.2.0-RC1]
		at reactor.pool.SimpleDequePool.lambda$drainLoop$5(SimpleDequePool.java:246) ~[reactor-pool-0.2.0-RC1.jar:0.2.0-RC1]
		at reactor.core.publisher.FluxDoOnEach$DoOnEachSubscriber.onNext(FluxDoOnEach.java:154) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:120) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1783) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1783) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.MonoDelayUntil$DelayUntilCoordinator.signal(MonoDelayUntil.java:261) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.MonoDelayUntil$DelayUntilTrigger.onComplete(MonoDelayUntil.java:341) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:88) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxConcatIterable$ConcatIterableSubscriber.onComplete(FluxConcatIterable.java:121) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:88) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxFlatMap$FlatMapMain.checkTerminated(FluxFlatMap.java:845) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:607) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:587) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxFlatMap$FlatMapMain.onComplete(FluxFlatMap.java:464) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onComplete(FluxContextWrite.java:126) ~[reactor-core-3.4.0-RC1.jar:na]
		at io.r2dbc.postgresql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onComplete(FluxDiscardOnCancel.java:99) ~[r2dbc-postgresql-0.8.5.RELEASE.jar:0.8.5.RELEASE]
		at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onComplete(FluxMapFuseable.java:150) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onComplete(FluxMapFuseable.java:150) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxWindowPredicate$WindowPredicateMain.checkTerminated(FluxWindowPredicate.java:527) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxWindowPredicate$WindowPredicateMain.drainLoop(FluxWindowPredicate.java:475) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxWindowPredicate$WindowPredicateMain.drain(FluxWindowPredicate.java:419) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxWindowPredicate$WindowPredicateMain.onComplete(FluxWindowPredicate.java:299) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxCreate$BaseSink.complete(FluxCreate.java:439) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxCreate$BufferAsyncSink.drain(FluxCreate.java:784) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxCreate$BufferAsyncSink.complete(FluxCreate.java:732) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxCreate$SerializedFluxSink.drainLoop(FluxCreate.java:240) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxCreate$SerializedFluxSink.drain(FluxCreate.java:206) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxCreate$SerializedFluxSink.complete(FluxCreate.java:197) ~[reactor-core-3.4.0-RC1.jar:na]
		at io.r2dbc.postgresql.client.ReactorNettyClient$Conversation.complete(ReactorNettyClient.java:709) ~[r2dbc-postgresql-0.8.5.RELEASE.jar:0.8.5.RELEASE]
		at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.emit(ReactorNettyClient.java:974) ~[r2dbc-postgresql-0.8.5.RELEASE.jar:0.8.5.RELEASE]
		at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onNext(ReactorNettyClient.java:850) ~[r2dbc-postgresql-0.8.5.RELEASE.jar:0.8.5.RELEASE]
		at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onNext(ReactorNettyClient.java:757) ~[r2dbc-postgresql-0.8.5.RELEASE.jar:0.8.5.RELEASE]
		at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:118) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:854) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:220) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:220) ~[reactor-core-3.4.0-RC1.jar:na]
		at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:256) ~[reactor-netty-core-1.0.0-RC1.jar:1.0.0-RC1]
		at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:362) ~[reactor-netty-core-1.0.0-RC1.jar:1.0.0-RC1]
		at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:374) ~[reactor-netty-core-1.0.0-RC1.jar:1.0.0-RC1]
		at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94) ~[reactor-netty-core-1.0.0-RC1.jar:1.0.0-RC1]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) ~[netty-codec-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296) ~[netty-codec-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.52.Final.jar:4.1.52.Final]
		at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.52.Final.jar:4.1.52.Final]
		at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
mp911de

mp911de commented on Sep 21, 2020

@mp911de
Member

Thanks a lot! We apply input-value to R2DBC driver-compliant value conversion for derived queries. For String-based queries, we don't apply that type of value conversion. We should fix that.

added and removed on Sep 21, 2020
changed the title [-]Decode enums in @Query[/-] [+]Enum values used through @Query not converted to String[/+] on Sep 21, 2020
parikshitdutta

parikshitdutta commented on Sep 22, 2020

@parikshitdutta

@mp911de can I take this one?

mp911de

mp911de commented on Sep 22, 2020

@mp911de
Member

Sure, feel free to submit a pull request.

Tienisto

Tienisto commented on Oct 7, 2020

@Tienisto
Author

Any updates here? It would be nice if I could use this in the next spring release :)

mp911de

mp911de commented on Oct 7, 2020

@mp911de
Member

What a coincidence. I just opened this ticket and started building a test case since there was no movement for two weeks.

added 2 commits that reference this issue on Oct 7, 2020

#465 - Convert bind values for String-based queries to their native t…

03a667c

#465 - Polishing.

c00184b
added this to the 1.2 RC2 (2020.0.0) milestone on Oct 7, 2020
mp911de

mp911de commented on Oct 7, 2020

@mp911de
Member

That's fixed now.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @parikshitdutta@mp911de@Tienisto

        Issue actions

          Enum values used through @Query not converted to String · Issue #465 · spring-projects/spring-data-r2dbc