Java Code Examples for reactor.core.publisher.Mono#subscribe()

The following examples show how to use reactor.core.publisher.Mono#subscribe() . These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source Project: tutorials   File: EmployeeWebClient.java    License: MIT License 8 votes vote down vote up
public void consume() {

        Mono<Employee> employeeMono = client.get()
            .uri("/employees/{id}", "1")
            .retrieve()
            .bodyToMono(Employee.class);

        employeeMono.subscribe(System.out::println);
        
        Flux<Employee> employeeFlux = client.get()
            .uri("/employees")
            .retrieve()
            .bodyToFlux(Employee.class);
        
        employeeFlux.subscribe(System.out::println);
    }
 
Example 2
@Test
public void subscriptionOfManyNotifications() throws Exception {
	//given
	log.info("About to create Mono");

	//when
	final Mono<Integer> work = Mono.fromCallable(() -> {
		log.info("Doing hard work");
		return 42;
	});

	//then
	log.info("Mono was created");

	work.subscribe(
			i -> log.info("Received {}", i),
			ex -> log.error("Opps!", ex),
			() -> log.info("Mono completed")
	);

	log.info("Work is done");
}
 
Example 3
Source Project: reactor-core   File: FluxTests.java    License: Apache License 2.0 6 votes vote down vote up
@Test
public void testStreamBatchesResults() {
	Flux<String> stream = Flux.just("1", "2", "3", "4", "5");
	Mono<List<Integer>> s = stream.map(STRING_2_INTEGER)
	                                .collectList();

	final AtomicInteger batchCount = new AtomicInteger();
	final AtomicInteger count = new AtomicInteger();
	s.subscribe(is -> {
		batchCount.incrementAndGet();
		for (int i : is) {
			count.addAndGet(i);
		}
	});

	assertThat("batchCount is 3", batchCount.get(), is(1));
	assertThat("count is 15", count.get(), is(15));
}
 
Example 4
@Override
public <R> Mono<R> reactive(Callable<RFuture<R>> supplier) {
    Mono<R> mono = super.reactive(new Callable<RFuture<R>>() {
        volatile RFuture<R> future;
        @Override
        public RFuture<R> call() throws Exception {
            if (future == null) {
                synchronized (this) {
                    if (future == null) {
                        future = supplier.call();
                    }
                }
            }
            return future;
        }
    });
    mono.subscribe();
    return mono;
}
 
Example 5
@Test
@Disabled("invalid")
@Timeout(2_000)
public void testRequestReplyErrorOnSend() {
  rule.connection.setAvailability(0); // Fails send
  Mono<Payload> response = rule.socket.requestResponse(EmptyPayload.INSTANCE);
  Subscriber<Payload> responseSub = TestSubscriber.create(10);
  response.subscribe(responseSub);

  this.rule
      .socket
      .onClose()
      .as(StepVerifier::create)
      .expectComplete()
      .verify(Duration.ofMillis(100));

  verify(responseSub).onSubscribe(any(Subscription.class));

  rule.assertHasNoLeaks();
  // TODO this should get the error reported through the response subscription
  //    verify(responseSub).onError(any(RuntimeException.class));
}
 
Example 6
/**
 * TODO create a {@link Mono} that completes with an error
 */
@Test
public void monoCompletingWithError() {
	//given

	//when
	final Mono<Integer> work = null;

	//then
	work.subscribe(
			i -> onNext.set(true),
			ex -> error.set(ex),
			() -> completed.set(true)
	);

	//Hint: you don't normally test streams like that! Don't get used to it
	assertThat(onNext).isFalse();
	assertThat(error.get())
			.isInstanceOf(IOException.class)
			.hasMessage("Simulated");
	assertThat(completed).isFalse();
}
 
Example 7
/**
 * TODO create a {@link Mono} that completes normally without emitting any value
 */
@Test
public void monoCompletingWithoutAnyValue() throws Exception {
	//given

	//when
	final Mono<Integer> work = null;

	//then
	work.subscribe(
			i -> onNext.set(true),
			ex -> error.set(ex),
			() -> completed.set(true)
	);

	//Hint: you don't normally test streams like that! Don't get used to it
	assertThat(onNext).isFalse();
	assertThat(error).hasValue(null);
	assertThat(completed).isTrue();
}
 
