From 631dcd58daf5c9a3d4ba99fdea743ca9f2b0c862 Mon Sep 17 00:00:00 2001 From: Mark Thomas Date: Mon, 16 Jan 2023 16:11:33 +0000 Subject: [PATCH] Fix #273 - clarify behaviour around non-blocking writes --- api/src/main/java/jakarta/servlet/AsyncContext.java | 11 +++++++++-- .../java/jakarta/servlet/ServletOutputStream.java | 10 +++++----- spec/src/main/asciidoc/servlet-spec-body.adoc | 8 +++++++- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/jakarta/servlet/AsyncContext.java b/api/src/main/java/jakarta/servlet/AsyncContext.java index 2f9620040..b24012a82 100644 --- a/api/src/main/java/jakarta/servlet/AsyncContext.java +++ b/api/src/main/java/jakarta/servlet/AsyncContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020 Oracle and/or its affiliates and others. + * Copyright (c) 2017, 2023 Oracle and/or its affiliates and others. * All rights reserved. * * This program and the accompanying materials are made available under the @@ -156,7 +156,9 @@ public interface AsyncContext { * This method returns immediately after passing the request and response objects to a container managed thread, on * which the dispatch operation will be performed. If this method is called before the container-initiated dispatch that * called startAsync has returned to the container, the dispatch operation will be delayed until after the - * container-initiated dispatch has returned to the container. + * container-initiated dispatch has returned to the container. If the output stream is in non-blocking mode when this + * method is called, the output stream will be closed as described by {@code ServletOutputStream#close} and the dispatch + * operation will be delayed until after the non-blocking write has completed. * *

* The dispatcher type of the request is set to DispatcherType.ASYNC. Unlike @@ -277,6 +279,11 @@ public interface AsyncContext { * startAsync has returned to the container, then the call will not take effect (and any invocations of * {@link AsyncListener#onComplete(AsyncEvent)} will be delayed) until after the container-initiated dispatch has * returned to the container. + * + *

+ * If the output stream is in non-blocking mode when this method is called, the output stream will be closed as + * described by {@code ServletOutputStream#close} and this call to complete will not take effect (and any invocations of + * {@link AsyncListener#onComplete(AsyncEvent)} will be delayed) until after the non-blocking write has completed. */ public void complete(); diff --git a/api/src/main/java/jakarta/servlet/ServletOutputStream.java b/api/src/main/java/jakarta/servlet/ServletOutputStream.java index 0068c7f4a..22f31f4a9 100644 --- a/api/src/main/java/jakarta/servlet/ServletOutputStream.java +++ b/api/src/main/java/jakarta/servlet/ServletOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022 Oracle and/or its affiliates and others. + * Copyright (c) 1997, 2023 Oracle and/or its affiliates and others. * All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -325,10 +325,10 @@ public void println(double d) throws IOException { } /** - * Returns {@code true} if it is allowable to call any method that may write data (e.g. {@code write()}, {@code print()} - * or {@code flush}). In blocking mode, this method will always return {@code true}, but a subsequent call to a method - * that writes data may block. In non-blocking mode this method may return {@code false}, in which case it is illegal to - * call a method that writes data and an {@link IllegalStateException} MUST be thrown. When + * Returns {@code true} if it is allowable to call any method that may write data (i.e. {@code write()}, {@code print()} + * {@code println()} or {@code flush}). In blocking mode, this method will always return {@code true}, but a subsequent + * call to a method that writes data may block. In non-blocking mode this method may return {@code false}, in which case + * it is illegal to call a method that writes data and an {@link IllegalStateException} MUST be thrown. When * {@link WriteListener#onWritePossible()} is called, a call to this method that returned {@code true} is implicit. *

* If this method returns {@code false} and a {@link WriteListener} has been set via diff --git a/spec/src/main/asciidoc/servlet-spec-body.adoc b/spec/src/main/asciidoc/servlet-spec-body.adoc index b745fae74..c2732fa33 100644 --- a/spec/src/main/asciidoc/servlet-spec-body.adoc +++ b/spec/src/main/asciidoc/servlet-spec-body.adoc @@ -2482,7 +2482,7 @@ This method returns `true` if a write to the `ServletOutputStream` will succeed, otherwise it will return `false`. If this method returns `true`, a write operation can be performed on the `ServletOutputStream`. If no further -data can be written to the `ServletOutputStream`. then this method will +data can be written to the `ServletOutputStream` then this method will return `false` till the underlying data is flushed at which point the container will invoke the `onWritePossible` method of the `WriteListener.` A subsequent call to this method will return `true`. @@ -8557,6 +8557,12 @@ link:https://github.com/eclipse-ee4j/servlet-api/issues/164[Issue 164]:: Clarify Javadoc for `ServletResponse` and `HttpServletResponse` methods that are NO-OPs once the response has been committed. +link:https://github.com/eclipse-ee4j/servlet-api/issues/273[Issue 273]:: +Clarify the meaning of "write operation" in the Javadoc for +`ServletOutputStream.isReady()` and, in particular, that this does not include +`ServletOutputStream.close()`, `AsyncContext.complete()` nor any of the +`AsyncContext.dispatch()` methods. + link:https://github.com/eclipse-ee4j/servlet-api/issues/275[Issue 275]:: Containers may provide an option to send redirects using a location header with a relative URL.