0

I have following code that demonstrates issue:

@Component
public class App {
    @Autowired S1 s1;
    @Autowired S2 s2;
    int jobs = 0;
    @Scheduled(cron = "0 * * * * ?")
    void foo() {
        System.out.println("schedule cron job: " + jobs++);
        Observable<String> observable = Observable.just("bar");
        ConnectableObservable<String> publishedObservable = observable.publish();
        publishedObservable.subscribe(s1);
        publishedObservable.subscribe(s2);
        publishedObservable.connect();
    }
}

Subscriber1:

@Component
public class S1 extends Subscriber<String> {
    private AtomicInteger counter = new AtomicInteger(0);

    @Override
    public void onCompleted() {
    }

    @Override
    public void onError(Throwable e) {
    }

    @Override
    public void onNext(String s) {
        System.out.println("S1:::: Times called: " + counter.getAndIncrement() + ", input: " + s);

    }
}

Subscriber2:

@Component
public class S2 extends Subscriber<String> {
    private AtomicInteger counter = new AtomicInteger(0);

    @Override
    public void onCompleted() {
    }

    @Override
    public void onError(Throwable e) {
    }

    @Override
    public void onNext(String s) {
        System.out.println("S2:::: Times called: " + counter.getAndIncrement() + ", input: " + s);
    }
}

The output will be:

schedule cron job: 0
S1:::: Times called: 0, input: bar
S2:::: Times called: 0, input: bar
schedule cron job: 1
schedule cron job: 2
schedule cron job: 3
schedule cron job: 4
......

Why is S1 and S2 not called each time the foo method called ? How to achieve that ?

Is this because rx some subscriptions logic or because of these beans are singletons?

marknorkin
  • 3,904
  • 10
  • 46
  • 82

1 Answers1

2

Why is S1 and S2 not called each time the foo method called ?

RxJava Subscribers are stateful and once they consumed a sequence they are no longer usable and report themselves as unsubscribed. Subscribing with them again has no effect. You have to re-create them each time you need to subscribe to the source.

akarnokd
  • 69,132
  • 14
  • 157
  • 192
  • Thank you for clarifying this out. Is this will be an option ? `publishedObservable.subscribe(s1::onNext, s1::onError, s1::onCompleted); publishedObservable.subscribe(s2::onNext, s2::onError, s2::onCompleted);` or is it better to use prototype scope ? – marknorkin Sep 28 '16 at 12:16
  • Use an `Observer`. – akarnokd Sep 28 '16 at 12:31
  • `Observers` are sateless and can be reused ? in some subscribers i use `onStart` method, where this logic can be moved ? `publishedObservable.subscribe(s1::onNext, s1::onError, s1::onCompleted);` that is why is won't work for me I think – marknorkin Sep 28 '16 at 12:38
  • That won't work with `Observer` and won't happen with `s1::` style either. Recreate the `Subscriber`s in `foo()`. – akarnokd Sep 28 '16 at 12:40