Skip to content

Releases: ReactiveX/RxJava

2.0.8

29 Mar 08:14
Compare
Choose a tag to compare

Maven

API enhancements

  • Pull 5161: Add Observable.switchMapSingle()
  • Pull 5184: Add offer() method to PublishProcessor & BehaviorProcessor.
  • Pull 5197: Add ParallelTransformer interface.
  • Pull 5217: UnicastSubject fail-fast support.
  • Pull 5202: Add resilient versions of parallel map(), filter() and doOnNext().
  • Pull 5226: UnicastProcessor fail-fast support.

Bugfixes

  • Pull 5163: Single.subscribe() to report isDisposed() true on success/error.
  • Pull 5170: Fix LambdaObserver not cancelling the upstream.
  • Pull 5182: Fix replay().refCount() leaking items between connections.
  • Pull 5188: Fix flatMap emitting the terminal exception indicator on cancel.
  • Pull 5207: Prevent tasks to self interrupt on the standard schedulers.
  • Pull 5213: Fix window() with time+size emission problems.
  • Pull 5240: fix CallbackCompletableObserver calling onError.

Documentation

  • Pull 5189: Declare concatMapEager requires positive prefetch amount.
  • Pull 5191: Correct java doc for refCount() return type.
  • Pull 5208: Fix images of firstElement, flattenAsX, flatMapIterable, UnicastSubject and UnicastProcessor.
  • Pull 5210: Better documentation on the abstract consumer classes (such as DisposableSubscriber).
  • Pull 5223: Improve the documentation of Schedulers utility class.
  • Pull 5230: Fix wrong comments in Functions “Function3” -> “BiFunction, Function3”

Other

  • Remove anonymous inner classes.
  • Pull 5183: Test to disallow anonymous inner classes.
  • Pull 5187: Reflection-based parameter validator & fixes.
  • Pull 5196: Add a few more @Nullable & @NonNull annotations to public interfaces.

1.2.9

24 Mar 09:12
Compare
Choose a tag to compare

Maven

API enhancements

  • Pull 5146: Add Single.unsubscribeOn.
  • Pull 5195: Enhance UnicastSubject with optional delay error behavior.

Bugfixes

  • Pull 5141: Fix timed replay() not terminating when all items timeout.
  • Pull 5181: replay().refCount() avoid leaking items between connections.

1.2.8

24 Mar 08:59
Compare
Choose a tag to compare
1.2.8 Pre-release
Pre-release

Accidental release of the wrong branch. Please ignore this.

2.0.7

07 Mar 09:13
Compare
Choose a tag to compare

Maven

Reactive-Streams compliance

Related issue 5110, related pull 5112.

RxJava 2's Flowable was designed with Reactive-Streams compliance in mind but didn't follow all rules to the letter. A temporary workaround was the introduction of the strict() operator to enable full compliance. Unfortunately, according to the clarified stance from the specification leads, implementors of Publisher must honor the specification (despite its shortcomings) without excuses or workarounds.

Honoring the specification adds a per-item cost of two atomic increments, manifesting in between the Flowable and an arbitrary Reactive-Streams compliant org.reactivestreams.Subscriber. See Pull 5115 for the benchmark comparison.

Starting from 2.0.7, the Flowable.subscribe(org.reactivestreams.Subscriber) now follows the spec by wrapping via the StrictSubscriber of the strict() operator unless the consuming instance implements a new interface specific to RxJava 2: FlowableSubscriber.

The FlowableSubscriber extends org.reactivestreams.Subscriber but doesn't add any new methods and only overrides four of the textual rules of the specification to enable a relaxed operation within RxJava 2. All internal operators have been converted to use this new interface and thus don't have suffer the per-item overhead required by the specification, including the standard DisposableSubscriber, TestSubscriber and ResourceSubscriber. The lambda-based subscribe() operators were also retrofitted.

If you were implementing a Subscriber (directly or anonymously), you may want to change the interface to FlowableSubscriber. In order to avoid some of the runtime checks when subscribing to Flowable the new subscribe(FlowableSubscriber) has been introduced.

