RxJava 2没有告诉错误行

时间:2017-02-28 11:26:12

标签: java rx-java2

在我看来,RxJava没有提供良好的异常跟踪。

这是我在运行单元测试时从Eclipse获得的一个例子。目前尚不清楚使用map函数的代码。

是否有任何增加跟踪能力的特殊技巧?或者这被视为一个错误?

2017-02-28 19:12:44/SGT INFO  c.bt.nmdb.ndac.adapter.Bnmpv5Adapter     : Current time stamp - Tue Dec 23 23:56:00 SGT 2014
2017-02-28 19:12:45/SGT TRACE c.bt.nmdb.ndac.adapter.Bnmpv5Adapter     : @findAndSendDeviceCredentials()
io.reactivex.exceptions.OnErrorNotImplementedException: The mapper function returned a null value.
    at io.reactivex.internal.functions.Functions$14.accept(Functions.java:229)
    at io.reactivex.internal.functions.Functions$14.accept(Functions.java:226)
    at io.reactivex.internal.subscribers.LambdaSubscriber.onError(LambdaSubscriber.java:75)
    at io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onError(FlowableDoOnEach.java:109)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.onError(BasicFuseableSubscriber.java:100)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.fail(BasicFuseableSubscriber.java:110)
    at io.reactivex.internal.operators.flowable.FlowableMap$MapSubscriber.onNext(FlowableMap.java:65)
    at io.reactivex.internal.operators.flowable.FlowableFromArray$ArraySubscription.fastPath(FlowableFromArray.java:134)
    at io.reactivex.internal.operators.flowable.FlowableFromArray$BaseArraySubscription.request(FlowableFromArray.java:87)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.request(BasicFuseableSubscriber.java:152)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.request(BasicFuseableSubscriber.java:152)
    at io.reactivex.internal.subscribers.LambdaSubscriber.request(LambdaSubscriber.java:110)
    at io.reactivex.internal.operators.flowable.FlowableInternalHelper$RequestMax.accept(FlowableInternalHelper.java:244)
    at io.reactivex.internal.operators.flowable.FlowableInternalHelper$RequestMax.accept(FlowableInternalHelper.java:240)
    at io.reactivex.internal.subscribers.LambdaSubscriber.onSubscribe(LambdaSubscriber.java:48)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.onSubscribe(BasicFuseableSubscriber.java:66)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.onSubscribe(BasicFuseableSubscriber.java:66)
    at io.reactivex.internal.operators.flowable.FlowableFromArray.subscribeActual(FlowableFromArray.java:37)
    at io.reactivex.Flowable.subscribe(Flowable.java:12901)
    at io.reactivex.internal.operators.flowable.FlowableMap.subscribeActual(FlowableMap.java:37)
    at io.reactivex.Flowable.subscribe(Flowable.java:12901)
    at io.reactivex.internal.operators.flowable.FlowableDoOnEach.subscribeActual(FlowableDoOnEach.java:48)
    at io.reactivex.Flowable.subscribe(Flowable.java:12901)
    at io.reactivex.Flowable.subscribe(Flowable.java:12886)
    at io.reactivex.Flowable.subscribe(Flowable.java:12746)
    at michsan.adapter.Bnmpv5Adapter_On_FindAndSendDeviceCredentials_TestCase.shouldFindDeviceCredentialsAndBuildResponses(Bnmpv5Adapter_On_FindAndSendDeviceCredentials_TestCase.java:71)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.NullPointerException: The mapper function returned a null value.
    at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39)
    at io.reactivex.internal.operators.flowable.FlowableMap$MapSubscriber.onNext(FlowableMap.java:63)
    ... 43 more