Example 8
@Test
void shouldNotConsiderPendingMessageDeleteAsInconsistency(CassandraCluster cassandra) throws Exception {
    messageIdDAO.insert(MESSAGE_1).block();

    Scenario.Barrier barrier = new Scenario.Barrier(1);
    cassandra.getConf()
        .registerScenario(awaitOn(barrier)
            .thenExecuteNormally()
            .times(1)
            .whenQueryStartsWith("SELECT messageId,mailboxId,uid,modSeq,flagAnswered,flagDeleted," +
                "flagDraft,flagFlagged,flagRecent,flagSeen,flagUser,userFlags FROM messageIdTable " +
                "WHERE mailboxId=:mailboxId AND uid=:uid;"));

    Context context = new Context();
    Mono<Task.Result> task = testee.fixMessageInconsistencies(context, RunningOptions.DEFAULT).subscribeOn(Schedulers.elastic()).cache();
    task.subscribe();

    barrier.awaitCaller();
    messageIdDAO.delete(MAILBOX_ID, MESSAGE_UID_1).block();
    barrier.releaseCaller();

    task.block();

    // Verify that no inconsistency is fixed
    assertThat(context.snapshot())
        .isEqualTo(Context.Snapshot.builder()
            .processedImapUidEntries(0)
            .processedMessageIdEntries(1)
            .build());
}
 
Example 9
@Test
public void testRetrieveSpaceSummary() {
	Mono<GetSpaceSummaryResponse> response1 = subject.retrieveSpaceSummary("dummy");
	response1.subscribe();
	Mockito.verify(this.parentMock, Mockito.times(1)).retrieveSpaceSummary("dummy");
	
	Mono<GetSpaceSummaryResponse> response2 = subject.retrieveSpaceSummary("dummy");
	response2.subscribe();
	assertThat(response1).isNotEqualTo(response2);
	Mockito.verify(this.parentMock, Mockito.times(2)).retrieveSpaceSummary("dummy");
}
 
Example 10
@PostMapping(path="fromEmail", consumes="application/json")
@ResponseStatus(HttpStatus.CREATED)
public Mono<Order> postOrderFromEmail(@RequestBody Mono<EmailOrder> emailOrder) {
  Mono<Order> order = emailOrderService.convertEmailOrderToDomainOrder(emailOrder);
  order.subscribe(orderMessages::sendOrder); // TODO: not ideal...work into reactive flow below
  return order
      .flatMap(repo::save);
}
 
Example 11
public void validateFareReactively(BookingRecord record){
 	Mono<Fare> result = webClient.get()
 			                      .uri("/fares/get?flightNumber="+record.getFlightNumber()+"&flightDate="+record.getFlightDate())
 			                      .accept(MediaType.APPLICATION_JSON)
 			                      .exchange()
 			                      .flatMap(response -> response.bodyToMono(Fare.class));
	result.subscribe(fare ->  checkFare(record.getFare(),fare.getFare()));
	
}
 
Example 12
@Test
public void testRetrieveOrgId() throws InterruptedException {
	Mono<ListOrganizationsResponse> response1 = subject.retrieveOrgId("dummy");
	response1.subscribe();
	Mockito.verify(this.parentMock, Mockito.times(1)).retrieveOrgId("dummy");
	
	// required to permit asynchronous updates of caches => test stability
	Thread.sleep(10);
	
	Mono<ListOrganizationsResponse> response2 = subject.retrieveOrgId("dummy");
	response2.subscribe();
	assertThat(response1).isNotEqualTo(response2);
	Mockito.verify(this.parentMock, Mockito.times(2)).retrieveOrgId("dummy");
}
 
Example 13
@Test
public void givenAnEmptyMono_WhenTheDefaultIfEmptyOperatorIsUsed_ThenTheDefaultValueIsDeliveredAsResult() throws Exception {
    String defaultMessage = "Hello world";
    Mono<String> emptyMonoMessageProduced = Mono.empty();

    Mono<String> monoMessageDelivered = emptyMonoMessageProduced.defaultIfEmpty(defaultMessage);

    monoMessageDelivered.subscribe(messageDelivered ->
            Assert.assertEquals(defaultMessage, messageDelivered));
}
 
Example 14
Source Project: reactor-core   File: ScannableTest.java    License: Apache License 2.0 5 votes vote down vote up
@Test
public void operatorChainWithoutDebugMode() {
	List<String> downstream = new ArrayList<>();

	Mono<?> m=
			Flux.from(s -> {
				Scannable thisSubscriber = Scannable.from(s);
				assertThat(thisSubscriber.isScanAvailable()).as("thisSubscriber.isScanAvailable").isTrue();
				thisSubscriber.steps().forEach(downstream::add);
			})
			    .map(a -> a)
			    .filter(a -> true)
			    .reduce((a, b) -> b);

	m.subscribe();

	assertThat(downstream)
			.as("from downstream")
			.containsExactly(
			"map",
			"filter",
			"reduce",
			"lambda");


	Scannable thisOperator = Scannable.from(m);

	assertThat(thisOperator.isScanAvailable())
			.as("thisOperator.isScanAvailable")
			.isTrue();
	assertThat(thisOperator.steps())
			.as("from upstream")
			.containsExactly(
			"source(FluxSource)",
			"map",
			"filter",
			"reduce");
}
 