Note that the other reactive base types, Observable, Single, Maybe and Completable are not affected as these were never intended to implement the Reactive-Streams specification (they were only inspired by the spec and are RxJava 2 only to begin with).

API enhancements

  • Pull 5117: Add ParallelFlowable.sequentialDelayError.
  • Pull 5137: Add TestSubscriber.withTag.
  • Pull 5140: Fix timed replay-like components replaying outdated items.
  • Pull 5155: Add TestSubscriber.awaitCount, assertTimeout & assertNoTimeout, improve assertion error message

API deprecations

  • Pull 5112: Flowable.strict() deprecated and will be removed in 2.1.0 - the default Flowable behavior is now strict.

Bugfixes

  • Pull 5101: Fix Maybe.concat() subscribe-after-cancel, verify others.
  • Pull 5103: Fix doOnSubscribe signalling UndeliverableException instead of onError.
  • Pull 5106: Fix window(time, size) not completing windows on timeout.
  • Pull 5114: Fix Observable.combineLatest to dispose eagerly.
  • Pull 5121: Fix Observable.zip to dispose eagerly.
  • Pull 5133: Fix flatMap not cancelling the upstream eagerly.
  • Pull 5136: Fix repeatWhen and retryWhen signatures.

Other

  • Pull 5102: Added missing @NonNull attribute to Function7.
  • Pull 5112: Flowable as a Publisher to be fully RS compliant.
  • Pull 5127: Update javadoc of flatMap() overloads.
  • Pull 5153: Java 9 compatibility fixes
  • Pull 5156: Add @NonNull to the methods of Emitter

1.2.7

24 Feb 08:41
Compare
Choose a tag to compare

Maven

Deprecation of create(OnSubscribe)

The method started out in RxJava 0.x as a simple and direct way for implementing custom operators because 0.x had a much simpler protocol requirements. Over the years, as the Observable protocol evolved and create became a powerful and complicated extension point of RxJava that required users to implement the Observable protocol, including cancellation and backpressure manually.

Unfortunately, guides, blogs, StackOverflow answers and mere typical user behavior still leads to this create method and lots of confusion, unstoppable sequences and MissingBackpressureException. We tried remedying the situation by introducing fromEmitter with limited discoverability success.