Exception in thread "main" io.reactivex.exceptions.OnErrorNotImplementedException: The mapper function returned a null value.
    at io.reactivex.internal.functions.Functions$14.accept(Functions.java:229)
    at io.reactivex.internal.functions.Functions$14.accept(Functions.java:226)
    at io.reactivex.internal.subscribers.LambdaSubscriber.onError(LambdaSubscriber.java:75)
    at io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onError(FlowableDoOnEach.java:109)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.onError(BasicFuseableSubscriber.java:100)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.fail(BasicFuseableSubscriber.java:110)
    at io.reactivex.internal.operators.flowable.FlowableMap$MapSubscriber.onNext(FlowableMap.java:65)
    at io.reactivex.internal.operators.flowable.FlowableFromArray$ArraySubscription.fastPath(FlowableFromArray.java:134)
    at io.reactivex.internal.operators.flowable.FlowableFromArray$BaseArraySubscription.request(FlowableFromArray.java:87)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.request(BasicFuseableSubscriber.java:152)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.request(BasicFuseableSubscriber.java:152)
    at io.reactivex.internal.subscribers.LambdaSubscriber.request(LambdaSubscriber.java:110)
    at io.reactivex.internal.operators.flowable.FlowableInternalHelper$RequestMax.accept(FlowableInternalHelper.java:244)
    at io.reactivex.internal.operators.flowable.FlowableInternalHelper$RequestMax.accept(FlowableInternalHelper.java:240)
    at io.reactivex.internal.subscribers.LambdaSubscriber.onSubscribe(LambdaSubscriber.java:48)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.onSubscribe(BasicFuseableSubscriber.java:66)
    at io.reactivex.internal.subscribers.BasicFuseableSubscriber.onSubscribe(BasicFuseableSubscriber.java:66)
    at io.reactivex.internal.operators.flowable.FlowableFromArray.subscribeActual(FlowableFromArray.java:37)
    at io.reactivex.Flowable.subscribe(Flowable.java:12901)
    at io.reactivex.internal.operators.flowable.FlowableMap.subscribeActual(FlowableMap.java:37)
    at io.reactivex.Flowable.subscribe(Flowable.java:12901)
    at io.reactivex.internal.operators.flowable.FlowableDoOnEach.subscribeActual(FlowableDoOnEach.java:48)
    at io.reactivex.Flowable.subscribe(Flowable.java:12901)
    at io.reactivex.Flowable.subscribe(Flowable.java:12886)
    at io.reactivex.Flowable.subscribe(Flowable.java:12746)
    at michsan.adapter.Bnmpv5Adapter_On_FindAndSendDeviceCredentials_TestCase.shouldFindDeviceCredentialsAndBuildResponses(Bnmpv5Adapter_On_FindAndSendDeviceCredentials_TestCase.java:71)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.NullPointerException: The mapper function returned a null value.
    at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39)
    at io.reactivex.internal.operators.flowable.FlowableMap$MapSubscriber.onNext(FlowableMap.java:63)
    ... 43 more

1 个答案:

答案 0 :(得分:1)

建立akarnokd的答案,你想使用RxJavaPlugins为每个Flowable,Observable添加一个钩子......例如,正如akarnokd在他的带有Flowables的RxJava2Extensions库中做的那样:

RxJavaPlugins.setOnFlowableAssembly(new Function<Flowable, Flowable>() {
    @Override
    public Flowable apply(Flowable f) throws Exception {
        // Play with the Stack, collect info
        return new FlowableOnAssembly(f);
    }
});

这样,您可以在FlowableOnAssembly中收集信息(例如堆栈)。此时,如果您可以捕获崩溃,您可以访问您添加的信息(stacktrace,以及您放入FlowableOnAssembly的任何其他内容)。

为了便于调试,即使在远程设备中,您也可以设置DefaultUncaughtExceptionHandler来捕获任何崩溃并打印您在FlowableOnAssembly中收集的信息,例如:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        if (e instanceOf FlowableOnAssembly) {
            // Print the info you captured
        }
    }
};

这个机制将拦截RxJava2所做的一切,所以你可能想要轻松放入/删除启用/禁用它。您可以使用我为此目的编写的小型库:

RxJava2Debug

RxJava2Debug将为您创建一个简单的StackTrace。或者,它也会过滤它,因此根本原因的第一个条目指向您的代码(这样像Crashlytics这样的服务可以为您整理不同的错误。)