RxJava 2 doesn't tell the error line

送分小仙女□ 提交于 2019-12-25 05:36:19

问题


It seems to me that RxJava doesn't give good exception tracing.

One example is this which I got from Eclipse when running my unit test. It is not clear which code using the map function.

Is there any special trick to increase the tracing ability? Or is this considered as a bug?

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:


Building up on akarnokd's answer, you want to use RxJavaPlugins to add a hook for each Flowable, Observable,... For instance, as akarnokd does in his RxJava2Extensions library with Flowables:

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

This way, you can collect info (the stack, for instance) in that FlowableOnAssembly. At this point, if you can capture crashes, you can already access that info you added (stacktrace, and whatever else you put into FlowableOnAssembly).

For easier debugging, even in remote devices, you can set a DefaultUncaughtExceptionHandler to capture any crash and print the info you collected in FlowableOnAssembly, for instance:

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

This mechanism will be intercepting everything RxJava2 does, so you probably want to put/remove enable/disable it easily. You can go use a small library I wrote for this purpose in:

RxJava2Debug

RxJava2Debug will create a nice simple StackTrace for you. Optionally, it will also filter it so the first entry of the root cause points to your code (this way services like Crashlytics can collate different errors for you).



来源:https://stackoverflow.com/questions/42507511/rxjava-2-doesnt-tell-the-error-line

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!