PublishSubject: OnNext Not delivered or OnNext delivered on wrong Thread
See original GitHub issueI was writing some automated test to verify the behaviour of PublishSubject and I noticed strange and unexpected behaviour when the subject is subscribed on a Scheduler. If I do not put a sleep after the subscriber, I will not get the onNext items but the onCompleted is called on the correct Thread. If I put a sleep after subscribing, the subscriber receives the onNext items but on the wrong thread. It receives the onNext items on the thread that called the subject.onNext.
I wrote some unit test to show the behaviour. Both tests will fail with rxjava 1.1.2. Is this a bug or is this expected behavior and where can I find this in the documentation?
import org.junit.Test;
import rx.observers.TestSubscriber;
import rx.subjects.PublishSubject;
import static org.assertj.core.api.Assertions.assertThat;
import static rx.schedulers.Schedulers.newThread;
public class PublishSubjectTest {
@Test
public void subscribeOn_WhenNoSleep_ThenNoOnNextReceived() throws InterruptedException {
// GIVEN
PublishSubject<String> subject = PublishSubject.create();
Thread currentThread = Thread.currentThread();
TestSubscriber<String> subscriber = new TestSubscriber<>();
// WHEN
subject.subscribeOn(newThread()).subscribe(subscriber);
subject.onNext("one");
subject.onCompleted();
// THEN
subscriber.awaitTerminalEvent();
assertThat(subscriber.getLastSeenThread()).isNotSameAs(currentThread);
assertThat(subscriber.getOnNextEvents()).containsOnly("one");
}
@Test
public void subscribeOn_WhenSleep_ThenOnNextReceivedButOnWrongThread() throws InterruptedException {
// GIVEN
PublishSubject<String> subject = PublishSubject.create();
Thread currentThread = Thread.currentThread();
TestSubscriber<String> subscriber = new TestSubscriber<>();
// WHEN
subject.subscribeOn(newThread()).subscribe(subscriber);
Thread.sleep(2000);
subject.onNext("one");
subject.onCompleted();
// THEN
subscriber.awaitTerminalEvent();
assertThat(subscriber.getOnNextEvents()).containsOnly("one");
assertThat(subscriber.getLastSeenThread()).isNotSameAs(currentThread);
}
}
Issue Analytics
- State:
- Created 7 years ago
- Comments:5 (3 by maintainers)
Top Results From Across the Web
RxJava2.1.0 : PublishSubject onNext not invoked when ...
Ok, the issue is with PublishSubject; use of ReplaySubject seems to fix this problem of concurrent subscription; there is also an issue with ......
Read more >PublishSubject (RxJava Javadoc 3.0.1) - ReactiveX
Calling onNext(Object) , onError(Throwable) and onComplete() is required to be serialized (called from the same thread or called non-overlappingly from ...
Read more >RxJava: listen for events after error | by Andranik Azizbekian
publishSubject.onNext("2");. This will result in the following output: 1 java.lang.IllegalArgumentException: err1. Note, “2” is not present in the output, ...
Read more >3 things i learned about rxjava 2 subjects - helw.net
subscribeOn(Schedulers.io()) , but call subject.onNext(value) from the main thread, the downstream will receive onNext on the main thread. see ...
Read more >This is Not an RxJava Tutorial - Paco won't stop learning
onNext() receives any amount of values, and either onCompleted() or ... to imperative code and use the Observable as the response delivery.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
The problem is that you use
subscribeOn
instead ofobserveOn
to move the delivery of events to another thread. When yousubscribeOn
, that delays the real subscription toPublishSubject
by some amount, giving enough time toonNext
to be observed by no one. You see onlyonCompleted
becausePublishSubject
replays the terminal event to lateSubscriber
s.You still have a race where onNext could find an already subscribed observer and signal the first item on the test thread.