When a server implementation method throws an exception, it is caught by the generated connectDeferredToObserver() method and passed to the observer's onError() method. While that seems reasonable at first, the onError() method documentation suggests otherwise:
t should be a io.grpc.StatusException or io.grpc.StatusRuntimeException, but other Throwable types are possible. Callers should generally convert from a io.grpc.Status via io.grpc.Status.asException() or io.grpc.Status.asRuntimeException(). Implementations should generally convert to a Status via io.grpc.Status.fromThrowable(Throwable).
The result of passing the exception to the onError() method is that the exception is not logged anywhere, and cannot be detected by a ServerInterceptor.
Java code generated by GRPC on the other hand allows exceptions thrown by the implementation to propagate up to the ServerCall.Listener.onHalfClose() method, where they can be intercepted by a ServerInterceptor, allowing them to be handled by user code, and logged.
I believe that the generated code should simply not catch these exceptions, making it functionally much more similar to the generated java code.
When a server implementation method throws an exception, it is caught by the generated
connectDeferredToObserver()
method and passed to the observer'sonError()
method. While that seems reasonable at first, theonError()
method documentation suggests otherwise:The result of passing the exception to the
onError()
method is that the exception is not logged anywhere, and cannot be detected by aServerInterceptor
.Java code generated by GRPC on the other hand allows exceptions thrown by the implementation to propagate up to the
ServerCall.Listener.onHalfClose()
method, where they can be intercepted by aServerInterceptor
, allowing them to be handled by user code, and logged.I believe that the generated code should simply not catch these exceptions, making it functionally much more similar to the generated java code.