2

I've already added onErrorReturn and doOnError, but I still get fatal error. Here's my code:

 apiInterface.submitDataToAnalyze("dataToAnalyze", HelperFunctions.authenticationData, 1, uuid, dataToAnalyze.toString(), todayDate)
                                .onErrorReturn(new Func1<Throwable, BasicResponse>() {
                                    @Override
                                    public BasicResponse call(Throwable throwable) {
                                        Log.e(FILE_NAME, "submitDataToAnalyze throwable??");
                                        Log.e(FILE_NAME, throwable.getMessage().toString());
                                        return null;
                                    }
                                })
                                .flatMap(new Func1<BasicResponse, Observable<LocationSuggestion>>() {
                                    @Override
                                    public Observable<LocationSuggestion> call(BasicResponse basicResponse) {
                                        Log.v(FILE_NAME, "basicResponse: " + basicResponse.toString());
                                        if (basicResponse.getResult() == 1) {
                                            //update TABLE_REQUEST_SUGGESTIONS with serverResponse = 1
                                            dbc.updateRequestSuggestionLog(strTodayDate, strDataToAnalyze, basicResponse.getResult());
                                            return apiInterface.getSuggestion("getSuggestion", HelperFunctions.authenticationData, HelperFunctions.requestVersion, uuid,
                                                    strLocationLat, strLocationLng, radius, requestForDate);
                                        } else {
                                            return Observable.just(null);
                                        }
                                    }
                                }).doOnError(new Action1<Throwable>() {
                            @Override
                            public void call(Throwable t) {
                                Log.e(FILE_NAME, "masuk doOnError??");
                                Log.e(FILE_NAME, t.getMessage().toString());
                            }


                        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe();

                }

Specifically, here's the error message:

E/ISRS: masuk doOnError??
E/ISRS: masuk 22??
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.IllegalStateException: Exception thrown on Scheduler.Worker thread. Add `onError` handling.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:60)

Additional information: the fatal error would occur if submitDataToAnalyze() has problem connecting to my server due to bad connection etc

imin
  • 4,504
  • 13
  • 56
  • 103
  • I don't think that returing `null` in the `onErrorReturn`is a good idea, especially if you use that value in the `flatMap` without making any check. – rciovati Dec 22 '15 at 18:00
  • @RiccardoCiovati in that case, what should I return there? – imin Dec 22 '15 at 18:02
  • It should be fine to return `null` but you should check it in the `flatMap`. However I'm not sure it's right to do that, moreover I think you should just remove the `onErrorReturn` at all because it's useless there. Note that `doOnError` doesn't actually catch the exception. If you want to catch it you should pass the proper callback in the `subscribe` method. – rciovati Dec 22 '15 at 19:28
  • Ouh so what actually the onErrorReturn and doOnError there do? Btw sorry I missed an important info - that is, the error will be thrown when submitDataToAnalyze() failed to connect to my server (due to bad connection etc) – imin Dec 23 '15 at 02:56
  • `onErrorReturn` is useful when, in case of an error, you don't want to break the call chain e provide a value that the next call (in your case the `flatMap`) could use to perform its job. As far as I can see in your code, if `submitDataToAnalyze` fails you don't want to perform the code in the `.flatMap` so for that reason I'm saying that you could remove the `onErrorReturn`. `doOnError`is a hook to have notification that an exception occurred but if you want to catch it you need a proper subscriber. – rciovati Dec 23 '15 at 09:37
  • Here is my newbie response on a duplicate question : http://stackoverflow.com/questions/29655840/how-to-properly-handle-onerror-inside-rxjava-android/38017291#38017291 – Tobliug Jun 24 '16 at 15:50

1 Answers1

7

In onErrorReturn method you return null, and then this null is propagated further along the chain. So it causes NPE (eg basicResponse.toString()). In this case doOnError is invocated, but your subscriber still get Throwable, that stays unhandled.

So you have to pass Subscriber instance with onError implementation.

Another option: in your chain you can use something like onErrorResumeNext(Observable.empty()), so it'll emit nothing and then complete. In this case you are have not to pass Subscriber implementation to subscribe.

VasyaFromRussia
  • 1,872
  • 2
  • 14
  • 18
  • Ok.. understood..I think :p. Anyway in my case here, I think onErrorResumeNext suites me better.. but could you show me how to add it inside my code above? I changed onErrorReturn() to .onErrorResumeNext(Observable.empty()) but all I got was "Cannot resolve method 'onErrorResumeNext(rx.Observable)' – imin Dec 23 '15 at 17:11
  • `onErrorResumeNext` takes Func1 as parameter, so you have to write something like `onErrorResumeNext(throwable -> Observable.empty())` (expand lambda if you use java 6/7). Here you can read much more about error handling in RxJava, and there's javadoc about all of methods: https://github.com/ReactiveX/RxJava/wiki/Error-Handling-Operators – VasyaFromRussia Dec 25 '15 at 15:28