java.lang.ClassCastException class xxxxx 无法转换为 class io.micronaut.data.model.Page Micronaut 数据

java.lang.ClassCastException class xxxxx cannot be cast to class io.micronaut.data.model.Page Micronaut data

尝试使用 MongoDB Micronaut 数据实现分页,如下所示

@MongoRepository
public interface IDiscountRepository extends ReactorCrudRepository<Discount, ObjectId> , ReactorJpaSpecificationExecutor<Discount> {
    @NonNull
    Flux<Page<Discount>> findAll(@Nullable PredicateSpecification<Discount> spec, Pageable pageable);
}

服务

public Flux<DiscountModel> find(DiscountFilterModel searchCriteria) {
        LOG.info("Find the discount");
        var test = Mono.from(iDiscountRepository.findAll(QueryBuilder(searchCriteria), Pageable.from(0, 2))).block();
        return iDiscountRepository.findAll(QueryBuilder(searchCriteria), Pageable.from(0,2)).map(item -> this.mapDiscountToModel(item.));
    }

查询生成器

@Introspected
public record QueryBuilderSpecification() {
    public static PredicateSpecification<Discount> QueryBuilder(DiscountFilterModel discountFilterModel){
        PredicateSpecification<Discount> predicateSpecification = null;

        if (discountFilterModel.getId() != null){
            predicateSpecification = DiscountIdEquals(new ObjectId(discountFilterModel.getId()));
        }
        if (discountFilterModel.getDiscountCode() != null){
            predicateSpecification = DiscountCodeEquals(discountFilterModel.getDiscountCode());
        }
        return predicateSpecification;
    }
}

谓词

public class DiscountSpecification {
    final static BeanIntrospection<Discount> introspection = BeanIntrospection.getIntrospection(Discount.class);
    static String[] discountProperty = introspection.getPropertyNames();

    public static PredicateSpecification<Discount> DiscountIdEquals(ObjectId DiscountId) {
        return (root, criteriaBuilder) -> criteriaBuilder.equal(root.get(discountProperty[0]), DiscountId);
    }

    public static PredicateSpecification<Discount> DiscountCodeEquals(String DiscountCode) {
        return (root, criteriaBuilder) -> criteriaBuilder.equal(root.get(discountProperty[1]), DiscountCode);
    }
}

异常

