question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

PublishSubject: OnNext Not delivered or OnNext delivered on wrong Thread

See original GitHub issue

I 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:closed
  • Created 7 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

6reactions
akarnokdcommented, Mar 27, 2016

The problem is that you use subscribeOn instead of observeOn to move the delivery of events to another thread. When you subscribeOn, that delays the real subscription to PublishSubject by some amount, giving enough time to onNext to be observed by no one. You see only onCompleted because PublishSubject replays the terminal event to late Subscribers.

1reaction
akarnokdcommented, Jul 17, 2018

You still have a race where onNext could find an already subscribed observer and signal the first item on the test thread.

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found