@Override public void call(Subscriber<? super T> subscriber) { if (refresh.compareAndSet(true, false)) { current = source.cache(); } current.unsafeSubscribe(subscriber); }
@Test public void testZip() { Observable<String> os = OBSERVABLE_OF_5_INTEGERS.zip( OBSERVABLE_OF_5_INTEGERS, new Func2<Integer, Integer, String>() { @Override public String call(Integer a, Integer b) { return a + "-" + b; } }); final ArrayList<String> list = new ArrayList<String>(); os.subscribe( new Action1<String>() { @Override public void call(String s) { System.out.println(s); list.add(s); } }); assertEquals(5, list.size()); assertEquals("1-1", list.get(0)); assertEquals("2-2", list.get(1)); assertEquals("5-5", list.get(4)); }
/** IO scheduler defaults to using CachedThreadScheduler */ @Test public final void testIOScheduler() { Observable<Integer> o1 = Observable.from(1, 2, 3, 4, 5); Observable<Integer> o2 = Observable.from(6, 7, 8, 9, 10); Observable<String> o = Observable.merge(o1, o2) .map( new Func1<Integer, String>() { @Override public String call(Integer t) { assertTrue( Thread.currentThread().getName().startsWith("RxCachedThreadScheduler")); return "Value_" + t + "_Thread_" + Thread.currentThread().getName(); } }); o.subscribeOn(Schedulers.io()) .toBlocking() .forEach( new Action1<String>() { @Override public void call(String t) { System.out.println("t: " + t); } }); }
/** If the 'other' onCompletes then we unsubscribe from the source and onComplete */ @Test @SuppressWarnings("unchecked") public void testTakeUntilOtherCompleted() { Subscription sSource = mock(Subscription.class); Subscription sOther = mock(Subscription.class); TestObservable source = new TestObservable(sSource); TestObservable other = new TestObservable(sOther); Observer<String> result = mock(Observer.class); Observable<String> stringObservable = Observable.create(source).takeUntil(Observable.create(other)); stringObservable.subscribe(result); source.sendOnNext("one"); source.sendOnNext("two"); other.sendOnCompleted(); source.sendOnNext("three"); verify(result, times(1)).onNext("one"); verify(result, times(1)).onNext("two"); verify(result, times(0)).onNext("three"); verify(result, times(1)).onCompleted(); verify(sSource, times(1)).unsubscribe(); verify(sOther, times(1)) .unsubscribe(); // unsubscribed since SafeSubscriber unsubscribes after onComplete }
@Test public void testResumeNext() { Subscription s = mock(Subscription.class); // Trigger failure on second element TestObservable f = new TestObservable(s, "one", "fail", "two", "three"); Observable<String> w = Observable.create(f); Observable<String> resume = Observable.from("twoResume", "threeResume"); Observable<String> observable = Observable.create(onErrorResumeNextViaObservable(w, resume)); @SuppressWarnings("unchecked") Observer<String> observer = mock(Observer.class); observable.subscribe(observer); try { f.t.join(); } catch (InterruptedException e) { fail(e.getMessage()); } verify(observer, Mockito.never()).onError(any(Throwable.class)); verify(observer, times(1)).onCompleted(); verify(observer, times(1)).onNext("one"); verify(observer, Mockito.never()).onNext("two"); verify(observer, Mockito.never()).onNext("three"); verify(observer, times(1)).onNext("twoResume"); verify(observer, times(1)).onNext("threeResume"); }
/** Simple concat of 2 asynchronous observables ensuring it emits in correct order. */ @SuppressWarnings("unchecked") @Test public void testSimpleAsyncConcat() { Observer<String> observer = mock(Observer.class); TestObservable<String> o1 = new TestObservable<String>("one", "two", "three"); TestObservable<String> o2 = new TestObservable<String>("four", "five", "six"); Observable.concat(Observable.create(o1), Observable.create(o2)).subscribe(observer); try { // wait for async observables to complete o1.t.join(); o2.t.join(); } catch (Throwable e) { throw new RuntimeException("failed waiting on threads"); } InOrder inOrder = inOrder(observer); inOrder.verify(observer, times(1)).onNext("one"); inOrder.verify(observer, times(1)).onNext("two"); inOrder.verify(observer, times(1)).onNext("three"); inOrder.verify(observer, times(1)).onNext("four"); inOrder.verify(observer, times(1)).onNext("five"); inOrder.verify(observer, times(1)).onNext("six"); }
@Test(groups = "standalone") public void testObserveMultiple() { final TestSubscriber<Response> tester = new TestSubscriber<>(); try (AsyncHttpClient client = asyncHttpClient()) { Observable<Response> o1 = AsyncHttpObservable.observe(() -> client.prepareGet("http://gatling.io")); Observable<Response> o2 = AsyncHttpObservable.observe( () -> client.prepareGet("http://www.wisc.edu").setFollowRedirect(true)); Observable<Response> o3 = AsyncHttpObservable.observe( () -> client.prepareGet("http://www.umn.edu").setFollowRedirect(true)); Observable<Response> all = Observable.merge(o1, o2, o3); all.subscribe(tester); tester.awaitTerminalEvent(); tester.assertTerminalEvent(); tester.assertCompleted(); tester.assertNoErrors(); List<Response> responses = tester.getOnNextEvents(); assertNotNull(responses); assertEquals(responses.size(), 3); for (Response response : responses) { assertEquals(response.getStatusCode(), 200); } } catch (Exception e) { Thread.currentThread().interrupt(); } }
@SuppressWarnings({"unchecked", "RedundantCast"}) private static Observable<Object> invokeWithRetry( Api api, Method method, Object[] args, Predicate<Throwable> shouldRetryTest, int retryCount) throws IllegalAccessException, InvocationTargetException { Observable<Object> result = (Observable<Object>) method.invoke(api, args); for (int i = 0; i < retryCount; i++) { result = result.onErrorResumeNext( err -> { if (shouldRetryTest.apply(err)) { try { // give the server a small grace period before trying again. Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS); logger.warn("perform retry, calling method {} again", method); return (Observable<Object>) method.invoke(api, args); } catch (Exception error) { return Observable.error(error); } } else { // forward error if it is not a network problem return Observable.error(err); } }); } return result; }
// Get the image from the filesystem if it exists or download from network private Observable<Page> getOrDownloadImage(final Page page, Download download) { // If the image URL is empty, do nothing if (page.getImageUrl() == null) return Observable.just(page); String filename = getImageFilename(page); File imagePath = new File(download.directory, filename); // If the image is already downloaded, do nothing. Otherwise download from network Observable<Page> pageObservable = isImageDownloaded(imagePath) ? Observable.just(page) : downloadImage(page, download.source, download.directory, filename); return pageObservable // When the image is ready, set image path, progress (just in case) and status .doOnNext( p -> { page.setImagePath(imagePath.getAbsolutePath()); page.setProgress(100); download.downloadedImages++; page.setStatus(Page.READY); }) // Mark this page as error and allow to download the remaining .onErrorResumeNext( e -> { page.setProgress(0); page.setStatus(Page.ERROR); return Observable.just(page); }); }
@Test public void testBackpressureWithTakeBefore() { final AtomicInteger generated = new AtomicInteger(); Observable<Integer> observable = Observable.from( new Iterable<Integer>() { @Override public Iterator<Integer> iterator() { return new Iterator<Integer>() { @Override public void remove() {} @Override public Integer next() { return generated.getAndIncrement(); } @Override public boolean hasNext() { return true; } }; } }); TestSubscriber<Integer> testSubscriber = new TestSubscriber<Integer>(); observable.take(7).observeOn(Schedulers.newThread()).subscribe(testSubscriber); testSubscriber.awaitTerminalEvent(); testSubscriber.assertReceivedOnNext(Arrays.asList(0, 1, 2, 3, 4, 5, 6)); assertEquals(7, generated.get()); }
@Test @SuppressWarnings("unchecked") public void testOrdering() throws InterruptedException { Observable<String> obs = Observable.just("one", null, "two", "three", "four"); Observer<String> observer = mock(Observer.class); InOrder inOrder = inOrder(observer); TestSubscriber<String> ts = new TestSubscriber<String>(observer); obs.observeOn(Schedulers.computation()).subscribe(ts); ts.awaitTerminalEvent(1000, TimeUnit.MILLISECONDS); if (ts.getOnErrorEvents().size() > 0) { for (Throwable t : ts.getOnErrorEvents()) { t.printStackTrace(); } fail("failed with exception"); } inOrder.verify(observer, times(1)).onNext("one"); inOrder.verify(observer, times(1)).onNext(null); inOrder.verify(observer, times(1)).onNext("two"); inOrder.verify(observer, times(1)).onNext("three"); inOrder.verify(observer, times(1)).onNext("four"); inOrder.verify(observer, times(1)).onCompleted(); inOrder.verifyNoMoreInteractions(); }
@Test public void observeOnTheSameSchedulerTwice() { Scheduler scheduler = Schedulers.immediate(); Observable<Integer> o = Observable.just(1, 2, 3); Observable<Integer> o2 = o.observeOn(scheduler); @SuppressWarnings("unchecked") Observer<Object> observer1 = mock(Observer.class); @SuppressWarnings("unchecked") Observer<Object> observer2 = mock(Observer.class); InOrder inOrder1 = inOrder(observer1); InOrder inOrder2 = inOrder(observer2); o2.subscribe(observer1); o2.subscribe(observer2); inOrder1.verify(observer1, times(1)).onNext(1); inOrder1.verify(observer1, times(1)).onNext(2); inOrder1.verify(observer1, times(1)).onNext(3); inOrder1.verify(observer1, times(1)).onCompleted(); verify(observer1, never()).onError(any(Throwable.class)); inOrder1.verifyNoMoreInteractions(); inOrder2.verify(observer2, times(1)).onNext(1); inOrder2.verify(observer2, times(1)).onNext(2); inOrder2.verify(observer2, times(1)).onNext(3); inOrder2.verify(observer2, times(1)).onCompleted(); verify(observer2, never()).onError(any(Throwable.class)); inOrder2.verifyNoMoreInteractions(); }
/** One time setup of the FFmpeg library. */ public Observable<Void> setupFFmpeg() { if (!firstSetup.get()) return Observable.just(null); firstSetup.set(false); return Observable.create( new Observable.OnSubscribe<Void>() { @Override public void call(final Subscriber<? super Void> subscriber) { LoadBinaryResponseHandler responseHandler = new LoadBinaryResponseHandler() { @Override public void onFailure() { if (subscriber.isUnsubscribed()) return; subscriber.onError(new IllegalStateException("failed to load FFmpeg binaries")); } @Override public void onSuccess() { if (subscriber.isUnsubscribed()) return; subscriber.onNext(null); subscriber.onCompleted(); } }; try { fFmpeg.loadBinary(responseHandler); } catch (FFmpegNotSupportedException e) { subscriber.onError(e); } } }); }
@Test public void testDebounceNeverEmits() { Observable<String> source = Observable.create( new OnSubscribeFunc<String>() { @Override public Subscription onSubscribe(Observer<? super String> observer) { // all should be skipped since they are happening faster than the 200ms timeout publishNext(observer, 100, "a"); // Should be skipped publishNext(observer, 200, "b"); // Should be skipped publishNext(observer, 300, "c"); // Should be skipped publishNext(observer, 400, "d"); // Should be skipped publishNext(observer, 500, "e"); // Should be skipped publishNext(observer, 600, "f"); // Should be skipped publishNext(observer, 700, "g"); // Should be skipped publishNext(observer, 800, "h"); // Should be skipped publishCompleted( observer, 900); // Should be published as soon as the timeout expires. return Subscriptions.empty(); } }); Observable<String> sampled = Observable.create( OperationDebounce.debounce(source, 200, TimeUnit.MILLISECONDS, scheduler)); sampled.subscribe(observer); scheduler.advanceTimeTo(0, TimeUnit.MILLISECONDS); InOrder inOrder = inOrder(observer); inOrder.verify(observer, times(0)).onNext(anyString()); scheduler.advanceTimeTo(1000, TimeUnit.MILLISECONDS); inOrder.verify(observer, times(1)).onCompleted(); inOrder.verifyNoMoreInteractions(); }
Object apply( final Object[] args, final TProtocol protocol, final int seqid, Scheduler subscribScheduler) throws Exception { if (isObservable) { Observable observable = Observable.create( new Observable.OnSubscribe<Object>() { @Override public void call(Subscriber<? super Object> subscriber) { try { if (subscriber.isUnsubscribed()) { return; } subscriber.onNext(FunctionCall.this.sendAndRecv(args, protocol, seqid)); subscriber.onCompleted(); } catch (Exception e) { subscriber.onError(e); } } }); if (null != subscribScheduler) return observable.subscribeOn(subscribScheduler); else return observable; } return sendAndRecv(args, protocol, seqid); }
/** Bind view on immediate scheduler. */ public static <T> Observable<T> bindViewImmediate(View view, Observable<T> source) { if (view == null || source == null) throw new IllegalArgumentException("View and Observable must be given"); return source .takeUntil(Observable.create(new OnSubscribeViewDetachedFromWindowFirst(view))) .observeOn(Schedulers.immediate()); }
@Test public void testZippingDifferentLengthObservableSequences2() { @SuppressWarnings("unchecked") Observer<String> w = mock(Observer.class); TestObservable w1 = new TestObservable(); TestObservable w2 = new TestObservable(); TestObservable w3 = new TestObservable(); Observable<String> zipW = Observable.create(zip(w1, w2, w3, getConcat3StringsZipr())); zipW.subscribe(w); /* simulate sending data */ // 4 times for w1 w1.Observer.onNext("1a"); w1.Observer.onNext("1b"); w1.Observer.onNext("1c"); w1.Observer.onNext("1d"); w1.Observer.onCompleted(); // twice for w2 w2.Observer.onNext("2a"); w2.Observer.onNext("2b"); w2.Observer.onCompleted(); // 1 times for w3 w3.Observer.onNext("3a"); w3.Observer.onCompleted(); /* we should have been called 1 time on the Observer */ InOrder inOrder = inOrder(w); inOrder.verify(w).onNext("1a2a3a"); inOrder.verify(w, times(1)).onCompleted(); }
public static void main(String[] args) { Common.init("Hello RxJava"); Observable<String> tweets = Observable.just("Hello RxJava!", "RxJava is fun!!", "RxJava rocks!!!"); tweets.subscribe((s) -> System.out.println(s)); }
@Test public void concatVeryLongObservableOfObservablesTakeHalf() { final int n = 10000; Observable<Observable<Integer>> source = Observable.create( new OnSubscribe<Observable<Integer>>() { @Override public void call(Subscriber<? super Observable<Integer>> s) { for (int i = 0; i < n; i++) { if (s.isUnsubscribed()) { return; } s.onNext(Observable.from(i)); } s.onCompleted(); } }); Observable<List<Integer>> result = Observable.concat(source).take(n / 2).toList(); Observer<List<Integer>> o = mock(Observer.class); InOrder inOrder = inOrder(o); result.subscribe(o); List<Integer> list = new ArrayList<Integer>(n); for (int i = 0; i < n / 2; i++) { list.add(i); } inOrder.verify(o).onNext(list); inOrder.verify(o).onCompleted(); verify(o, never()).onError(any(Throwable.class)); }
private static void test4() { log("just subscribe to see output "); Observable<List<Integer>> listOfInts = Observable.just(Arrays.asList(1, 3, 5, 7), Arrays.asList(2, 4, 6, 8)); listOfInts.subscribe(x -> System.out.print(x + " ")); println(""); log("concatMap"); listOfInts.concatMap(x -> Observable.from(x)).subscribe(Main::print); println(""); log("flapMap"); listOfInts .flatMap( listOfIntegers -> { return Observable.from(listOfIntegers); }) .subscribe(Main::print); println(""); Map<String, List<Integer>> m1 = new HashMap<>(); m1.put("key", Arrays.asList(2, 4, 6, 8, 10)); Map<String, List<Integer>> m2 = new HashMap<>(); m2.put("key", Arrays.asList(1, 3, 5, 7, 9)); log("testing flatMap with 2 maps param"); Observable.just(m1, m2) .flatMap(map -> Observable.from(map.get("key")).map(x -> x)) .subscribe(Main::print); println(""); }
@Test public void testSkipTimedFinishBeforeTime() { TestScheduler scheduler = new TestScheduler(); PublishSubject<Integer> source = PublishSubject.create(); Observable<Integer> result = source.skip(1, TimeUnit.SECONDS, scheduler); Observer<Object> o = mock(Observer.class); result.subscribe(o); source.onNext(1); source.onNext(2); source.onNext(3); source.onCompleted(); scheduler.advanceTimeBy(1, TimeUnit.SECONDS); InOrder inOrder = inOrder(o); inOrder.verify(o).onCompleted(); inOrder.verifyNoMoreInteractions(); verify(o, never()).onNext(any()); verify(o, never()).onError(any(Throwable.class)); }
public Observable<List<TwitterUser>> searchUsers(String prefix) { if (ThreadLocalRandom.current().nextDouble() < failureProbability) { return Observable.error(new IOException("Broken pipe")); } return Observable.from(users).skip(1).toList().subscribeOn(Schedulers.newThread()); }
@Test @SuppressWarnings("unchecked") public void testTakeUntilSourceError() { Subscription sSource = mock(Subscription.class); Subscription sOther = mock(Subscription.class); TestObservable source = new TestObservable(sSource); TestObservable other = new TestObservable(sOther); Throwable error = new Throwable(); Observer<String> result = mock(Observer.class); Observable<String> stringObservable = Observable.create(source).takeUntil(Observable.create(other)); stringObservable.subscribe(result); source.sendOnNext("one"); source.sendOnNext("two"); source.sendOnError(error); source.sendOnNext("three"); verify(result, times(1)).onNext("one"); verify(result, times(1)).onNext("two"); verify(result, times(0)).onNext("three"); verify(result, times(1)).onError(error); verify(sSource, times(1)).unsubscribe(); verify(sOther, times(1)).unsubscribe(); }
@Test public void testSingleWithBackpressure() { Observable<Integer> observable = Observable.just(1, 2).single(); Subscriber<Integer> subscriber = spy( new Subscriber<Integer>() { @Override public void onStart() { request(1); } @Override public void onCompleted() {} @Override public void onError(Throwable e) {} @Override public void onNext(Integer integer) { request(1); } }); observable.subscribe(subscriber); InOrder inOrder = inOrder(subscriber); inOrder.verify(subscriber, times(1)).onError(isA(IllegalArgumentException.class)); inOrder.verifyNoMoreInteractions(); }
public void importGDMModel(final String filePath) throws IOException { final Observable<Resource> gdmModel = getGDMModel(filePath); gdmModel .map( resource -> { try { processGDMResource(resource); } catch (final Exception e) { final String message = "something went wrong while processing this resource"; LOG.error(message, e); throw WikidataImporterError.wrap(new WikidataImporterException(message, e)); } return resource; }) .toBlocking() .lastOrDefault(null); // TODO: return Observable (?) }
private Observable<Item> searchByHashtagObservable() { Observable<Item> observableSocialNetworks = Observable.from(socialNetworks) .flatMap( new Func1<SocialNetwork, Observable<Item>>() { @Override public Observable<Item> call(SocialNetwork socialNetwork) { return socialNetwork.getService().searchByHashtag(hashtag); } }); List<Observable<Item>> observableList = Lists.newArrayList(); observableList.add(observableSocialNetworks); return Observable.zip( observableList, new FuncN<Item>() { @Override public Item call(Object... args) { if (args.length == 1) { return (Item) args[0]; } return Item.empty(); } }); }
@Test public void testEmitNull() { Observable<Integer> oi = Observable.from(1, null, 3); Observable<String> os = Observable.from("a", "b", null); Observable<String> o = Observable.zip( oi, os, new Func2<Integer, String, String>() { @Override public String call(Integer t1, String t2) { return t1 + "-" + t2; } }); final ArrayList<String> list = new ArrayList<String>(); o.subscribe( new Action1<String>() { @Override public void call(String s) { System.out.println(s); list.add(s); } }); assertEquals(3, list.size()); assertEquals("1-a", list.get(0)); assertEquals("null-b", list.get(1)); assertEquals("3-null", list.get(2)); }
public static void main(String[] args) { // A basic Observable that emits "Hello World" when someone subscribes to it Observable<String> simpleObservable = Observable.create( new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("Hello, world"); subscriber.onCompleted(); } }); // A basic Subscriber to consume the data. All it does is emit a string emitted by the // observable Subscriber<String> simpleSubscriber = new Subscriber<String>() { @Override public void onCompleted() {} @Override public void onError(Throwable throwable) {} @Override public void onNext(String s) { System.out.println(s); } }; simpleObservable.subscribe(simpleSubscriber); }
@Test public void testUnsubscribeAfterTake() { final Subscription s = mock(Subscription.class); TestObservableFunc f = new TestObservableFunc("one", "two", "three"); Observable<String> w = Observable.create(f); @SuppressWarnings("unchecked") Observer<String> observer = mock(Observer.class); Subscriber<String> subscriber = Subscribers.from(observer); subscriber.add(s); Observable<String> take = w.lift(new OperatorTake<String>(1)); take.subscribe(subscriber); // wait for the Observable to complete try { f.t.join(); } catch (Throwable e) { e.printStackTrace(); fail(e.getMessage()); } System.out.println("TestObservable thread finished"); verify(observer, times(1)).onNext("one"); verify(observer, never()).onNext("two"); verify(observer, never()).onNext("three"); verify(observer, times(1)).onCompleted(); verify(s, times(1)).unsubscribe(); verifyNoMoreInteractions(observer); }
@Override public void onError(Throwable e) { long p = produced; if (p != 0L) { arbiter.produced(p); } Observable<T> o; try { o = onError.call(e); } catch (Throwable ex) { Exceptions.throwIfFatal(ex); actual.onError(new CompositeException(e, ex)); return; } if (o == null) { actual.onError( new NullPointerException("The onError function returned a null Observable.")); } else { o.unsafeSubscribe(new ResumeSubscriber<T>(actual, arbiter)); } }