/** * Invoke the method for the given exchange. * @param exchange the current exchange * @param bindingContext the binding context to use * @param providedArgs optional list of argument values to match by type * @return a Mono with a {@link HandlerResult}. * @throws ServerErrorException if method argument resolution or method invocation fails */ @Nullable public HandlerResult invokeForHandlerResult(ServerWebExchange exchange, BindingContext bindingContext, Object... providedArgs) { MonoProcessor<HandlerResult> processor = MonoProcessor.create(); this.delegate.invoke(exchange, bindingContext, providedArgs).subscribeWith(processor); if (processor.isTerminated()) { Throwable ex = processor.getError(); if (ex != null) { throw (ex instanceof ServerErrorException ? (ServerErrorException) ex : new ServerErrorException("Failed to invoke: " + getShortLogMessage(), getMethod(), ex)); } return processor.peek(); } else { // Should never happen... throw new IllegalStateException( "SyncInvocableHandlerMethod should have completed synchronously."); } }
try { if (!isPending()) { return peek();
@Test public void MonoProcessorNullFulfill() { MonoProcessor<String> mp = MonoProcessor.create(); mp.onNext(null); assertThat(mp.isTerminated()).isTrue(); assertThat(mp.isSuccess()).isTrue(); assertThat(mp.peek()).isNull(); }
@Test public void MonoProcessorThenFulfill() { MonoProcessor<Integer> mp = MonoProcessor.create(); mp.onNext(1); MonoProcessor<Integer> mp2 = mp.flatMap(s -> Mono.just(s * 2)) .toProcessor(); mp2.subscribe(); assertThat(mp2.isTerminated()).isTrue(); assertThat(mp2.isSuccess()).isTrue(); assertThat(mp2.peek()).isEqualTo(2); }
@Test public void MonoProcessorMapFulfill() { MonoProcessor<Integer> mp = MonoProcessor.create(); mp.onNext(1); MonoProcessor<Integer> mp2 = mp.map(s -> s * 2) .toProcessor(); mp2.subscribe(); assertThat(mp2.isTerminated()).isTrue(); assertThat(mp2.isSuccess()).isTrue(); assertThat(mp2.peek()).isEqualTo(2); }
@Test public void MonoProcessorSuccessChainTogether() { MonoProcessor<String> mp = MonoProcessor.create(); MonoProcessor<String> mp2 = MonoProcessor.create(); mp.subscribe(mp2); mp.onNext("test"); assertThat(mp2.peek()).isEqualToIgnoringCase("test"); assertThat(mp.isSuccess()).isTrue(); assertThat(mp.isError()).isFalse(); }
@Test public void filterMono() { MonoProcessor<Integer> mp = MonoProcessor.create(); StepVerifier.create(Mono.just(2).filter(s -> s % 2 == 0).subscribeWith(mp)) .then(() -> assertThat(mp.isError()).isFalse()) .then(() -> assertThat(mp.isSuccess()).isTrue()) .then(() -> assertThat(mp.peek()).isEqualTo(2)) .then(() -> assertThat(mp.isTerminated()).isTrue()) .expectNext(2) .verifyComplete(); }
@Test public void filterMonoNot() { MonoProcessor<Integer> mp = MonoProcessor.create(); StepVerifier.create(Mono.just(1).filter(s -> s % 2 == 0).subscribeWith(mp)) .then(() -> assertThat(mp.isError()).isFalse()) .then(() -> assertThat(mp.isSuccess()).isTrue()) .then(() -> assertThat(mp.peek()).isNull()) .then(() -> assertThat(mp.isTerminated()).isTrue()) .verifyComplete(); } }
@Test public void whenKnownNumberOfValuesIsReducedOnlyFinalValueMadeAvailable() { // "When a known number of values is being reduced, only the final value is made available" // given: "a composable that will accept 2 values and a reduce function" EmitterProcessor<Integer> source = EmitterProcessor.create(); MonoProcessor<Integer> value = source.reduce(new Reduction()) .subscribeWith(MonoProcessor.create()); // when: "the first value is accepted" source.onNext(1); // then: "the reduced value is unknown" assertThat(value.peek()).isNull(); // when: "the second value is accepted" source.onNext(2); source.onComplete(); // then: "the reduced value is known" assertThat(value.peek()).isEqualTo(2); }
@Test public void zipMonoProcessor2() { MonoProcessor<Integer> mp = MonoProcessor.create(); MonoProcessor<Integer> mp3 = MonoProcessor.create(); StepVerifier.create(Mono.zip(d -> (Integer)d[0], mp) .subscribeWith(mp3)) .then(() -> assertThat(mp3.isPending()).isTrue()) .then(() -> mp.onNext(1)) .then(() -> { assertThat(mp3.isTerminated()).isTrue(); assertThat(mp3.isSuccess()).isTrue(); assertThat(mp3.isPending()).isFalse(); assertThat(mp3.peek()).isEqualTo(1); }) .expectNext(1) .verifyComplete(); }
@Test public void filterMonoProcessor() { MonoProcessor<Integer> mp = MonoProcessor.create(); MonoProcessor<Integer> mp2 = MonoProcessor.create(); StepVerifier.create(mp.filter(s -> s % 2 == 0).subscribeWith(mp2)) .then(() -> mp.onNext(2)) .then(() -> assertThat(mp2.isError()).isFalse()) .then(() -> assertThat(mp2.isSuccess()).isTrue()) .then(() -> assertThat(mp2.peek()).isEqualTo(2)) .then(() -> assertThat(mp2.isTerminated()).isTrue()) .expectNext(2) .verifyComplete(); }
@Test public void filterMonoProcessorNot() { MonoProcessor<Integer> mp = MonoProcessor.create(); MonoProcessor<Integer> mp2 = MonoProcessor.create(); StepVerifier.create(mp.filter(s -> s % 2 == 0).subscribeWith(mp2)) .then(() -> mp.onNext(1)) .then(() -> assertThat(mp2.isError()).isFalse()) .then(() -> assertThat(mp2.isSuccess()).isTrue()) .then(() -> assertThat(mp2.peek()).isNull()) .then(() -> assertThat(mp2.isTerminated()).isTrue()) .verifyComplete(); }
@Test public void zipMonoProcessor() { MonoProcessor<Integer> mp = MonoProcessor.create(); MonoProcessor<Integer> mp2 = MonoProcessor.create(); MonoProcessor<Tuple2<Integer, Integer>> mp3 = MonoProcessor.create(); StepVerifier.create(Mono.zip(mp, mp2) .subscribeWith(mp3)) .then(() -> assertThat(mp3.isPending()).isTrue()) .then(() -> mp.onNext(1)) .then(() -> assertThat(mp3.isPending()).isTrue()) .then(() -> mp2.onNext(2)) .then(() -> { assertThat(mp3.isTerminated()).isTrue(); assertThat(mp3.isSuccess()).isTrue(); assertThat(mp3.isPending()).isFalse(); assertThat(mp3.peek() .getT1()).isEqualTo(1); assertThat(mp3.peek() .getT2()).isEqualTo(2); }) .expectNextMatches(t -> t.getT1() == 1 && t.getT2() == 2) .verifyComplete(); }
@Test public void whenUnknownNumberOfValuesReducedEachReductionPassedToConsumerOnWindow() { // "When an unknown number of values is being reduced, each reduction is passed to a consumer on window" // given: "a composable with a reduce function" FluxProcessor<Integer, Integer> source = EmitterProcessor.create(); Flux<Integer> reduced = source.window(2) .log() .flatMap(it -> it.log("lol") .reduce(new Reduction())); MonoProcessor<Integer> value = reduced.subscribeWith(MonoProcessor.create()); // when: "the first value is accepted" source.onNext(1); // then: "the reduction is not available" assertThat(value.peek()).isNull(); // when: "the second value is accepted and flushed" source.onNext(2); // then: "the updated reduction is available" assertThat(value.peek()).isEqualTo(2); }
@Test public void streamCanBeCounted() { // "Stream can be counted" // given: "source composables to count and tap" EmitterProcessor<Integer> source = EmitterProcessor.create(); MonoProcessor<Long> tap = source.count() .subscribeWith(MonoProcessor.create()); // when: "the sources accept a value" source.onNext(1); source.onNext(2); source.onNext(3); source.onComplete(); // then: "the count value matches the number of accept" assertThat(tap.peek()).isEqualTo(3); }
@Test public void knownNumberOfValuesCanBeReduced() { // "A known number of values can be reduced" // given: "a composable that will accept 5 values and a reduce function" EmitterProcessor<Integer> source = EmitterProcessor.create(); Mono<Integer> reduced = source.reduce(new Reduction()); MonoProcessor<Integer> value = reduced.subscribeWith(MonoProcessor.create()); // when: "the expected number of values is accepted" source.onNext(1); source.onNext(2); source.onNext(3); source.onNext(4); source.onNext(5); source.onComplete(); // then: "the reduced composable holds the reduced value" assertThat(value.peek()).isEqualTo(120); }
@Nullable public O peek() { return processor.peek(); }
private MultiValueMap<String, String> getRequestParams(ServerWebExchange exchange) { MultiValueMap<String, String> params = exchange.getRequestParams().subscribe().peek(); Assert.notNull(params, "Expected form data (if any) to be parsed."); return params; }
private MultiValueMap<String, String> getRequestParams(ServerWebExchange exchange) { MultiValueMap<String, String> params = exchange.getRequestParams().subscribe().peek(); Assert.notNull(params, "Expected form data (if any) to be parsed."); return params; } }
private MultiValueMap<String, String> getRequestParams(ServerWebExchange exchange) { MultiValueMap<String, String> params = exchange.getRequestParams().subscribe().peek(); Assert.notNull(params, "Expected form data (if any) to be parsed."); return params; }