From 7e9437738272a31e1d764972291de42936194ab1 Mon Sep 17 00:00:00 2001 From: Violeta Georgieva Date: Thu, 29 Sep 2016 21:04:27 +0300 Subject: [PATCH] Handle async operation events Problem: The following exception is observed on an async timeout: "java.lang.IllegalStateException: It is invalid to call isReady() when the response has not been put into non-blocking mode" Current Implementation: The async operation events sent by the web container are not propagated to the internal implementation. When timeout/error happens and if the application does not complete the async operation, the web container will complete it. At that point if the application tries to read/write, the operation will fail with an exception (above) that there is not async operation started. Proposed Solution: On async timeout or error, make calls to: - AbstractRequestBodyPublisher.onError, - AbstractResponseBodyProcessor.onError, - AbstractResponseBodyFlushProcessor.onError As a result of these calls the async operation will be completed and no more invocations of read/write will be made. --- .../AbstractResponseBodyFlushProcessor.java | 2 +- .../reactive/ServletHttpHandlerAdapter.java | 39 +++++++++++++++++++ .../reactive/ServletServerHttpRequest.java | 6 +++ .../reactive/ServletServerHttpResponse.java | 17 +++++++- 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractResponseBodyFlushProcessor.java b/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractResponseBodyFlushProcessor.java index fdfc577ef8..57510a9c09 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractResponseBodyFlushProcessor.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractResponseBodyFlushProcessor.java @@ -120,7 +120,7 @@ abstract class AbstractResponseBodyFlushProcessor implements Processor, Void> createBodyFlushProcessor() { - Processor, Void> processor = new ResponseBodyFlushProcessor(); + ResponseBodyFlushProcessor processor = new ResponseBodyFlushProcessor(); registerListener(); + bodyFlushProcessor = processor; return processor; } @@ -152,6 +155,18 @@ public class ServletServerHttpResponse extends AbstractListenerServerHttpRespons } + void onError(Throwable t) { + if (bodyFlushProcessor != null) { + bodyFlushProcessor.cancel(); + bodyFlushProcessor.onError(t); + } + if (bodyProcessor != null) { + bodyProcessor.cancel(); + bodyProcessor.onError(t); + } + } + + private class ResponseBodyProcessor extends AbstractResponseBodyProcessor { private final ServletOutputStream outputStream;