Example 15
@Test
void shouldNotConsiderPendingMessageUpdatesAsInconsistency(CassandraCluster cassandra) throws Exception {
    imapUidDAO.insert(MESSAGE_1_WITH_SEEN_FLAG).block();
    messageIdDAO.insert(MESSAGE_1).block();

    Scenario.Barrier barrier = new Scenario.Barrier(1);
    cassandra.getConf()
        .registerScenario(awaitOn(barrier)
            .thenExecuteNormally()
            .times(1)
            .whenQueryStartsWith("SELECT messageId,mailboxId,uid,modSeq,flagAnswered,flagDeleted,flagDraft,flagFlagged,flagRecent,flagSeen,flagUser,userFlags FROM messageIdTable WHERE mailboxId=:mailboxId AND uid=:uid;"));

    Context context = new Context();
    Mono<Task.Result> task = testee.fixMessageInconsistencies(context, RunningOptions.DEFAULT).subscribeOn(Schedulers.elastic()).cache();
    task.subscribe();

    barrier.awaitCaller();
    messageIdDAO.insert(MESSAGE_1_WITH_SEEN_FLAG).block();
    barrier.releaseCaller();

    task.block();

    // Verify that no inconsistency is fixed
    assertThat(context.snapshot())
        .isEqualTo(Context.Snapshot.builder()
            .processedImapUidEntries(1)
            .processedMessageIdEntries(1)
            .build());
}
 
Example 16
@Test
public void sameThread() throws Exception {
	final Mono<String> one = Mono.fromCallable(() -> reliable.findBlocking(41));
	final Mono<String> two = Mono.fromCallable(() -> reliable.findBlocking(42));

	log.info("Starting");
	one.subscribe(x -> log.info("Got from one: {}", x));
	log.info("Got first response");
	two.subscribe(x -> log.info("Got from two: {}", x));
	log.info("Got second response");
}
 
Example 17
private <T> void blockingSubscribe(Mono<? super T> publisher) {
	CountDownLatch latch = new CountDownLatch(1);
	publisher.subscribe(System.out::println, t -> {
		if (LOG.isDebugEnabled()) {
			LOG.debug("error subscribing to publisher", t);
		}
		latch.countDown();
	}, latch::countDown);
	try {
		latch.await();
	}
	catch (InterruptedException e) {
		throw new RuntimeException(e);
	}
}
 
Example 18
@Test
public void testRetrieveOrgId() {
	Mono<ListOrganizationsResponse> response1 = subject.retrieveOrgId("dummy");
	response1.subscribe();
	Mockito.verify(this.parentMock, Mockito.times(1)).retrieveOrgId("dummy");
	
	Mono<ListOrganizationsResponse> response2 = subject.retrieveOrgId("dummy");
	response2.subscribe();
	assertThat(response1).isNotEqualTo(response2);
	Mockito.verify(this.parentMock, Mockito.times(2)).retrieveOrgId("dummy");
}
 
Example 19
private Mono<ListOrganizationsResponse> orgCacheLoader(String orgName) {
	Mono<ListOrganizationsResponse> mono = this.parent.retrieveOrgId(orgName).cache();
	
	/*
	 * Note that the mono does not have any subscriber, yet! 
	 * The cache which we are using is working "on-stock", i.e. we need to ensure
	 * that the underlying calls to the CF API really is triggered.
	 * Fortunately, we can do this very easily:
	 */
	mono.subscribe();
	
	/*
	 * Handling for issue #96: If a timeout of the request to the  CF Cloud Controller occurs, 
	 * we must make sure that the erroneous Mono is not kept in the cache. Instead we have to displace the item, 
	 * which triggers a refresh of the cache.
	 * 
	 * Note that subscribe() must be called *before* adding this error handling below.
	 * Otherwise we will run into the situation that the error handling routine is called by this
	 * subscribe() already - but the Mono has not been written into the cache yet!
	 * If we do it in this order, the doOnError method will only be called once the first "real subscriber" 
	 * of the Mono will start requesting.
	 */
	mono = mono.doOnError(e -> {
		if (e instanceof TimeoutException && this.orgCache != null) {
			log.warn(String.format("Timed-out entry using key %s detected, which would get stuck in our org cache; "
					+ "displacing it now to prevent further harm", orgName), e);
			/* 
			 * Note that it *might* happen that a different Mono gets displaced than the one we are in here now. 
			 * Yet, we can't make use of the
			 * 
			 * remove(key, value)
			 * 
			 * method, as providing value would lead to a hen-egg problem (we were required to provide the reference
			 * of the Mono instance, which we are just creating).
			 * Instead, we just blindly remove the entry from the cache. This may lead to four cases to consider:
			 * 
			 * 1. We hit the correct (erroneous) entry: then this is exactly what we want to do.
			 * 2. We hit another erroneous entry: then we have no harm done, because we fixed yet another case.
			 * 3. We hit a healthy entry: Bad luck; on next iteration, we will get a cache miss, which automatically
			 *    fixes the issue (as long this does not happen too often, ...)
			 * 4. The entry has already been deleted by someone else: the remove(key) operation will 
			 *    simply be a NOOP. => no harm done either.
			 */
			
			this.orgCache.remove(orgName);
			
			// Notify metrics of this case
			if (this.internalMetrics != null) {
				this.internalMetrics.countAutoRefreshingCacheMapErroneousEntriesDisplaced(this.orgCache.getName());
			}
		}
	});
	/* Valid for AccessorCacheType = CLASSIC only:
	 * 
	 * Keep in mind that doOnError is a side-effect:  The logic above only removes it from the cache. 
	 * The erroneous instance still is used downstream and will trigger subsequent error handling (including 
	 * logging) there.
	 * Note that this also holds true during the timeframe of the timeout: This instance of the Mono will 
	 * be written to the cache, thus all consumers of the cache will be handed out the cached, not-yet-resolved 
	 * object instance. This implicitly makes sure that there can only be one valid pending request is out there.
	 */
	
	return mono;
}
 
