1

I am trying to get the hang of creating a SyncOnSubscribe and not quite sure what to do if the generateState method fails during initialization of the state.

return Observable.create(new SyncOnSubscribe<MyState, String>() {
    @Override
    protected MyState generateState() {
        return new MyState();   // <---- what if this fails?
    }

    @Override
    protected MyState next(MyState state, Observer<? super String> observer) {
        // do something with state
    }
});

I can think of a couple of ways that this could be handled offhand:

  1. If a runtime exception is thrown, does the library automatically call o.onError? (see EDIT).
  2. I could wrap MyState in another variable that stores the error and I can call o.onError on my own the first time that next is invoked.

I'm just curious if there is a suggested practice around this?

Thanks!

EDIT: I tried just throwing a runtime exception in the generateState method, and I think it points me to wrapping MyState with an error that I will inspect in the next method. PLEASE comment/answer if you have a better suggestion.

public static Observable<String> getEventsOnSubscribe1() {
    return Observable.create((s) -> {
        throw new UnsupportedOperationException("getEvents3");
    });
};

/** Like 'getEventsOnSubscribe1' but wrap exception and call onError manually.  */
public static Observable<String> getEventsOnSubscribe2() {
    return Observable.create((s) -> {
        try {
            throw new UnsupportedOperationException("getEvents3");
        } catch (Exception ex) {
            s.onError(ex);
        }
    });
};

public static Observable<String> getEventsSyncOnSubscribe() {
    return Observable.create(new SyncOnSubscribe<Channel, String>() {
        @Override
        protected Channel generateState() {
            System.out.println("SyncOnSubscribe.generateState");
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        protected Channel next(Channel state, Observer<? super String> observer) {
            System.out.println("SyncOnSubscribe.next");
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        protected void onUnsubscribe(Channel state) {
            System.out.println("SyncOnSubscribe.onUnsubscribe");
            throw new UnsupportedOperationException("Not supported yet.");
        }
    });
}

public static void main(String[] args) throws IOException, TimeoutException {
    getEventsOnSubscribe1()
    //getEventsOnSubscribe2()
    //getEventsOnSyncSubscribe()
            .toBlocking()
            .subscribe(new Subscriber<String>() {
                @Override
                public void onCompleted() {
                    System.out.println("onCompleted");
                }

                @Override
                public void onError(Throwable e) {
                    System.out.println("onError: " + e.getLocalizedMessage());
                }

                @Override
                public void onNext(String t) {
                    System.out.println("onNext: " + t);
                }
            });
}

With the main function above getEventsOnSubscribe1 and getEventsSyncOnSubscribe both call the subscriber onError, but they leave the program hanging. Using getEventsOnSubscribe2 which wraps the exception and manually calls s.onError, the program is able to exit.

Danny G
  • 581
  • 4
  • 16
  • 1
    This appears to be an error handling bug with `SyncOnSubscribe`. I'll post a fix for it soon – akarnokd Jan 25 '16 at 21:10
  • @akarnokd I may have been mistaken, I can't seem to reproduce what I was seeing earlier - the program not exiting may have been due to a different library spawning a daemon thread. I'll reply back here if I see the issue again. Thanks! – Danny G Jan 28 '16 at 15:54

0 Answers0