Therefore, as of 1.2.7 the create() method is now deprecated (but won't be removed due to binary compatibility requirements). In addition fromEmitter has been deprecate-renamed to create(Action1, BackpressureMode) and the experimental-marked fromEmitter itself will be removed in 1.3.0.

Since the functionality of create() was useful for writing (custom) operators inside and outside of RxJava, the new unsafeCreate(OnSubscribe) method was introduced as the replacement.

The new create() and unsafeCreate() methods will be fast-tracked to become standard in 1.3.0.

API enhancements

  • Pull 5086: Deprecate create(), add alternatives
  • Pull 5092: Add Single.merge(Observable<Single<T>>), Observable.flatMapSingle() & Observable.flatMapCompletable.
  • Pull 5091: Add subscribeOn(Scheduler, boolean) avoid same-pool deadlock.

API deprecations

  • Pull 5086:
    • Deprecate Observable.create(OnSubscribe),
    • Deprecate fromEmitter in favor of Observable.create(Action1, BackpressureMode).

Bugfixes

  • Pull 5091: create(Action1, BackpressureMode)+subscribeOn avoid same-pool deadlock.
  • Pull 5123: throttleFirst detecting clock-drift backwards to open the gate

Other

  • Pull 5125: reduce stack depth with switchIfEmpty

2.0.6

15 Feb 09:04
Compare
Choose a tag to compare

Maven

Undeliverable exceptions

One of the design goals of 2.x was that no errors can be lost. Sometimes, the sequence ends or gets cancelled before the source could emit an onError which has nowhere to go at that point and gets routed to the RxJavaPlugins.onError.

Unlike 1.x, 2.x by default calls Thread.currentThread().getUncaughtExceptionHandler().uncaughtException() which crashes an Android app. Many developers have noticed the increased number of app crashes when porting to 2.x due to this behavior change. Note that this doesn't mean RxJava 2 is unstable but it means you likely had these exceptions all along but they were silently dropped.

Unfortunately, RxJava can't tell which of these out-of-lifecycle, undeliverable exceptions should or shouldn't crash your app. Identifying the source and reason for these exceptions can be tiresome, especially if they originate from a source and get routed to RxJavaPlugins.onError somewhere lower the chain.

Therefore, 2.0.6 introduces specific exception wrappers to help distinguish and track down what was happening the time of the error:

  • OnErrorNotImplementedException: reintroduced to detect when the user forgot to add error handling to subscribe().
  • ProtocolViolationException: indicates a bug in an operator
  • UndeliverableException: wraps the original exception that can't be delivered due to lifecycle restrictions on a Subscriber/Observer. It is automatically applied by RxJavaPlugins.onError with intact stacktrace that may help find which exact operator rerouted the original error.

If an undeliverable exception is an instance/descendant of NullPointerException, IllegalStateException (UndeliverableException and ProtocolViolationException extend this), IllegalArgumentException, CompositeException, MissingBackpressureException or OnErrorNotImplementedException, the UndeliverableException wrapping doesn't happen.

In addition, some 3rd party libraries/code throw when they get interrupted by a cancel/dispose call which leads to an undeliverable exception most of the time. Internal changes in 2.0.6 now consistently cancel or dispose a Subscription/Disposable before cancelling/disposing a task or worker (which causes the interrupt on the target thread).

// in some library
try {
   doSomethingBlockingly()
} catch (InterruptedException ex) {
   // check if the interrupt is due to cancellation
   // if so, no need to signal the InterruptedException
   if (!disposable.isDisposed()) {
      observer.onError(ex);
   }
}

If the library/code already did this, the undeliverable InterruptedExceptions should stop now. If this pattern was not employed before, we encourage updating the code/library in question.

API enhancements

  • Pull 5036: Reintroduce OnErrorNotImplementedException for 0-1 arg subscribe.
  • Pull 5043: Add parallel hooks to RxJavaPlugins, add missing params validation
  • Pull 5080: Wrap undeliverable errors.
  • Pull 5093: Add Single.doAfterTerminate

Bugfixes

  • Pull 5064: Fix replay() cancel/dispose NullPointerException.
  • Pull 5090: fix scan(seed, f) to emit accumulated values without delay.

Other

  • Pull 5027: Dedicated Single.zip implementation, no dispose on all-success.
  • Pull 5023: Annotate function interfaces.
  • Pull 5047: Document and test amb subscription ordering.
  • Pull 5051: More @Nonnull annotations.
  • Pull 5054: Add @Nullable annotation to SimpleQueue.
  • Pull 5055: More null checks.
  • Pull 5049: Use bounded wildcards for errorHandler.
  • Pull 5075: Cancel upstream first, dispose worker last.
  • Pull 5058: More generics in RxJavaPlugins.
  • Pull 5076: Removed documentation leftover of Completable.subscribe.
  • Pull 5087: Correct marble diagram dimensions.

1.2.6

03 Feb 08:28
Compare
Choose a tag to compare

Maven

Documentation

  • Pull 5000: Add which are the other stardard methods of create
  • Pull 5007: update sample(time) diagram to indicate emission of last
  • Pull 5048: Improve the javadoc of BehaviorSubject

Bugfixes

  • Pull 5030: fix groupBy consuming the upstream in an unbounded manner

2.0.5

27 Jan 08:13
Compare
Choose a tag to compare

Maven

The most notable enhancement of this version is the inclusion of the ParallelFlowable API that allows parallel execution of a few select operators such as map, filter, concatMap, flatMap, collect, reduce and so on. Note that is a parallel mode for Flowable (a sub-domain specific language) instead of a new reactive base type.

Consequently, several typical operators such as take, skip and many others are not available and there is no ParallelObservable because backpressure is essential in not flooding the internal queues of the parallel operators as by expectation, we want to go parallel because the processing of the data is slow on one thread.

The easiest way of entering the parallel world is by using Flowable.parallel:

ParallelFlowable<Integer> source = Flowable.range(1, 1000).parallel();

By default, the parallelism level is set to the number of available CPUs (Runtime.getRuntime().availableProcessors()) and the prefetch amount from the sequential source is set to Flowable.bufferSize() (128). Both can be specified via overloads of parallel().

ParallelFlowable follows the same principles of parametric asynchrony as Flowable does, therefore, parallel() on itself doesn't introduce the asynchronous consumption of the sequential source but only prepares the parallel flow; the asynchrony is defined via the runOn(Scheduler) operator.

ParallelFlowable<Integer> psource = source.runOn(Schedulers.io());

The parallelism level (ParallelFlowable.parallelism()) doesn't have to match the parallelism level of the Scheduler. The runOn operator will use as many Scheduler.Worker instances as defined by the parallelized source. This allows ParallelFlowable to work for CPU intensive tasks via Schedulers.computation(), blocking/IO bound tasks through Schedulers.io() and unit testing via TestScheduler. You can specify the prefetch amount on runOn as well.

Once the necessary parallel operations have been applied, you can return to the sequential Flowable via the ParallelFlowable.sequential() operator.

Flowable<Integer> result = psource.filter(v -> v % 3 == 0).map(v -> v * v).sequential();

Note that sequential doesn't guarantee any ordering between values flowing through the parallel operators.

For further details, please visit the wiki page about Parallel flows. (New content will be added there as time permits.)

API enhancements

  • Pull 4955: add sample() overload that can emit the very last buffered item.
  • Pull 4966: add strict() operator for strong Reactive-Streams conformance
  • Pull 4967: add subjects for Single, Maybe and Completable
  • Pull 4972: Improve compose() generics
  • Pull 4973: Add Completable.hide()
  • Pull 4974: add Flowable.parallel() and parallel operators
  • Pull 5002: Add scheduler creation factories

Bugfixes

  • Pull 4957: fix LambdaObserver calling dispose when terminating
  • Pull 4962: fix takeUntil() other triggering twice
  • Pull 4970: fix withLatestFrom null checks, lifecycle
  • Pull 4982: fix Observable.concatMapEager bad logic for immediate scalars.
  • Pull 4984: fix cross-boundary invalid fusion with observeOn, flatMap & zip
  • Pull 4987: Make Observable.combineLatest consistent with Flowable, fix early termination cancelling the other sources and document empty source case
  • Pull 4992: A.flatMapB to eagerly check for cancellations before subscribing
  • Pull 5005: ExecutorScheduler.scheduleDirect to report isDisposed on task completion

Other

  • Pull 4971: Add @CheckReturnValue to create() methods of Subjects + Processors
  • Pull 4980: Update Copyright to 'RxJava Contributors'
  • Pull 4990: Update marble diagrams for sample() overloads, Maybe and Maybe.switchIfEmpty()
  • Pull 5015: Fix Reactive-Streams dependency to be compile in the library's POM
  • Pull 5020: option to fail for using blockingX on the computation/single scheduler

1.2.5

06 Jan 12:00
Compare
Choose a tag to compare

Maven

Documentation

  • Pull 4963: Add missing marbles, fix image sizes

Bugfixes

  • Pull 4941: Fix Completable.mergeDelayError to check unsafe availability

2.0.4

04 Jan 09:08
Compare
Choose a tag to compare

Maven

API enhancements

Bugfixes

  • Pull 4927: fix timer() IllegalStateException due to bad resource management
  • Pull 4932: Add safeguards to generate()
  • Pull 4943: Fix publish(Function) not replenishing its internal queue
  • Pull 4945: Fix timeout with fallback not cancelling/disposing the main source connection.