我有一个 Quarkus gRPC 服务器(与 Mutiny 反应),并且我想在服务器端服务抛出异常时自定义响应状态。
默认情况下,当抛出异常时,服务器会响应 gRPC 状态
UNKNOWN
。当抛出一些异常时,我想用状态 INTERNAL
(或其他)来响应。
为此,我使用了
ExceptionHandlerProvider
(doc)。问题是方法 ExceptionHandler::handleException
永远不会被调用(但是 ExceptionHandlerProvider::transform
会被调用)。
代码简化,真正的代码这里
@ApplicationScoped
public class HelloExceptionHandlerProvider implements ExceptionHandlerProvider {
@Override
public <ReqT, RespT> ExceptionHandler<ReqT, RespT> createHandler(ServerCall.Listener<ReqT> listener, ServerCall<ReqT, RespT> serverCall, Metadata metadata) {
System.out.println("HelloExceptionHandlerProvider::createHandler");
return new HelloExceptionHandler<>(listener, serverCall, metadata);
}
@Override
public Throwable transform(final Throwable throwable) {
return new StatusException().status(Status.INTERNAL); // TODO: transform the throwable to status exception
}
protected static class HelloExceptionHandler<I, O> extends ExceptionHandler<I, O> {
public HelloExceptionHandler(ServerCall.Listener<I> listener, ServerCall<I, O> call, Metadata metadata) {
super(listener, call, metadata);
}
@Override
protected void handleException(Throwable throwable, ServerCall<I, O> call, Metadata metadata) {
// This is never called!
StatusException ex = (StatusException) throwable;
call.close(ex.getStatus(), ex.getTrailers());
}
}
}
所以在客户端,当抛出异常时,响应状态仍然是
UNKNOWN
(应该是INTERNAL)
,但是有一个grpc-status
元数据值,值为13(INTERNAL
代码值)。
在日志中,一切都很好,除了丢失的
handleException
电话:
HelloExceptionHandlerProvider::createHandler
HelloExceptionHandler::constructor
HelloExceptionHandlerProvider::transform - Should exit with status INTERNAL
我是不是错过了什么?
另一个奇怪的事情是,如果我评论
metadata.put(Metadata.Key.of("hello-error-code", Metadata.ASCII_STRING_MARSHALLER), ex.getCode());
行,那么状态就是预期的 INTERNAL
。添加预告片元数据似乎会导致响应失败并显示 UNKNOWN
状态。
编辑: 使用 Quarkus gRPC 客户端时似乎没问题。这种奇怪的行为可以在 Postman 界面中看到。请参阅https://github.com/quarkusio/quarkus/discussions/31110#discussioncomment-4956272
我使用的是 Quakus 3.9.2 版本并遇到了这个问题。 github 讨论说它不久前就已经修复了。这对你有用吗?