Reactor - 在 flatMap 的输出上调用块导致 ClassCastException
Reactor - Calling block on output of flatMap causes ClassCastException
我正在使用 Spring Boot 2.0.0.M7 和 Project Reactor。我的问题与编写单元测试时遇到的一些 st运行ge 行为有关。在尝试将 flatMap
的输出输入存储库时,我也 运行 加入了此内容。
Mono<Foo> create(Mono<FooResource> resourceMono) {
resourceMono.flatMap({
// convert resource into Foo domain Entity
return new Foo()
})
}
由于 flatMap
的 return 值,此闭包应发出 Mono<Foo>
。但是调用block()
订阅得到结果Foo
的时候,在FluxFlatMap.trySubscribeScalarMap
中有一个ClassCastException
测试代码:
def createdFoo = Foo.create(Mono.just(fooResource)).block()
堆栈跟踪:
java.lang.ClassCastException: com.example.Foo cannot be cast to org.reactivestreams.Publisher
at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:141)
at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:53)
at reactor.core.publisher.Mono.block(Mono.java:1161)
这似乎是因为 MonoJust
实现了 Callable
,所以 trySubscribeScalarMap
尝试解包失败。
在非测试用例场景下,出现类似错误。
Mono<ServerResponse> createFoo(ServerRequest request) {
def body = request.body(BodyExtractors.toMono(FooResource))
ok().body(fromPublisher(Foo.create(body)
.flatMap({fooRepository.save(it)}), Foo))
}
堆栈跟踪:
java.lang.ClassCastException: com.example.Foo cannot be cast to reactor.core.publisher.Mono
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118) [reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:450) ~[reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1092) ~[reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at reactor.core.publisher.MonoSingle$SingleSubscriber.onComplete(MonoSingle.java:171) ~[reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE]
<...>
Assembly trace from producer [reactor.core.publisher.MonoFlatMap] :
reactor.core.publisher.Mono.flatMap(Mono.java:2059)
org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap.invoke(PojoMetaMethodSite.java:213)
org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
com.example.Foo.create(Foo.groovy:28)
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
com.example.FooHandlerFunctions.createFoo(FooHandlerFunctions.groovy:48)
将 flatMap
闭包的输出包装在另一个 Mono.just(foo)
中可以解决这两个问题。但是,似乎不需要这样做。我是做错了什么还是只是误解了 flatMap
在这里的工作原理?
flatmap
需要一个 Function
应该 return 一个 Mono
(我猜 groovy 让你 return 错误的类型,因为 Foo
似乎没有实现 Publisher
?)
我正在使用 Spring Boot 2.0.0.M7 和 Project Reactor。我的问题与编写单元测试时遇到的一些 st运行ge 行为有关。在尝试将 flatMap
的输出输入存储库时,我也 运行 加入了此内容。
Mono<Foo> create(Mono<FooResource> resourceMono) {
resourceMono.flatMap({
// convert resource into Foo domain Entity
return new Foo()
})
}
由于 flatMap
的 return 值,此闭包应发出 Mono<Foo>
。但是调用block()
订阅得到结果Foo
的时候,在FluxFlatMap.trySubscribeScalarMap
ClassCastException
测试代码:
def createdFoo = Foo.create(Mono.just(fooResource)).block()
堆栈跟踪:
java.lang.ClassCastException: com.example.Foo cannot be cast to org.reactivestreams.Publisher
at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:141)
at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:53)
at reactor.core.publisher.Mono.block(Mono.java:1161)
这似乎是因为 MonoJust
实现了 Callable
,所以 trySubscribeScalarMap
尝试解包失败。
在非测试用例场景下,出现类似错误。
Mono<ServerResponse> createFoo(ServerRequest request) {
def body = request.body(BodyExtractors.toMono(FooResource))
ok().body(fromPublisher(Foo.create(body)
.flatMap({fooRepository.save(it)}), Foo))
}
堆栈跟踪:
java.lang.ClassCastException: com.example.Foo cannot be cast to reactor.core.publisher.Mono
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118) [reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:450) ~[reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1092) ~[reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at reactor.core.publisher.MonoSingle$SingleSubscriber.onComplete(MonoSingle.java:171) ~[reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE]
<...>
Assembly trace from producer [reactor.core.publisher.MonoFlatMap] :
reactor.core.publisher.Mono.flatMap(Mono.java:2059)
org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap.invoke(PojoMetaMethodSite.java:213)
org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
com.example.Foo.create(Foo.groovy:28)
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
com.example.FooHandlerFunctions.createFoo(FooHandlerFunctions.groovy:48)
将 flatMap
闭包的输出包装在另一个 Mono.just(foo)
中可以解决这两个问题。但是,似乎不需要这样做。我是做错了什么还是只是误解了 flatMap
在这里的工作原理?
flatmap
需要一个 Function
应该 return 一个 Mono
(我猜 groovy 让你 return 错误的类型,因为 Foo
似乎没有实现 Publisher
?)