Reactor - 在flatMap的输出上调用块会导致ClassCastException(Reactor - Calling block on output of flatMap causes ClassCastException)
我正在使用Spring Boot 2.0.0.M7和Project Reactor。 我的问题涉及编写单元测试时遇到的一些奇怪的行为。 在尝试将
flatMap
的输出提供给存储库时,我也遇到了这个问题。Mono<Foo> create(Mono<FooResource> resourceMono) { resourceMono.flatMap({ // convert resource into Foo domain Entity return new Foo() }) }
由于
flatMap
的返回值,这个闭包应该发出一个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)
在另一个
Mono.just(foo)
封装flatMap
闭包的输出解决了这两个问题。 但是,这似乎不应该需要。 我做错了什么或者误解了flatMap
在这里的工作原理?I'm using Spring Boot 2.0.0.M7 and Project Reactor. My issue is relating to some strange behavior encountered while writing a Unit test. I also ran into this while trying to feed the output of
flatMap
into the repository.Mono<Foo> create(Mono<FooResource> resourceMono) { resourceMono.flatMap({ // convert resource into Foo domain Entity return new Foo() }) }
This closure should emit a
Mono<Foo>
due to the return value offlatMap
. However, when callingblock()
to subscribe and get the resultingFoo
, there is aClassCastException
inFluxFlatMap.trySubscribeScalarMap
Test code:
def createdFoo = Foo.create(Mono.just(fooResource)).block()
Stack Trace:
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)
This appears to occur because
MonoJust
implementsCallable
, sotrySubscribeScalarMap
tries to unwrap it unsuccessfully.In a non-test case scenario, a similar error occurs.
Mono<ServerResponse> createFoo(ServerRequest request) { def body = request.body(BodyExtractors.toMono(FooResource)) ok().body(fromPublisher(Foo.create(body) .flatMap({fooRepository.save(it)}), Foo)) }
Stack trace:
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)
Wrapping the output of the
flatMap
closure in anotherMono.just(foo)
solves both issues. However, it seems like that shouldn't be needed. Am I doing something wrong or just misunderstanding howflatMap
works here?
原文:https://stackoverflow.com/questions/47994303
最满意答案
当然有办法做到这一点! 天无绝人之路!
任何人,我认为你正在寻找的是远程服务器。 这取决于你有多少钱可以用几种方法完成。
(1)如果你一直都像我一样摔断,那么你可以在家中制作一台额外的电脑,作为你的应用程序的服务器。 尽管如此,这可能会导致几个(:) hehe几个)安全问题。 您的家庭网络上也会有很多流量。
(2)它是获得域名和虚拟主机的另一种选择。 我见过的大多数网络托管服务都提供数据库支持。 所以你可以做的是跳上,在Web主机服务器上创建你的数据库,然后将你的应用程序链接到你的服务器。 其成本因您的需求而异。
真的,是你的应用程序与多个人交互? 我想不出你会希望在任何其他电话(设备)上使用此功能的原因,而不是(相对于我们的客户)设备。 我很少将设备交给其他人,除非锁定,否则绝不会。
Of course there is way to do it! There is always a way!
Anywho, what I think you are looking for is a remote server. These can be done in a few way depending on how much money you have.
(1)If you're broke like me all the time, then you can make an extra computer you have at home act as a server for your app. This can cause a few ( :) hehe few) security issues for your home though. Also you will have a lot of traffic on your home network.
(2)Another option it's to get a domain name and web host. Most of the web hosting services I have seen offer database support. So what you could do is hop on, create your database on the web host server then link your app to your server. The cost on that varies based on your needs.
Really though, is your app interfacing with mulitple people? I can't think of a reason you would want this feature on any other phone (device) than your (relative to us customers) device. I rarely hand my device over to others, and never unless it's locked.
相关问答
更多-
确保XAMPP中的Apache模块已启动,并且您的Android手机已连接到您的路由器(假设您在无线网络上)。 查找托管服务器的计算机的本地IP地址。 例如,我的是192.168.1.142。 这可能与您的相似也可能不相似。 在手机的URL栏中输入该IP地址。 您可能还需要将端口号附加到该端口号,具体取决于服务器设置。 例如,如果XAMPP在端口8080上运行Apache:192.168.1.142:8080。 要获取本地IP,它会因操作系统而略有不同。 对于Windows,转到命令提示符并执行ipconf ...
-
当然有办法做到这一点! 天无绝人之路! 任何人,我认为你正在寻找的是远程服务器。 这取决于你有多少钱可以用几种方法完成。 (1)如果你一直都像我一样摔断,那么你可以在家中制作一台额外的电脑,作为你的应用程序的服务器。 尽管如此,这可能会导致几个(:) hehe几个)安全问题。 您的家庭网络上也会有很多流量。 (2)它是获得域名和虚拟主机的另一种选择。 我见过的大多数网络托管服务都提供数据库支持。 所以你可以做的是跳上,在Web主机服务器上创建你的数据库,然后将你的应用程序链接到你的服务器。 其成本因您的需求 ...
-
注意:我没有足够的声望来发布包含两个以上链接的帖子:/以下所有项目都应该通过网络搜索很容易找到。 收集breakpad崩溃报告是否存在更好的项目? Mozilla的Socorro是Mozilla使用的一个开源项目,用于收集Firefox等应用程序的breakpad崩溃报告。 您可以通过搜索Mozilla崩溃统计信息来查看他们的Socorro实例。 有没有好的托管选项? 我只知道有三家公司提供了托管的breakpad崩溃管理选项:Backtrace I / O,Bugsplat和Raygun I / O。 充 ...
-
您可能需要更新JAR文件,但为什么在可以使用Gradle获取依赖项时使用JAR文件? dependencies { compile 'com.parse.bolts:bolts-android:1.+' compile 'com.parse:parse-android:1.+' } 此外,Play服务目前是8.4.0 ,除非您确实需要所有 Play服务,否则建议您只选择您真正使用的依赖项 。 You might need to update your JAR files, but why ...
-
本指南可能比您真正要求的信息更多,但Web服务器信息就在那里。 它是Gentoo特有的,但是您可以将相同的信息与小版本应用到其他发行版。 This guide is probably more info than you really requested, but webserver information is in there. It's Gentoo-specific, but you can apply the same information with minor translations to ...
-
我在html5中为android和ios开发应用程序,我将在云端托管它,可能是亚马逊。 使用云,您将支付您真正使用的内容。 使用传统托管服务,无论您的应用程序是否被使用,您都需要按年/月支付固定金额。 云是动态的,所以如果您的应用突然变成populuar,您的应用仍然可以正常工作,因为云提供商将提供更多资源。 我试试亚马逊,因为它在一定数量的资源需求下免费。 对于第二个问题,我认为这些api没有问题。 Im developing an app in html5 for android and ios and ...
-
那么我解决了这个问题,通过我的无线路由器访问我的笔记本电脑的IPv4,并通过它连接到我的服务器的端口。 最初,我的浏览器(我的笔记本电脑和手机)都无法访问服务器的端口。 但后来我发现它是我的.yml配置文件中的问题。 服务器没有设置为监听所有的IPv4呼叫,而是监听所有的IPv6。 所以我改变了这一点,然后就可以在同一个wifi上访问所有设备。 所以把它连接到热点是我的坏主意:P Well I solved this problem by accessing IPv4 of my laptop throug ...
-
您可以配置 (通过XML或代码)具有特定超时的端点。 这是在servicehost启动时设置的,运行时无法更改。 同样不,客户端无法设置服务超时,因为这会使拒绝服务攻击变得非常容易。 您最好通过隔离“文件上载服务”并相应地配置其端点。 You can configure (throught XML or code) an endpoint with certain timeouts. This is set at servicehost startup and can't be changed while ...
-
只有在WCF中确保“互操作性”的绑定才是BasicHttpBinding 。 如果您需要最小过载,请不要使用WCF。 编写自己的基于tcp的协议,使用套接字或任何你喜欢的。 这是非常类似问题的答案。 Only binding that assures "interoperability" in WCF is BasicHttpBinding. If you need minimum overload don't use WCF. Write your own tcp based protocol, use ...
-
将router.Run从router.Run("127.0.0.1:8080")更改为router.Run(":8080")并且它可以正常工作。 正如@elithrar和@ user3591723所建议的那样127.0.0.1(本地主机)只是机器上的环回接口绑定到“:8080”意味着0.0.0.0:8080 - 这意味着所有接口 Changed the router.Run from router.Run("127.0.0.1:8080") to router.Run(":8080") and it wor ...