3

I started learning about reactive streams because I was curious about this new trend of using RxJava as a replacement for more traditional event buses. This blog post is a typical description of how this is done. If I understand correctly, RxJava 1.x was not strictly an implementation of Reactive Streams, but it was very similar. Version 2.0 includes some classes that are compliant, or at least pass the TCK, so an updated version of this code may look a little different.

public class UserLocationModel {

  private PublishSubject<LatLng> subject = PublishSubject.create();

  public void setLocation(LatLng latLng) {
    subject.onNext(latLng);
  }

  public Observable<LatLng> getUserLocation() {
    return subject;
  }
}

In Reactive Streams terminology, I think subject is a Processor, which is both a Publisher and a Subscriber.

The problem is that calling onNext on a Subscriber that isn't subscribed to anything would seem to violate the Reactive Streams spec, particularly rule 1.9.

Is it merely an implementation detail that this works at all? Am I correct in thinking that you cannot generally rely on this working with a compliant Reactive Streams implementation?

Kevin Krumwiede
  • 9,868
  • 4
  • 34
  • 82

1 Answers1

7

Subjects and Processors of standard RxJava 2 are relaxed so you don't have to call onSubscribe on them before calling the other methods. This is partly due to traditionality as 1.x Subjects didn't have an onSubscribe and partly due to the fact that RxJava 2 Processors don't coordinate requests between the Subscriber side and the Publisher side by choice and thus have no use for a Subscription.

If you subscribe an RxJava Processor any RS compliant Publisher, they will appear to request Long.MAX_VALUE and relay signals as much as possible. If you subscribe an RS compliant Subscriber to RxJava Processors, they will honor the backpressure of those Subscribers and never overflow them, however, the lack of requests may result in individual MissingBackpressureException being emitted and the Subscriber "thrown" away. There is a custom Publisher in the extensions library that does coordinate requests.

Am I correct in thinking that you cannot generally rely on this working with a compliant Reactive Streams implementation.

There is nothing in the specification and thus not tested in the TCK what should happen with a Processor that didn't receive an onSubscribe call yet it needed it, therefore, I think this has become an implementation detail.

There are two bigger issues here:

  1. Subjects were invented to bridge the imperative world with the reactive world and work nicely in GUI cases and non-backpressured cases as the multicasters of events. In reactive-reactive multicasts, they are better and more direct alternatives, such as publish(Function).
  2. Thinking in event bus is a step backwards because you create a single choke point by shoveling in and draining out events on a single "rail". In contrast, design for reactive favors individual and often independent streams where each stream can jump between threads as necessary and perhaps avoid the main thread till the very last moment.
akarnokd
  • 69,132
  • 14
  • 157
  • 192