Search code examples
javajavafxreactive-programmingrx-javareactfx

Most effective way to turn Observable into ObservableValue/Binding/EventStream?


I will be using RxJava and ReactFX more heavily, but what I am trying to understand is how to reconcile the two since ReactFX does not have an RxJava dependency, so how can the two talk to each other within the same monad? This is especially the case for bridging between JavaFX's ObservableValue, RxJava's Observable, and ReactFX's StreamEvent without a lot of boilerplate.

I want to compose my core business logic with RxJava since they won't always be backing JavaFX applications. But I want the JavaFX UI to use ReactFX and utilize the EventStream. So my question is what is the most effective way to turn an EventStream into an Observable, and an Observable into an EventStream, Binding, or ObservableValue? I know I could just use RxJava across the board but I want to leverage ReactFX's Platform thread safety and conveniences...

//DESIRE 1- Turn EventStream into Observable in the same monad
Observable<Foo> obs = EventStream.valuesOf(fooObservableValue).toObservable();

//Desire 2- Turn Observable into ObservableValue, Eventstream, or Binding
Binding<Foo> obsVal = Observable.create(...).toBinding();

Solution

  • To turn ReactFX EventStream into RxJava Observable:

    Observable<Foo> toRx(EventStream<Foo> es) {
        PublishSubject<Foo> sub = PublishSubject.create();
        es.subscribe(sub::onNext);
        return sub;
    }
    

    To turn RxJava Observable into ReactFX EventStream:

    EventStream<Foo> fromRx(Observable<Foo> obs) {
        EventSource<Foo> es = new EventSource<>();
        obs.subscribe(foo -> Platform.runLater(() -> es.push(foo)));
        return es;
    }
    

    Notice the Platform.runLater(...) in the latter case. This makes the resulting EventStream emit events on the JavaFX application thread.

    Also note that we are ignoring the Subscriptions returned from the subscribe methods in both cases. This is fine if you are establishing the binding for the lifetime of your application. If, on the other hand, the binding between them should be short-lived, in the first case, you would have your RxJava component expose the Subject, your ReactFX component expose the EventStream, and then do subscribe/unsubscribe as necessary. Similarly for the second case.