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(