我正在努力寻找正确的方法来处理服务层中抛出的异常,以便 GraphQL 响应包含有意义的错误消息。我知道服务器错误不应包含任何消息,但这里我们讨论的是客户端错误。
GPT 建议使用 JaxRS 中的
ExceptionMapper
但这不起作用:
@GraphQLApi
@RegisterProvider(MyExceptionMapper.class)
public class MembersGraphQLApi {
@Query("members")
public List<Member> members(String keyword) throws UserException {
throw new UserException("This is a test exception");
}
}
和
@Provider
public class MyExceptionMapper implements ExceptionMapper<UserException> {
@Override
public Response toResponse(UserException exception) {
// just some dummy code to make the response very different
// to the generated response
return Response
.status(400)
.entity(exception.getMessage())
.build();
}
}
这是服务器自动生成的响应,我希望有所不同:
{
"errors": [
{
"message": "Server Error",
"locations": [
{
"line": 2,
"column": 2
}
],
"path": [
"members"
],
"extensions": {
"exception": "de.codevibe.jeelab.UserException",
"classification": "DataFetchingException",
"code": "user"
}
}
],
"data": {
"members": null
}
}
到目前为止,我唯一的解决方案是捕获每个业务异常并重新抛出一些
GraphQLException
异常子类型,但这感觉很愚蠢,在每个查询方法中进行所有样板处理。
基本上我想要的是类似 Spring Boot 控制器建议的东西。
是的,GPT 幻想使用与 JAX-RS 相同的异常映射机制会很好。但这实际上甚至没有必要,因为错误响应的格式是在 GraphQL 规范中指定的,而这对于 REST 来说并非如此;所以 JAX-RS 一定更强大,而 GraphQL 更简单。
术语
client error
与 server error
通常没有明确的定义。在 MP GraphQL Spec 中,client error
被定义为客户端发送技术上无效的请求,但您想要抛出的 UserException
可能是深度验证的结果,例如数据库中的某些数据不存在。根据上面的规范,这是一个server error
。
默认情况下,未检查异常返回的
message
(默认情况下)始终为“服务器错误”,因此有关实际 Java 异常的详细信息不会泄露给客户端。但对于已检查的异常,消息会包含在内。所以你的 UserException
似乎没有被选中,这也很好:
您可以将异常类的完全限定名称
de.codevibe.jeelab.UserException
放入 MP Config mp.graphql.showErrorMessage
(请注意,此选项的已弃用名称是 mp.graphql.exceptionsWhiteList
)。如果您有多个异常,您可以用逗号作为分隔符列出它们,甚至更好:您可以创建所有异常的公共超类,客户端应该了解它们做错了什么,并进行配置。
那就是
message
;而code
中的extensions
则源自类名,对此还有更多要说的。