silb78
silb78

Reputation: 139

Java gRPC: exception from client to server

Is it's possible to throw an exception from the client to the server? We have an open stream from the server to the client:

rpc addStream(Request) returns (stream StreamMessage) {}     

When i try something like this:

throw Status.INTERNAL.withDescription(e.getMessage()).withCause(e.getCause()).asRuntimeException();

I got the exception in the StreamObserver.onError on the client, but there is no exception on the server-side.

Upvotes: 0

Views: 1296

Answers (1)

Eric Anderson
Eric Anderson

Reputation: 26464

Servers can respond with a "status" that the stub API exposes as a StatusRuntimeException. Clients, however, can only "cancel" the RPC. Servers will not know the source of the cancellation; it could be because the client cancelled or maybe the TCP connection broke.

In a client-streaming or bidi-streaming call, the client can cancel by calling observer.onError() (without ever calling onCompleted()). However, if the client called onCompleted() or the RPC has a unary request, then you need to use ClientCallStreamObserver or Context:

stub.someRpc(request, new ClientResponseObserver<Request, Response>() {
  private ClientCallStreamObserver<Request> requestStream;

  @Override public void beforeStart(ClientCallStreamObserver<Request> requestStream) {
    this.requestStream = requestStream;
  }
  ...
});

// And then where you want to cancel

// RequestStream is non-thread-safe. For unary requests, wait until
// stub.someRpc() returns, since it uses the stream internally.
// The string is not sent to the server. It is just "echoed"
// back to the client's `onError()` to make clear that the
// cancellation was locally caused.
requestStream.cancel("some message for yourself", null);


// For thread-safe cancellation (e.g., for client-streaming)
CancellableContext ctx = Context.current().withCancellation();
StreamObserver requestObserver = ctx.call(() ->
  stub.someRpc(new StreamObserver<Response>() {
    @Override public void onCompleted() {
      // The ctx must be closed when done, to avoid leaks
      ctx.cancel(null);
    }

    @Override public void onError() {
      ctx.cancel(null);
    }
  }));

// The place you want to cancel
ctx.cancel(ex);

Upvotes: 1

Related Questions