Example 20
private Mono<ListApplicationsResponse> appsInSpaceCacheLoader(CacheKeyAppsInSpace cacheKey) {
	Mono<ListApplicationsResponse> mono = this.parent.retrieveAllApplicationIdsInSpace(cacheKey.getOrgId(), cacheKey.getSpaceId()).cache();
	
	
	/*
	 * Note that the mono does not have any subscriber, yet! 
	 * The cache which we are using is working "on-stock", i.e. we need to ensure
	 * that the underlying calls to the CF API really is triggered.
	 * Fortunately, we can do this very easily:
	 */
	mono.subscribe();
	
	/*
	 * Handling for issue #96: If a timeout of the request to the  CF Cloud Controller occurs, 
	 * we must make sure that the erroneous Mono is not kept in the cache. Instead we have to displace the item, 
	 * which triggers a refresh of the cache.
	 * 
	 * Note that subscribe() must be called *before* adding this error handling below.
	 * Otherwise we will run into the situation that the error handling routine is called by this
	 * subscribe() already - but the Mono has not been written into the cache yet!
	 * If we do it in this order, the doOnError method will only be called once the first "real subscriber" 
	 * of the Mono will start requesting.
	 */
	mono = mono.doOnError(e -> {
		if (e instanceof TimeoutException) {
			log.warn(String.format("Timed-out entry using key %s detected, which would get stuck in our appsInSpace cache; "
					+ "displacing it now to prevent further harm", cacheKey), e);
			/* 
			 * Note that it *might* happen that a different Mono gets displaced than the one we are in here now. 
			 * Yet, we can't make use of the
			 * 
			 * remove(key, value)
			 * 
			 * method, as providing value would lead to a hen-egg problem (we were required to provide the reference
			 * of the Mono instance, which we are just creating).
			 * Instead, we just blindly remove the entry from the cache. This may lead to four cases to consider:
			 * 
			 * 1. We hit the correct (erroneous) entry: then this is exactly what we want to do.
			 * 2. We hit another erroneous entry: then we have no harm done, because we fixed yet another case.
			 * 3. We hit a healthy entry: Bad luck; on next iteration, we will get a cache miss, which automatically
			 *    fixes the issue (as long this does not happen too often, ...)
			 * 4. The entry has already been deleted by someone else: the remove(key) operation will 
			 *    simply be a NOOP. => no harm done either.
			 */
			this.appsInSpaceCache.remove(cacheKey);
			
			// Notify metrics of this case
			if (this.internalMetrics != null) {
				this.internalMetrics.countAutoRefreshingCacheMapErroneousEntriesDisplaced(this.appsInSpaceCache.getName());
			}
		}
	});
	/*
	 * Keep in mind that doOnError is a side-effect:  The logic above only removes it from the cache. 
	 * The erroneous instance still is used downstream and will trigger subsequent error handling (including 
	 * logging) there.
	 * Note that this also holds true during the timeframe of the timeout: This instance of the Mono will 
	 * be written to the cache, thus all consumers of the cache will be handed out the cached, not-yet-resolved 
	 * object instance. This implicitly makes sure that there can only be one valid pending request is out there.
	 */

	return mono;
}