Search code examples
javarx-javareactivex

RxJava error handling withought swallowing the error


I'm a little bit new to RxJava. I am trying to emit another item if onError() get called without losing the error(I still want onError() to be called on the observer). but when I'm implementing each of the error handling methods declared in the docs the error being swallowed and on error isn't being called. any solutions?

edit: that's what I've tried to do yesterday -

@Override
public Observable<ArrayList<Address>> getAirports() {
    return new Observable<ArrayList<AirportPOJO>>() {
        @Override
        protected void subscribeActual(Observer<? super ArrayList<AirportPOJO>> observer) {
            try {
                // get airports from api list and map it
                ArrayList<AirportPOJO> airportsList = apiDb.getAirportsList(POJOHelper.toPOJO(AppCredentialManager.getCredentials()));
                observer.onNext(airportsList);
            } catch (Exception e) {
                e.printStackTrace();
                observer.onError(handleException(e));
            }
        }
    }.map(AirportsMappers.getAirportsPojoToDomainAirportsMapper()).doOnNext(new Consumer<ArrayList<Address>>() {
        @Override
        public void accept(ArrayList<Address> airportsList) throws Exception {
            // if airports loaded from api - save them to local db
            if (airportsList != null) {
                try {
                    localDb.saveAirportList(AirportsMappers.getAirportsToLocalDbAirportsMapper().apply(airportsList));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }).onErrorResumeNext(new Function<Throwable, ObservableSource<? extends ArrayList<Address>>>() {
        @Override
        public ObservableSource<? extends ArrayList<Address>> apply(final Throwable throwable) throws Exception {
            // load the local airports - 
            ArrayList<LocalDbAirportEntity> localAirportsEntities = localDb.getAirports();
            // map
            ArrayList<Address> airports = AirportsMappers.getLocalDbAirportsToAirportsMapper().apply(localAirportsEntities);
            // return the concat observable with the error
            return Observable.just(airports).concatWith(Observable.
                    <ArrayList<Address>>error(new Callable<Throwable>() {
                        @Override
                        public Throwable call() throws Exception {
                            return throwable;
                        }
                    }));
        }
    });
}

today I tought I might doing it wrong and tried -

@Override
public Observable<ArrayList<Address>> getAirports() {
    ArrayList<Observable<ArrayList<Address>>> observables = new ArrayList<>();
    observables.add(apiDb.getAirportsList(POJOHelper.toPOJO(AppCredentialManager.getCredentials())).map(AirportsMappers.getAirportsPojoToDomainAirportsMapper()));
    observables.add(localDb.getAirports().map(AirportsMappers.getLocalDbAirportsToAirportsMapper()));
    Observable<ArrayList<Address>> concatenatedObservable = Observable.concatDelayError(observables);
    return concatenatedObservable;
}

but I've got the same result. the onNext() called with the data of the second observable and the onError() not being called afterwards.


Solution

  • Resume with the desired value concatenated with the original error:

    source.onErrorResumeNext(error ->
        Observable.just(item).concatWith(Observable.<ItemType>error(error))
    );