java.lang.ClassCastException: class fete.bird.entities.Discount cannot be cast to class io.micronaut.data.model.Page (fete.bird.entities.Discount and io.micronaut.data.model.Page are in unnamed module of loader 'app')
    at fete.bird.service.DiscountService.find(DiscountService.java:30)
    at fete.bird.aggregate.query.GetDiscountsQuery$GetDiscountsQueryHandler.handler(GetDiscountsQuery.java:23)
    at fete.bird.aggregate.query.GetDiscountsQuery$GetDiscountsQueryHandler.handler(GetDiscountsQuery.java:15)
    at fete.bird.utils.ServiceBus.send(ServiceBus.java:27)
    at fete.bird.api.v1.controller.DiscountController.find(DiscountController.java:48)
    at fete.bird.api.v1.controller.$DiscountController$Definition$Intercepted.$$access$$find(Unknown Source)
    at fete.bird.api.v1.controller.$DiscountController$Definition$Exec.dispatch(Unknown Source)
    at io.micronaut.context.AbstractExecutableMethodsDefinition$DispatchedExecutableMethod.invoke(AbstractExecutableMethodsDefinition.java:378)
    at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:128)
    at io.micronaut.validation.ValidatingInterceptor.intercept(ValidatingInterceptor.java:138)
    at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:137)
    at fete.bird.api.v1.controller.$DiscountController$Definition$Intercepted.find(Unknown Source)
    at fete.bird.api.v1.controller.$DiscountController$Definition$Exec.dispatch(Unknown Source)
    at io.micronaut.context.AbstractExecutableMethodsDefinition$DispatchedExecutableMethod.invoke(AbstractExecutableMethodsDefinition.java:378)
    at io.micronaut.context.DefaultBeanContext.invoke(DefaultBeanContext.java:583)
    at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:303)
    at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:111)
    at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:103)
    at io.micronaut.http.server.RouteExecutor.lambda$executeRoute(RouteExecutor.java:659)
    at reactor.core.publisher.FluxDeferContextual.subscribe(FluxDeferContextual.java:49)
    at reactor.core.publisher.Flux.subscribe(Flux.java:8469)
    at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:426)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onNext(ReactorSubscriber.java:57)
    at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398)
    at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:371)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onSubscribe(ReactorSubscriber.java:50)
    at reactor.core.publisher.FluxJust.subscribe(FluxJust.java:68)
    at reactor.core.publisher.Flux.subscribe(Flux.java:8469)
    at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:195)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onNext(ReactorSubscriber.java:57)
    at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onNext(ReactorSubscriber.java:57)
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:282)
    at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:863)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onNext(ReactorSubscriber.java:57)
    at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onNext(ReactorSubscriber.java:57)
    at reactor.core.publisher.FluxFilter$FilterSubscriber.onNext(FluxFilter.java:113)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onNext(ReactorSubscriber.java:57)
    at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:101)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onNext(ReactorSubscriber.java:57)
    at reactor.core.publisher.FluxHide$SuppressFuseableSubscriber.onNext(FluxHide.java:137)
    at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398)
    at reactor.core.publisher.FluxHide$SuppressFuseableSubscriber.request(FluxHide.java:152)
    at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.request(FluxDefaultIfEmpty.java:77)
    at reactor.core.publisher.FluxFilter$FilterSubscriber.request(FluxFilter.java:186)
    at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.request(MonoPeekTerminal.java:139)
    at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2194)
    at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2068)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onSubscribe(ReactorSubscriber.java:50)
    at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onSubscribe(MonoPeekTerminal.java:152)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onSubscribe(ReactorSubscriber.java:50)
    at reactor.core.publisher.FluxFilter$FilterSubscriber.onSubscribe(FluxFilter.java:85)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onSubscribe(ReactorSubscriber.java:50)
    at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onSubscribe(FluxDefaultIfEmpty.java:91)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onSubscribe(ReactorSubscriber.java:50)
    at reactor.core.publisher.FluxHide$SuppressFuseableSubscriber.onSubscribe(FluxHide.java:122)
    at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55)
    at reactor.core.publisher.Mono.subscribe(Mono.java:4400)
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:451)
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:219)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onSubscribe(ReactorSubscriber.java:50)
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165)
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87)
    at reactor.core.publisher.InternalFluxOperator.subscribe(InternalFluxOperator.java:62)
    at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:54)
    at reactor.core.publisher.Mono.subscribe(Mono.java:4400)
    at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:82)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onComplete(ReactorSubscriber.java:71)
    at reactor.core.publisher.MonoFlatMap$FlatMapMain.onComplete(MonoFlatMap.java:181)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onComplete(ReactorSubscriber.java:71)
    at reactor.core.publisher.MonoNext$NextSubscriber.onComplete(MonoNext.java:102)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onComplete(ReactorSubscriber.java:71)
    at reactor.core.publisher.FluxFlatMap$FlatMapMain.checkTerminated(FluxFlatMap.java:846)
    at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:608)
    at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:588)
    at reactor.core.publisher.FluxFlatMap$FlatMapMain.onComplete(FluxFlatMap.java:465)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onComplete(ReactorSubscriber.java:71)
    at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:294)
    at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:230)
    at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:371)
    at io.micronaut.reactive.reactor.instrument.ReactorSubscriber.onSubscribe(ReactorSubscriber.java:50)
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:165)
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:87)
    at reactor.core.publisher.Flux.subscribe(Flux.java:8469)
    at io.micronaut.tracing.brave.instrument.http.HttpServerTracingPublisher.subscribe(HttpServerTracingPublisher.java:85)
    at reactor.core.publisher.FluxSource.subscribe(FluxSource.java:67)
    at reactor.core.publisher.Flux.subscribe(Flux.java:8469)
    at io.micronaut.http.server.netty.RoutingInBoundHandler.handleRouteMatch(RoutingInBoundHandler.java:586)
    at io.micronaut.http.server.netty.RoutingInBoundHandler.channelRead0(RoutingInBoundHandler.java:449)
    at io.micronaut.http.server.netty.RoutingInBoundHandler.channelRead0(RoutingInBoundHandler.java:144)
    at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)

无法投射 class,不确定如何解决这个问题。

参考 - https://micronaut-projects.github.io/micronaut-data/latest/guide/#pagination

这已在最新版本的 Micronaut Data 3.4 中修复,并将包含在 Micronaut 3.5 版本中。