Skip to content

Commit 4e8028c

Browse files
Clarify under what circumstances onError is called
Fixes #433 Signed-off-by: Stuart Douglas <[email protected]>
1 parent fc3f85f commit 4e8028c

File tree

5 files changed

+66
-5
lines changed

5 files changed

+66
-5
lines changed

api/src/main/java/jakarta/servlet/ReadListener.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,19 @@ public interface ReadListener extends EventListener {
4848
public void onAllDataRead() throws IOException;
4949

5050
/**
51-
* Invoked when an error occurs processing the request.
51+
* Invoked when an error occurs reading data. This listener will be invoked if there is a problem with the underlying
52+
* connection while data is being read from the stream. We consider data to be being read when the following conditions
53+
* are met:
54+
*
55+
* <ul>
56+
* <li>{@link ServletInputStream#isReady()} has been invoked and returned false</li>
57+
* <li>{@link ServletInputStream#close()} has not been called</li>
58+
* <li>{@link ServletInputStream#read()} (or any other read method) has not returned {@code -1}</li>
59+
* </ul>
60+
*
61+
* If these conditions are not met and the stream is still open then any failure notification will not be delivered
62+
* until {@link ServletInputStream#isReady()} is invoked. {@code isReady} must return false in this situation, and then
63+
* the failure will be delivered to this method.
5264
*
5365
* @param t the throwable to indicate why the read operation failed
5466
*/

api/src/main/java/jakarta/servlet/ServletInputStream.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,30 @@ public int readLine(byte[] b, int off, int len) throws IOException {
101101
/**
102102
* Returns true if data can be read without blocking else returns false.
103103
*
104+
* If an attempt is made to read from the stream when the stream is in async mode and this method has not returned
105+
* {@code true} the method will throw an {@link IllegalStateException}.
106+
* <p>
107+
* If an error occurs and {@link ReadListener#onError(Throwable)} is invoked then this method will always return false,
108+
* as no further IO operations are allowed after {@code onError} notification.
109+
* <p>
110+
* Note that due to the requirement for {@code read} to never throw in async mode, this method must return false if a
111+
* call to {@code read} would result in an exception.
112+
*
104113
* @return <code>true</code> if data can be obtained without blocking, otherwise returns <code>false</code>.
105114
*
106115
* @since Servlet 3.1
107116
*/
108117
public abstract boolean isReady();
109118

110119
/**
111-
* Instructs the <code>ServletInputStream</code> to invoke the provided {@link ReadListener} when it is possible to read
120+
* Instructs the <code>ServletInputStream</code> to invoke the provided {@link ReadListener} when it is possible to
121+
* read.
122+
* <p>
123+
* Note that after this method has been called methods on this stream that are documented to throw {@link IOException}
124+
* will no longer throw these exceptions directly, instead any exception that occurs will be reported via
125+
* {@link ReadListener#onError(Throwable)}. Please refer to this method for more information. This only applies to
126+
* {@code IOException}, other exception types may still be thrown (e.g. methods can throw {@link IllegalStateException}
127+
* if {@link #isReady()} has not returned true).
112128
*
113129
* @param readListener the {@link ReadListener} that should be notified when it's possible to read.
114130
*

api/src/main/java/jakarta/servlet/ServletOutputStream.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,15 @@ public void println(double d) throws IOException {
273273

274274
/**
275275
* This method can be used to determine if data can be written without blocking.
276+
* <p>
277+
* If an attempt is made to write to the stream when the stream is in async mode and this method has not returned
278+
* {@code true} the method will throw an {@link IllegalStateException}.
279+
* <p>
280+
* If an error occurs and {@link WriteListener#onError(Throwable)} is invoked then this method will always return false,
281+
* as no further IO operations are allowed after {@code onError} notification.
282+
* <p>
283+
* Note that due to the requirement for {@code write} to never throw in async mode, this method must return false if a
284+
* call to {@code write} would result in an exception.
276285
*
277286
* @return <code>true</code> if a write to this <code>ServletOutputStream</code> will succeed, otherwise returns
278287
* <code>false</code>.
@@ -283,8 +292,17 @@ public void println(double d) throws IOException {
283292

284293
/**
285294
* Instructs the <code>ServletOutputStream</code> to invoke the provided {@link WriteListener} when it is possible to
286-
* write
287-
*
295+
* write.
296+
* <p>
297+
* Note that after this method has been called methods on this stream that are documented to throw {@link IOException}
298+
* will no longer throw these exceptions directly, instead any exception that occurs will be reported via
299+
* {@link WriteListener#onError(Throwable)}. Please refer to this method for more information. This only applies to
300+
* {@code IOException}, other exception types may still be thrown (e.g. methods can throw {@link IllegalStateException}
301+
* if {@link #isReady()} has not returned true).
302+
* <p>
303+
* Once this method has been called {@link #flush()} and {@link #close()} become asynchronous operations, they will be
304+
* performed in the background and any problems will be reported through the {@link WriteListener#onError(Throwable)}
305+
* method.
288306
*
289307
* @param writeListener the {@link WriteListener} that should be notified when it's possible to write
290308
*

api/src/main/java/jakarta/servlet/WriteListener.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,19 @@ public interface WriteListener extends EventListener {
3939
public void onWritePossible() throws IOException;
4040

4141
/**
42-
* Invoked when an error occurs writing data using the non-blocking APIs.
42+
* Invoked when an error occurs writing data using the non-blocking APIs. This listener will be invoked if there is a
43+
* problem with the underlying connection while data is being written to the stream. We consider data to be being
44+
* written when any of the following conditions are met:
45+
*
46+
* <ul>
47+
* <li>{@link ServletOutputStream#isReady()} has been invoked and returned false</li>
48+
* <li>{@link ServletOutputStream#close()} has been called, and the failure occurred before the response could be fully
49+
* written to the client</li>
50+
* </ul>
51+
*
52+
* If these conditions are not met and the stream is still open then any failure notification will not be delivered
53+
* until {@link ServletOutputStream#isReady()} is invoked. {@code isReady} must return false in this situation, and then
54+
* the failure will be delivered to the {@link #onError(Throwable)} method.
4355
*
4456
* @param t the throwable to indicate why the write operation failed
4557
*/

spec/src/main/asciidoc/servlet-spec-body.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8546,6 +8546,9 @@ Jakarta Servlet {spec-version} specification developed under the Jakarta EE Work
85468546

85478547
=== Changes Since Jakarta Servlet 5.0
85488548

8549+
link:https://github.com/eclipse-ee4j/servlet-api/issues/433[Issue 433]::
8550+
Clarify how IO errors are handled by async streams.
8551+
85498552
link:https://github.com/eclipse-ee4j/servlet-api/issues/18[Issue 18]::
85508553
Clarify the decoding and normalization of URI paths.
85518554

0 commit comments

Comments
 (0)