From 68b4f42e7a00fd2c47ca1c9a84353ddf9c799373 Mon Sep 17 00:00:00 2001 From: deadEternally Date: Sat, 1 Feb 2025 21:33:20 +0530 Subject: [PATCH 1/4] Changes --- stub/src/main/java/io/grpc/stub/ClientCalls.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/stub/src/main/java/io/grpc/stub/ClientCalls.java b/stub/src/main/java/io/grpc/stub/ClientCalls.java index 13fb00d3b3e..8f83670558d 100644 --- a/stub/src/main/java/io/grpc/stub/ClientCalls.java +++ b/stub/src/main/java/io/grpc/stub/ClientCalls.java @@ -100,6 +100,12 @@ public static void asyncServerStreamingCall( * {@code beforeStart()} will be called. * * @return request stream observer. It will extend {@link ClientCallStreamObserver} + * onError called on the request stream observer will result in stream cancellation. The response + * {@link StreamObserver} will be immediately notified of the cancellation with a + * {@link io.grpc.StatusRuntimeException}. The server's request stream observer will receive an + * onError callbackk from the gRPC server framework with a {@link io.grpc.StatusRuntimeException} + * for the cancellation. The actual exception passed by the client to onError is never actually + * transmitted to the server. */ public static StreamObserver asyncClientStreamingCall( ClientCall call, @@ -116,6 +122,12 @@ public static StreamObserver asyncClientStreamingCall( * {@code beforeStart()} will be called. * * @return request stream observer. It will extend {@link ClientCallStreamObserver} + * onError called on the request stream observer will result in stream cancellation. The response + * {@link StreamObserver} will be immediately notified of the cancellation with a + * {@link io.grpc.StatusRuntimeException}. The server's request stream observer will receive an + * onError callbackk from the gRPC server framework with a {@link io.grpc.StatusRuntimeException} + * for the cancellation. The actual exception passed by the client to onError is never actually + * transmitted to the server. */ public static StreamObserver asyncBidiStreamingCall( ClientCall call, StreamObserver responseObserver) { From 916e8487175bbadc8ff6d01dc55df1a769912a23 Mon Sep 17 00:00:00 2001 From: deadEternally Date: Tue, 4 Feb 2025 14:08:29 +0530 Subject: [PATCH 2/4] Documenting error transmission and callback behavior. --- .../main/java/io/grpc/stub/ClientCalls.java | 52 ++++++++++++++--- .../main/java/io/grpc/stub/ServerCalls.java | 58 +++++++++++++++++++ 2 files changed, 102 insertions(+), 8 deletions(-) diff --git a/stub/src/main/java/io/grpc/stub/ClientCalls.java b/stub/src/main/java/io/grpc/stub/ClientCalls.java index 8f83670558d..194e37acd7a 100644 --- a/stub/src/main/java/io/grpc/stub/ClientCalls.java +++ b/stub/src/main/java/io/grpc/stub/ClientCalls.java @@ -70,6 +70,13 @@ private ClientCalls() {} * *

If the provided {@code responseObserver} is an instance of {@link ClientResponseObserver}, * {@code beforeStart()} will be called. + * + *

Server errors

+ * If the throwable sent to the server's outbound {@link StreamObserver}'s onError + * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be + * received by the {@link ClientCall}'s onClose, and UNKNOWN status code otherwise. Its + * description will be encoded to the stream trailer, but the cause (which may contain server + * application's information) will not. */ public static void asyncUnaryCall( ClientCall call, ReqT req, StreamObserver responseObserver) { @@ -84,6 +91,13 @@ public static void asyncUnaryCall( * *

If the provided {@code responseObserver} is an instance of {@link ClientResponseObserver}, * {@code beforeStart()} will be called. + * + *

Server errors

+ * If the throwable sent to the server's outbound {@link StreamObserver}'s onError + * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be + * received by the {@link ClientCall}'s onClose, and UNKNOWN status code otherwise. Its + * description will be encoded to the stream trailer, but the cause (which may contain server + * application's information) will not. */ public static void asyncServerStreamingCall( ClientCall call, ReqT req, StreamObserver responseObserver) { @@ -100,12 +114,23 @@ public static void asyncServerStreamingCall( * {@code beforeStart()} will be called. * * @return request stream observer. It will extend {@link ClientCallStreamObserver} + * + *

Client errors

* onError called on the request stream observer will result in stream cancellation. The response * {@link StreamObserver} will be immediately notified of the cancellation with a - * {@link io.grpc.StatusRuntimeException}. The server's request stream observer will receive an - * onError callbackk from the gRPC server framework with a {@link io.grpc.StatusRuntimeException} - * for the cancellation. The actual exception passed by the client to onError is never actually - * transmitted to the server. + * {@link io.grpc.StatusRuntimeException} with the exception passed to onError set as the cause + * and the stream is considered closed. The server's request stream observer will receive an + * onError callback with a {@link io.grpc.StatusRuntimeException} for the cancellation with the + * message 'Client cancelled', and exception cause set to null because the actual exception + * passed by the client to onError is never actually transmitted to the server and the server + * just receives a RST_STREAM frame indicating cancellation by the client. + * + *

Server errors

+ * If the throwable sent to the server's outbound {@link StreamObserver}'s onError + * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be + * received by the {@link ClientCall}'s onClose, and UNKNOWN status code otherwise. Its + * description will be encoded to the stream trailer, but the cause (which may contain server + * application's information) will not. */ public static StreamObserver asyncClientStreamingCall( ClientCall call, @@ -122,12 +147,23 @@ public static StreamObserver asyncClientStreamingCall( * {@code beforeStart()} will be called. * * @return request stream observer. It will extend {@link ClientCallStreamObserver} + * + *

Client errors

* onError called on the request stream observer will result in stream cancellation. The response * {@link StreamObserver} will be immediately notified of the cancellation with a - * {@link io.grpc.StatusRuntimeException}. The server's request stream observer will receive an - * onError callbackk from the gRPC server framework with a {@link io.grpc.StatusRuntimeException} - * for the cancellation. The actual exception passed by the client to onError is never actually - * transmitted to the server. + * {@link io.grpc.StatusRuntimeException} with the exception passed to onError set as the cause + * and the stream is considered closed. The server's request stream observer will receive an + * onError callback with a {@link io.grpc.StatusRuntimeException} for the cancellation with the + * message 'Client cancelled', and exception cause set to null because the actual exception + * passed by the client to onError is never actually transmitted to the server and the server + * just receives a RST_STREAM frame indicating cancellation by the client. + * + *

Server errors

+ * If the throwable sent to the server's outbound {@link StreamObserver}'s onError + * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be + * received by the {@link ClientCall}'s onClose, and UNKNOWN status code otherwise. Its + * description will be encoded to the stream trailer, but the cause (which may contain server + * application's information) will not. */ public static StreamObserver asyncBidiStreamingCall( ClientCall call, StreamObserver responseObserver) { diff --git a/stub/src/main/java/io/grpc/stub/ServerCalls.java b/stub/src/main/java/io/grpc/stub/ServerCalls.java index 7990a5b34c0..b16bc396a04 100644 --- a/stub/src/main/java/io/grpc/stub/ServerCalls.java +++ b/stub/src/main/java/io/grpc/stub/ServerCalls.java @@ -26,6 +26,8 @@ import io.grpc.ServerCall; import io.grpc.ServerCallHandler; import io.grpc.Status; +import io.grpc.StatusException; +import io.grpc.StatusRuntimeException; /** * Utility functions for adapting {@link ServerCallHandler}s to application service implementation, @@ -45,6 +47,14 @@ private ServerCalls() { * Creates a {@link ServerCallHandler} for a unary call method of the service. * * @param method an adaptor to the actual method on the service implementation. + *

+ *

Server errors

+ * If the throwable sent to the server's outbound {@link StreamObserver}'s onError + * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be sent + * and UNKNOWN status code otherwise. Its description will be encoded to the stream trailer, but + * the cause (which may contain server application's information) will not. After the stream + * trailer with END_STREAM is sent, the server side call is considered to be closed. + *

*/ public static ServerCallHandler asyncUnaryCall( UnaryMethod method) { @@ -55,6 +65,22 @@ public static ServerCallHandler asyncUnaryCall( * Creates a {@link ServerCallHandler} for a server streaming method of the service. * * @param method an adaptor to the actual method on the service implementation. + *

+ *

Client errors

+ * The server's request stream observer will receive an + * onError callback with a {@link io.grpc.StatusRuntimeException} for the cancellation with the + * message 'Client cancelled', and exception cause set to null because the actual exception + * passed by the client to onError is never actually transmitted to the server and the server just + * receives a RST_STREAM frame indicating cancellation by the client. + *

+ *

+ *

Server errors

+ * If the throwable sent to the server's outbound {@link StreamObserver}'s onError + * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be sent + * and UNKNOWN status code otherwise. Its description will be encoded to the stream trailer, but + * the cause (which may contain server application's information) will not. After the stream + * trailer with END_STREAM is sent, the server side call is considered to be closed. + *

*/ public static ServerCallHandler asyncServerStreamingCall( ServerStreamingMethod method) { @@ -65,6 +91,22 @@ public static ServerCallHandler asyncServerStreamingC * Creates a {@link ServerCallHandler} for a client streaming method of the service. * * @param method an adaptor to the actual method on the service implementation. + *

+ *

Client errors

+ * The server's request stream observer will receive an + * onError callback with a {@link io.grpc.StatusRuntimeException} for the cancellation with the + * message 'Client cancelled', and exception cause set to null because the actual exception + * passed by the client to onError is never actually transmitted to the server and the server just + * receives a RST_STREAM frame indicating cancellation by the client. + *

+ *

+ *

Server errors

+ * If the throwable sent to the server's outbound {@link StreamObserver}'s onError + * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be sent + * and UNKNOWN status code otherwise. Its description will be encoded to the stream trailer, but + * the cause (which may contain server application's information) will not. After the stream + * trailer with END_STREAM is sent, the server side call is considered to be closed. + *

*/ public static ServerCallHandler asyncClientStreamingCall( ClientStreamingMethod method) { @@ -75,6 +117,22 @@ public static ServerCallHandler asyncClientStreamingC * Creates a {@link ServerCallHandler} for a bidi streaming method of the service. * * @param method an adaptor to the actual method on the service implementation. + *

+ *

Client errors

+ * The server's request stream observer will receive an + * onError callback with a {@link io.grpc.StatusRuntimeException} for the cancellation with the + * message 'Client cancelled', and exception cause set to null because the actual exception + * passed by the client to onError is never actually transmitted to the server and the server just + * receives a RST_STREAM frame indicating cancellation by the client. + *

+ *

+ *

Server errors

+ * If the throwable sent to the server's outbound {@link StreamObserver}'s onError + * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be sent + * and UNKNOWN status code otherwise. Its description will be encoded to the stream trailer, but + * the cause (which may contain server application's information) will not. After the stream + * trailer with END_STREAM is sent, the server side call is considered to be closed. + *

*/ public static ServerCallHandler asyncBidiStreamingCall( BidiStreamingMethod method) { From f8b457a5b5f42fd345636fd79c69ce6b9c4d2300 Mon Sep 17 00:00:00 2001 From: Kannan J Date: Thu, 27 Aug 2026 12:24:28 +0000 Subject: [PATCH 3/4] Address review comments. --- .../main/java/io/grpc/stub/ClientCalls.java | 87 ++++++++----- .../main/java/io/grpc/stub/ServerCalls.java | 122 +++++++++--------- 2 files changed, 119 insertions(+), 90 deletions(-) diff --git a/stub/src/main/java/io/grpc/stub/ClientCalls.java b/stub/src/main/java/io/grpc/stub/ClientCalls.java index 194e37acd7a..f502a82b7c8 100644 --- a/stub/src/main/java/io/grpc/stub/ClientCalls.java +++ b/stub/src/main/java/io/grpc/stub/ClientCalls.java @@ -72,11 +72,10 @@ private ClientCalls() {} * {@code beforeStart()} will be called. * *

Server errors

- * If the throwable sent to the server's outbound {@link StreamObserver}'s onError - * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be - * received by the {@link ClientCall}'s onClose, and UNKNOWN status code otherwise. Its - * description will be encoded to the stream trailer, but the cause (which may contain server - * application's information) will not. + * If the server completes the RPC with status code OK, then {@code + * responseObserver.onCompleted()} is called at the end of the RPC. Otherwise the status and + * trailers are passed as a Throwable to {@code onError()} and can be accessed with {@link + * Status#fromThrowable} and {@link Status#trailersFromThrowable}. */ public static void asyncUnaryCall( ClientCall call, ReqT req, StreamObserver responseObserver) { @@ -93,11 +92,10 @@ public static void asyncUnaryCall( * {@code beforeStart()} will be called. * *

Server errors

- * If the throwable sent to the server's outbound {@link StreamObserver}'s onError - * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be - * received by the {@link ClientCall}'s onClose, and UNKNOWN status code otherwise. Its - * description will be encoded to the stream trailer, but the cause (which may contain server - * application's information) will not. + * If the server completes the RPC with status code OK, then {@code + * responseObserver.onCompleted()} is called at the end of the RPC. Otherwise the status and + * trailers are passed as a Throwable to {@code onError()} and can be accessed with {@link + * Status#fromThrowable} and {@link Status#trailersFromThrowable}. */ public static void asyncServerStreamingCall( ClientCall call, ReqT req, StreamObserver responseObserver) { @@ -113,24 +111,26 @@ public static void asyncServerStreamingCall( *

If the provided {@code responseObserver} is an instance of {@link ClientResponseObserver}, * {@code beforeStart()} will be called. * - * @return request stream observer. It will extend {@link ClientCallStreamObserver} - * *

Client errors

- * onError called on the request stream observer will result in stream cancellation. The response + * {@link StreamObserver#onError} called on the request stream observer will result in stream + * cancellation. The response * {@link StreamObserver} will be immediately notified of the cancellation with a * {@link io.grpc.StatusRuntimeException} with the exception passed to onError set as the cause * and the stream is considered closed. The server's request stream observer will receive an - * onError callback with a {@link io.grpc.StatusRuntimeException} for the cancellation with the - * message 'Client cancelled', and exception cause set to null because the actual exception + * {@link StreamObserver#onError} callback with a throwable which when converted to a status + * with + * Status.fromThrowable(), always has the status code CANCELLED and exception cause set to + * null because the actual exception * passed by the client to onError is never actually transmitted to the server and the server * just receives a RST_STREAM frame indicating cancellation by the client. * *

Server errors

- * If the throwable sent to the server's outbound {@link StreamObserver}'s onError - * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be - * received by the {@link ClientCall}'s onClose, and UNKNOWN status code otherwise. Its - * description will be encoded to the stream trailer, but the cause (which may contain server - * application's information) will not. + * If the server completes the RPC with status code OK, then {@code + * responseObserver.onCompleted()} is called at the end of the RPC. Otherwise the status and + * trailers are passed as a Throwable to {@code onError()} and can be accessed with {@link + * Status#fromThrowable} and {@link Status#trailersFromThrowable}. + * + * @return request stream observer. It will extend {@link ClientCallStreamObserver} */ public static StreamObserver asyncClientStreamingCall( ClientCall call, @@ -146,24 +146,26 @@ public static StreamObserver asyncClientStreamingCall( *

If the provided {@code responseObserver} is an instance of {@link ClientResponseObserver}, * {@code beforeStart()} will be called. * - * @return request stream observer. It will extend {@link ClientCallStreamObserver} - * *

Client errors

- * onError called on the request stream observer will result in stream cancellation. The response + * {@link StreamObserver#onError} called on the request stream observer will result in stream + * cancellation. The response * {@link StreamObserver} will be immediately notified of the cancellation with a * {@link io.grpc.StatusRuntimeException} with the exception passed to onError set as the cause * and the stream is considered closed. The server's request stream observer will receive an - * onError callback with a {@link io.grpc.StatusRuntimeException} for the cancellation with the - * message 'Client cancelled', and exception cause set to null because the actual exception + * {@link StreamObserver#onError} callback with a throwable which when converted to a status + * with + * Status.fromThrowable(), always has the status code CANCELLED and exception cause set to + * null because the actual exception * passed by the client to onError is never actually transmitted to the server and the server * just receives a RST_STREAM frame indicating cancellation by the client. * *

Server errors

- * If the throwable sent to the server's outbound {@link StreamObserver}'s onError - * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be - * received by the {@link ClientCall}'s onClose, and UNKNOWN status code otherwise. Its - * description will be encoded to the stream trailer, but the cause (which may contain server - * application's information) will not. + * If the server completes the RPC with status code OK, then {@code + * responseObserver.onCompleted()} is called at the end of the RPC. Otherwise the status and + * trailers are passed as a Throwable to {@code onError()} and can be accessed with {@link + * Status#fromThrowable} and {@link Status#trailersFromThrowable}. + * + * @return request stream observer. It will extend {@link ClientCallStreamObserver} */ public static StreamObserver asyncBidiStreamingCall( ClientCall call, StreamObserver responseObserver) { @@ -175,6 +177,10 @@ public static StreamObserver asyncBidiStreamingCall( * Executes a unary call and blocks on the response. The {@code call} should not be already * started. After calling this method, {@code call} should no longer be used. * + *

Server errors

+ * If the server completes the RPC with a non-OK status, a {@link StatusRuntimeException} + * is thrown. The status code and trailers can be accessed from the exception. + * * @return the single response message. * @throws StatusRuntimeException on error */ @@ -190,6 +196,10 @@ public static RespT blockingUnaryCall(ClientCall call * Executes a unary call and blocks on the response. The {@code call} should not be already * started. After calling this method, {@code call} should no longer be used. * + *

Server errors

+ * If the server completes the RPC with a non-OK status, a {@link StatusRuntimeException} + * is thrown. The status code and trailers can be accessed from the exception. + * * @return the single response message. * @throws StatusRuntimeException on error */ @@ -228,7 +238,11 @@ public static RespT blockingUnaryCall( * response stream. The {@code call} should not be already started. After calling this method, * {@code call} should no longer be used. * - *

The returned iterator may throw {@link StatusRuntimeException} on error. + *

Server errors

+ * If the server completes the RPC with a non-OK status, the returned iterator will throw + * a {@link StatusRuntimeException} when attempting to read the error response (e.g. in + * {@link Iterator#hasNext} or {@link Iterator#next}). The status code and trailers can be + * accessed from the exception. * * @return an iterator over the response stream. */ @@ -245,7 +259,11 @@ public static Iterator blockingServerStreamingCall( * response stream. The {@code call} should not be already started. After calling this method, * {@code call} should no longer be used. * - *

The returned iterator may throw {@link StatusRuntimeException} on error. + *

Server errors

+ * If the server completes the RPC with a non-OK status, the returned iterator will throw + * a {@link StatusRuntimeException} when attempting to read the error response (e.g. in + * {@link Iterator#hasNext} or {@link Iterator#next}). The status code and trailers can be + * accessed from the exception. * * @return an iterator over the response stream. */ @@ -264,6 +282,11 @@ public static Iterator blockingServerStreamingCall( * {@code call} should not be already started. After calling this method, {@code call} should no * longer be used. * + *

Server errors

+ * If the server completes the RPC with a non-OK status, the returned future will fail with + * a {@link StatusRuntimeException}. The status code and trailers can be accessed from the + * exception. + * * @return a future for the single response message. */ public static ListenableFuture futureUnaryCall( diff --git a/stub/src/main/java/io/grpc/stub/ServerCalls.java b/stub/src/main/java/io/grpc/stub/ServerCalls.java index b16bc396a04..30af95af921 100644 --- a/stub/src/main/java/io/grpc/stub/ServerCalls.java +++ b/stub/src/main/java/io/grpc/stub/ServerCalls.java @@ -26,8 +26,6 @@ import io.grpc.ServerCall; import io.grpc.ServerCallHandler; import io.grpc.Status; -import io.grpc.StatusException; -import io.grpc.StatusRuntimeException; /** * Utility functions for adapting {@link ServerCallHandler}s to application service implementation, @@ -47,14 +45,6 @@ private ServerCalls() { * Creates a {@link ServerCallHandler} for a unary call method of the service. * * @param method an adaptor to the actual method on the service implementation. - *

- *

Server errors

- * If the throwable sent to the server's outbound {@link StreamObserver}'s onError - * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be sent - * and UNKNOWN status code otherwise. Its description will be encoded to the stream trailer, but - * the cause (which may contain server application's information) will not. After the stream - * trailer with END_STREAM is sent, the server side call is considered to be closed. - *

*/ public static ServerCallHandler asyncUnaryCall( UnaryMethod method) { @@ -65,22 +55,6 @@ public static ServerCallHandler asyncUnaryCall( * Creates a {@link ServerCallHandler} for a server streaming method of the service. * * @param method an adaptor to the actual method on the service implementation. - *

- *

Client errors

- * The server's request stream observer will receive an - * onError callback with a {@link io.grpc.StatusRuntimeException} for the cancellation with the - * message 'Client cancelled', and exception cause set to null because the actual exception - * passed by the client to onError is never actually transmitted to the server and the server just - * receives a RST_STREAM frame indicating cancellation by the client. - *

- *

- *

Server errors

- * If the throwable sent to the server's outbound {@link StreamObserver}'s onError - * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be sent - * and UNKNOWN status code otherwise. Its description will be encoded to the stream trailer, but - * the cause (which may contain server application's information) will not. After the stream - * trailer with END_STREAM is sent, the server side call is considered to be closed. - *

*/ public static ServerCallHandler asyncServerStreamingCall( ServerStreamingMethod method) { @@ -91,22 +65,6 @@ public static ServerCallHandler asyncServerStreamingC * Creates a {@link ServerCallHandler} for a client streaming method of the service. * * @param method an adaptor to the actual method on the service implementation. - *

- *

Client errors

- * The server's request stream observer will receive an - * onError callback with a {@link io.grpc.StatusRuntimeException} for the cancellation with the - * message 'Client cancelled', and exception cause set to null because the actual exception - * passed by the client to onError is never actually transmitted to the server and the server just - * receives a RST_STREAM frame indicating cancellation by the client. - *

- *

- *

Server errors

- * If the throwable sent to the server's outbound {@link StreamObserver}'s onError - * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be sent - * and UNKNOWN status code otherwise. Its description will be encoded to the stream trailer, but - * the cause (which may contain server application's information) will not. After the stream - * trailer with END_STREAM is sent, the server side call is considered to be closed. - *

*/ public static ServerCallHandler asyncClientStreamingCall( ClientStreamingMethod method) { @@ -117,22 +75,6 @@ public static ServerCallHandler asyncClientStreamingC * Creates a {@link ServerCallHandler} for a bidi streaming method of the service. * * @param method an adaptor to the actual method on the service implementation. - *

- *

Client errors

- * The server's request stream observer will receive an - * onError callback with a {@link io.grpc.StatusRuntimeException} for the cancellation with the - * message 'Client cancelled', and exception cause set to null because the actual exception - * passed by the client to onError is never actually transmitted to the server and the server just - * receives a RST_STREAM frame indicating cancellation by the client. - *

- *

- *

Server errors

- * If the throwable sent to the server's outbound {@link StreamObserver}'s onError - * is a {@link StatusException} or {@link StatusRuntimeException}, that status code will be sent - * and UNKNOWN status code otherwise. Its description will be encoded to the stream trailer, but - * the cause (which may contain server application's information) will not. After the stream - * trailer with END_STREAM is sent, the server side call is considered to be closed. - *

*/ public static ServerCallHandler asyncBidiStreamingCall( BidiStreamingMethod method) { @@ -143,6 +85,20 @@ public static ServerCallHandler asyncBidiStreamingCal * Adaptor to a unary call method. */ public interface UnaryMethod extends UnaryRequestMethod { + /** + * Invoke the method. + * + * @param request the request message from the client + * @param responseObserver the observer to receive the single response. Calling {@code + * responseObserver}'s {@link StreamObserver#onCompleted} or {@link + * StreamObserver#onError} is the end of the RPC. {@code onCompleted()} will close the RPC + * with status code OK. {@code onError()} will convert the Throwable to a Status with {@link + * Status#fromThrowable} and trailers with {@link Status#trailersFromThrowable}. The {@link + * Status#getCause} is not sent to the client, except if done by an interceptor. Callers + * generally create a Throwable with {@link Status#asException()}, {@link + * Status#asException(Metadata)}, {@link Status#asRuntimeException()}, or {@link + * Status#asRuntimeException(Metadata)}. + */ @Override void invoke(ReqT request, StreamObserver responseObserver); } @@ -150,6 +106,20 @@ public interface UnaryMethod extends UnaryRequestMethod extends UnaryRequestMethod { + /** + * Invoke the method. + * + * @param request the request message from the client + * @param responseObserver the observer to receive the response stream. Calling {@code + * responseObserver}'s {@link StreamObserver#onCompleted} or {@link + * StreamObserver#onError} is the end of the RPC. {@code onCompleted()} will close the RPC + * with status code OK. {@code onError()} will convert the Throwable to a Status with {@link + * Status#fromThrowable} and trailers with {@link Status#trailersFromThrowable}. The {@link + * Status#getCause} is not sent to the client, except if done by an interceptor. Callers + * generally create a Throwable with {@link Status#asException()}, {@link + * Status#asException(Metadata)}, {@link Status#asRuntimeException()}, or {@link + * Status#asRuntimeException(Metadata)}. + */ @Override void invoke(ReqT request, StreamObserver responseObserver); } @@ -157,6 +127,24 @@ public interface ServerStreamingMethod extends UnaryRequestMethod extends StreamingRequestMethod { + /** + * Invoke the method. + * + *

Client errors

+ * The Throwable received by the server's request stream observer when converted to a status + * with Status.fromThrowable(), always has the status code CANCELLED. + * + * @param responseObserver the observer to receive the single response. Calling {@code + * responseObserver}'s {@link StreamObserver#onCompleted} or {@link + * StreamObserver#onError} is the end of the RPC. {@code onCompleted()} will close the RPC + * with status code OK. {@code onError()} will convert the Throwable to a Status with {@link + * Status#fromThrowable} and trailers with {@link Status#trailersFromThrowable}. The {@link + * Status#getCause} is not sent to the client, except if done by an interceptor. Callers + * generally create a Throwable with {@link Status#asException()}, {@link + * Status#asException(Metadata)}, {@link Status#asRuntimeException()}, or {@link + * Status#asRuntimeException(Metadata)}. + * @return a stream observer for receiving the request stream from the client + */ @Override StreamObserver invoke(StreamObserver responseObserver); } @@ -164,6 +152,24 @@ public interface ClientStreamingMethod extends StreamingRequestMeth * Adaptor to a bidirectional streaming method. */ public interface BidiStreamingMethod extends StreamingRequestMethod { + /** + * Invoke the method. + * + *

Client errors

+ * The Throwable received by the server's request stream observer when converted to a status + * with Status.fromThrowable(), always has the status code CANCELLED. + * + * @param responseObserver the observer to receive the response stream. Calling {@code + * responseObserver}'s {@link StreamObserver#onCompleted} or {@link + * StreamObserver#onError} is the end of the RPC. {@code onCompleted()} will close the RPC + * with status code OK. {@code onError()} will convert the Throwable to a Status with {@link + * Status#fromThrowable} and trailers with {@link Status#trailersFromThrowable}. The {@link + * Status#getCause} is not sent to the client, except if done by an interceptor. Callers + * generally create a Throwable with {@link Status#asException()}, {@link + * Status#asException(Metadata)}, {@link Status#asRuntimeException()}, or {@link + * Status#asRuntimeException(Metadata)}. + * @return a stream observer for receiving the request stream from the client + */ @Override StreamObserver invoke(StreamObserver responseObserver); } From 00dd36f5f72c76a12352e13ee316e6955b5e4043 Mon Sep 17 00:00:00 2001 From: Kannan J Date: Thu, 27 Aug 2026 12:55:44 +0000 Subject: [PATCH 4/4] Redo javadoc changes after accepting the copy from master, and also add the javadoc for the "blockingV2" calls. --- .../main/java/io/grpc/stub/ClientCalls.java | 100 +++++++++++++++++- 1 file changed, 98 insertions(+), 2 deletions(-) diff --git a/stub/src/main/java/io/grpc/stub/ClientCalls.java b/stub/src/main/java/io/grpc/stub/ClientCalls.java index ff2804a0a1f..5fcb1d42d78 100644 --- a/stub/src/main/java/io/grpc/stub/ClientCalls.java +++ b/stub/src/main/java/io/grpc/stub/ClientCalls.java @@ -77,6 +77,12 @@ private ClientCalls() {} * *

If the provided {@code responseObserver} is an instance of {@link ClientResponseObserver}, * {@code beforeStart()} will be called. + * + *

Server errors

+ * If the server completes the RPC with status code OK, then {@code + * responseObserver.onCompleted()} is called at the end of the RPC. Otherwise the status and + * trailers are passed as a Throwable to {@code onError()} and can be accessed with {@link + * Status#fromThrowable} and {@link Status#trailersFromThrowable}. */ public static void asyncUnaryCall( ClientCall call, ReqT req, StreamObserver responseObserver) { @@ -91,6 +97,12 @@ public static void asyncUnaryCall( * *

If the provided {@code responseObserver} is an instance of {@link ClientResponseObserver}, * {@code beforeStart()} will be called. + * + *

Server errors

+ * If the server completes the RPC with status code OK, then {@code + * responseObserver.onCompleted()} is called at the end of the RPC. Otherwise the status and + * trailers are passed as a Throwable to {@code onError()} and can be accessed with {@link + * Status#fromThrowable} and {@link Status#trailersFromThrowable}. */ public static void asyncServerStreamingCall( ClientCall call, ReqT req, StreamObserver responseObserver) { @@ -106,6 +118,25 @@ public static void asyncServerStreamingCall( *

If the provided {@code responseObserver} is an instance of {@link ClientResponseObserver}, * {@code beforeStart()} will be called. * + *

Client errors

+ * {@link StreamObserver#onError} called on the request stream observer will result in stream + * cancellation. The response + * {@link StreamObserver} will be immediately notified of the cancellation with a + * {@link io.grpc.StatusRuntimeException} with the exception passed to onError set as the cause + * and the stream is considered closed. The server's request stream observer will receive an + * {@link StreamObserver#onError} callback with a throwable which when converted to a status + * with + * Status.fromThrowable(), always has the status code CANCELLED and exception cause set to + * null because the actual exception + * passed by the client to onError is never actually transmitted to the server and the server + * just receives a RST_STREAM frame indicating cancellation by the client. + * + *

Server errors

+ * If the server completes the RPC with status code OK, then {@code + * responseObserver.onCompleted()} is called at the end of the RPC. Otherwise the status and + * trailers are passed as a Throwable to {@code onError()} and can be accessed with {@link + * Status#fromThrowable} and {@link Status#trailersFromThrowable}. + * * @return request stream observer. It will extend {@link ClientCallStreamObserver} */ public static StreamObserver asyncClientStreamingCall( @@ -122,6 +153,25 @@ public static StreamObserver asyncClientStreamingCall( *

If the provided {@code responseObserver} is an instance of {@link ClientResponseObserver}, * {@code beforeStart()} will be called. * + *

Client errors

+ * {@link StreamObserver#onError} called on the request stream observer will result in stream + * cancellation. The response + * {@link StreamObserver} will be immediately notified of the cancellation with a + * {@link io.grpc.StatusRuntimeException} with the exception passed to onError set as the cause + * and the stream is considered closed. The server's request stream observer will receive an + * {@link StreamObserver#onError} callback with a throwable which when converted to a status + * with + * Status.fromThrowable(), always has the status code CANCELLED and exception cause set to + * null because the actual exception + * passed by the client to onError is never actually transmitted to the server and the server + * just receives a RST_STREAM frame indicating cancellation by the client. + * + *

Server errors

+ * If the server completes the RPC with status code OK, then {@code + * responseObserver.onCompleted()} is called at the end of the RPC. Otherwise the status and + * trailers are passed as a Throwable to {@code onError()} and can be accessed with {@link + * Status#fromThrowable} and {@link Status#trailersFromThrowable}. + * * @return request stream observer. It will extend {@link ClientCallStreamObserver} */ public static StreamObserver asyncBidiStreamingCall( @@ -134,6 +184,10 @@ public static StreamObserver asyncBidiStreamingCall( * Executes a unary call and blocks on the response. The {@code call} should not be already * started. After calling this method, {@code call} should no longer be used. * + *

Server errors

+ * If the server completes the RPC with a non-OK status, a {@link StatusRuntimeException} + * is thrown. The status code and trailers can be accessed from the exception. + * * @return the single response message. * @throws StatusRuntimeException on error */ @@ -149,6 +203,10 @@ public static RespT blockingUnaryCall(ClientCall call * Executes a unary call and blocks on the response. The {@code call} should not be already * started. After calling this method, {@code call} should no longer be used. * + *

Server errors

+ * If the server completes the RPC with a non-OK status, a {@link StatusRuntimeException} + * is thrown. The status code and trailers can be accessed from the exception. + * * @return the single response message. * @throws StatusRuntimeException on error */ @@ -186,6 +244,10 @@ public static RespT blockingUnaryCall( * Executes a unary call and blocks on the response, * throws a checked {@link StatusException}. * + *

Server errors

+ * If the server completes the RPC with a non-OK status, a {@link StatusException} + * is thrown. The status code and trailers can be accessed from the exception. + * * @return the single response message. * @throws StatusException on error */ @@ -204,7 +266,11 @@ public static RespT blockingV2UnaryCall( * response stream. The {@code call} should not be already started. After calling this method, * {@code call} should no longer be used. * - *

The returned iterator may throw {@link StatusRuntimeException} on error. + *

Server errors

+ * If the server completes the RPC with a non-OK status, the returned iterator will throw + * a {@link StatusRuntimeException} when attempting to read the error response (e.g. in + * {@link Iterator#hasNext} or {@link Iterator#next}). The status code and trailers can be + * accessed from the exception. * * @return an iterator over the response stream. */ @@ -219,7 +285,11 @@ public static Iterator blockingServerStreamingCall( * Executes a server-streaming call returning a blocking {@link Iterator} over the * response stream. * - *

The returned iterator may throw {@link StatusRuntimeException} on error. + *

Server errors

+ * If the server completes the RPC with a non-OK status, the returned iterator will throw + * a {@link StatusRuntimeException} when attempting to read the error response (e.g. in + * {@link Iterator#hasNext} or {@link Iterator#next}). The status code and trailers can be + * accessed from the exception. * *

Warning: the iterator can result in leaks if not completely consumed. * @@ -242,6 +312,13 @@ public static Iterator blockingServerStreamingCall( *

The methods {@link BlockingClientCall#hasNext()} and {@link * BlockingClientCall#cancel(String, Throwable)} can be used for more extensive control. * + *

Server errors

+ * If the server completes the RPC with a non-OK status, the returned {@link BlockingClientCall} + * will throw a {@link StatusException} when calling read or write operations (e.g., + * {@link BlockingClientCall#read()}, {@link BlockingClientCall#hasNext()}, or + * {@link BlockingClientCall#write(Object)}). The status code and trailers can be accessed from + * the exception. + * * @return A {@link BlockingClientCall} that has had the request sent and halfClose called */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") @@ -280,6 +357,13 @@ public static BlockingClientCall blockingV2ServerStre * {@link #blockingServerStreamingCall(Channel, MethodDescriptor, CallOptions, Object)} * which returns an iterator, which would leave the stream open if not completely consumed. * + *

Server errors

+ * If the server completes the RPC with a non-OK status, the returned {@link BlockingClientCall} + * will throw a {@link StatusException} when calling read or write operations (e.g., + * {@link BlockingClientCall#read()}, {@link BlockingClientCall#hasNext()}, or + * {@link BlockingClientCall#write(Object)}). The status code and trailers can be accessed from + * the exception. + * * @return A {@link BlockingClientCall} which can be used by the client to write and receive * messages over the grpc channel. */ @@ -294,6 +378,13 @@ public static BlockingClientCall blockingClientStream * ({@link BlockingClientCall}) which can be used by the client to send and receive messages over * the grpc channel. * + *

Server errors

+ * If the server completes the RPC with a non-OK status, the returned {@link BlockingClientCall} + * will throw a {@link StatusException} when calling read or write operations (e.g., + * {@link BlockingClientCall#read()}, {@link BlockingClientCall#hasNext()}, or + * {@link BlockingClientCall#write(Object)}). The status code and trailers can be accessed from + * the exception. + * * @return an object representing the call which can be used to read, write and terminate it. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") @@ -316,6 +407,11 @@ public static BlockingClientCall blockingBidiStreamin * {@code call} should not be already started. After calling this method, {@code call} should no * longer be used. * + *

Server errors

+ * If the server completes the RPC with a non-OK status, the returned future will fail with + * a {@link StatusRuntimeException}. The status code and trailers can be accessed from the + * exception. + * * @return a future for the single response message. */ public static ListenableFuture futureUnaryCall(