/** * Indicates whether this {@code MonoProcessor} has been completed with an error. * * @return {@code true} if this {@code MonoProcessor} was completed with an error, {@code false} otherwise. */ public final boolean isError() { return getError() != null; }
/** * 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."); } }
@Test public void MonoProcessorRejectedChainTogether() { MonoProcessor<String> mp = MonoProcessor.create(); MonoProcessor<String> mp2 = MonoProcessor.create(); mp.subscribe(mp2); mp.onError(new Exception("test")); assertThat(mp2.getError()).hasMessage("test"); assertThat(mp.isSuccess()).isFalse(); assertThat(mp.isError()).isTrue(); }
@Test public void onMonoRejectedDoOnErrorClazzNot() { Mono<String> mp = Mono.error(new TestException()); AtomicReference<Throwable> ref = new AtomicReference<>(); MonoProcessor<String> processor = mp.doOnError(RuntimeException.class, ref::set) .toProcessor(); processor.subscribe(); assertThat(processor.getError()).isInstanceOf(TestException.class); assertThat(ref.get()).isNull(); }
@Test public void zipMonoProcessorRejected() { 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.onError(new Exception("test"))) .then(() -> { assertThat(mp3.isTerminated()).isTrue(); assertThat(mp3.isSuccess()).isFalse(); assertThat(mp3.isPending()).isFalse(); assertThat(mp3.getError()).hasMessage("test"); }) .verifyErrorMessage("test"); }
@Test public void MonoProcessorMapError() { MonoProcessor<Integer> mp = MonoProcessor.create(); mp.onNext(1); MonoProcessor<Integer> mp2 = MonoProcessor.create(); StepVerifier.create(mp.<Integer>map(s -> { throw new RuntimeException("test"); }).subscribeWith(mp2), 0) .thenRequest(1) .then(() -> { assertThat(mp2.isTerminated()).isTrue(); assertThat(mp2.isSuccess()).isFalse(); assertThat(mp2.getError()).hasMessage("test"); }) .verifyErrorMessage("test"); }
@Test public void filterMonoProcessorError() { MonoProcessor<Integer> mp = MonoProcessor.create(); MonoProcessor<Integer> mp2 = MonoProcessor.create(); StepVerifier.create(mp.filter(s -> {throw new RuntimeException("test"); }) .subscribeWith (mp2)) .then(() -> mp.onNext(2)) .then(() -> assertThat(mp2.isError()).isTrue()) .then(() -> assertThat(mp2.isSuccess()).isFalse()) .then(() -> assertThat(mp2.getError()).hasMessage("test")) .then(() -> assertThat(mp2.isTerminated()).isTrue()) .verifyErrorMessage("test"); }
@Test public void doOnSuccessMonoProcessorError() { MonoProcessor<Integer> mp = MonoProcessor.create(); MonoProcessor<Integer> mp2 = MonoProcessor.create(); AtomicReference<Throwable> ref = new AtomicReference<>(); StepVerifier.create(mp.doOnSuccess(s -> {throw new RuntimeException("test"); }) .doOnError(ref::set) .subscribeWith (mp2)) .then(() -> mp.onNext(2)) .then(() -> assertThat(mp2.isError()).isTrue()) .then(() -> assertThat(ref.get()).hasMessage("test")) .then(() -> assertThat(mp2.isSuccess()).isFalse()) .then(() -> assertThat(mp2.getError()).hasMessage("test")) .then(() -> assertThat(mp2.isTerminated()).isTrue()) .verifyErrorMessage("test"); }
@Test public void promiseErrorCountCannotExceedOne() { MonoProcessor<Object> deferred = MonoProcessor.create(); Throwable error = new IOException("foo"); StepVerifier.create(deferred) .then(() -> { deferred.onError(error); deferred.onNext(error); }) .expectErrorMessage("foo") .verifyThenAssertThat() .hasDroppedExactly(error); Assertions.assertThat(deferred.getError()).isSameAs(error); }
@Test public void promiseAcceptCountAndErrorCountCannotExceedOneInTotal() { MonoProcessor<Object> deferred = MonoProcessor.create(); Throwable error = new IOException("foo"); StepVerifier.create(deferred) .then(() -> { deferred.onError(error); deferred.onNext("alpha"); }) .expectErrorMessage("foo") .verifyThenAssertThat() .hasDroppedExactly("alpha"); Assertions.assertThat(deferred.getError()).isSameAs(error); }
@Nullable public Throwable getError() { return processor.getError(); }
/** * Indicates whether this {@code MonoProcessor} has been completed with an error. * * @return {@code true} if this {@code MonoProcessor} was completed with an error, {@code false} otherwise. */ public final boolean isError() { return getError() != null; }
@Nullable public Throwable getError() { return processor.getError(); }