【问题标题】:Correct way to return errors in GraphQL-SPQR在 GraphQL-SPQR 中返回错误的正确方法
【发布时间】:2019-12-04 12:29:15
【问题描述】:

目前,我正在抛出 RuntimeException 以返回 GraphQL 验证错误。它工作得非常好,除了它在我的日志中抛出带有大量堆栈跟踪的可怕错误。

在这里您可以看到我正在检查提交的新用户注册变更,以确保密码相互匹配并且电子邮件地址尚未被使用。

在 GraphQL SPQR Spring Boot Starter 中执行此操作的正确方法是什么。

@GraphQLMutation (name="register")
public User register(@GraphQLArgument(name="firstname") String firstname, @GraphQLArgument(name="lastname") String lastname, @GraphQLArgument(name="email") String email, @GraphQLArgument(name="msisdn") String msisdn, @GraphQLArgument(name="password") String password, @GraphQLArgument (name="confirmPassword") String confirmPassword) {
    if (userRepo.findByEmail(email) != null) {
        throw new RuntimeException("User already exists");
    }

    if (!password.equals(confirmPassword)) {
        throw new RuntimeException("Passwords do not match");
    }

    User newUser = new User();
    //...
    return userRepo.save(newUser);
}

【问题讨论】:

  • 我不知道是否有一种传统的方法可以通过注释或类似的方式委托验证,但对于输入验证,我会抛出 IllegalArgumentException 而不是 RuntimeException,您也可以使用 google Preconditions 进行这些检查
  • 你想减少堆栈跟踪的大小吗?这是您想要的吗?如果是,那么您可以覆盖 DataFetcherExceptionHandler 并创建自定义处理程序并挂钩到 GraphQL。

标签: java spring-boot validation graphql graphql-spqr


【解决方案1】:

我不清楚你在问什么……但我假设你想自定义记录的内容。

对于初学者,我建议使用像 ValidationException 这样的专用异常类型,您可以用不同的方式捕获和处理它。

至于日志记录,它可能发生在 grapqh-java 中,因为 SPQR 本身不会记录任何内容。默认情况下,graphql-java 使用SimpleDataFetcherExceptionHandlerlogs the exceptions 在字段解析期间捕获。

您现在有几个选项,您可以在 SPQR 中注册一个 ResolverInterceptor,它会捕获验证异常并记录您想要的内容,并为用户返回带有错误消息的 DataFetcherResult。因为没有验证异常冒泡到 graphql-java,DataFetcherExceptionHandler 在这种情况下没有任何作用。

它看起来像:

public class ValidationInterceptor implements ResolverInterceptor {

    @Override
    public Object aroundInvoke(InvocationContext context, Continuation continuation) throws Exception {
        try {
            return continuation.proceed(context);
        } catch (ValidationException e) {
            log.warning(e);
            return DataFetcherResult.newResult()
                    .error(GraphqlErrorBuilder
                            .newError(context.getResolutionEnvironment().dataFetchingEnvironment)
                            .message(e.getMessage()) //the message for the user
                            .build());
        }
    }
}

查看the answer here 以获取有关使用 Spring Boot 注册自定义拦截器的说明。

另一个选项是替换 DataFetcherExceptionHandler graphql-java 使用。为此,您必须自己构造 GraphQL 对象并将其注册为 bean。

@Bean
public GraphQL graphQL(GraphQLSchema schema) {
    GraphQL.Builder builder = GraphQL.newGraphQL(schema)
            .queryExecutionStrategy(new AsyncExecutionStrategy(customExceptionHandler))
            .mutationExecutionStrategy(new AsyncSerialExecutionStrategy(customExceptionHandler));
    return builder.build();
}

如果某个地方有一个 Spring 功能可用于对托管 bean 进行异常处理,我也不会感到惊讶。

【讨论】:

  • 在我的解析器拦截器中,我收到了一个 InvocationTargetException,它包装了我想要捕获的异常,这是什么原因?
  • @Unidan 这对于反射调用期间的异常是正常的,但 SPQR 应该解开这些异常。你是哪个版本的?
  • 我在 0.10.0。 FWIW 拦截器使用 Kotlin,但所有解析器及其底层数据模型均使用 Java。
  • @Unidan 恐怕这是个错误(我自己验证过)。将在下一个版本中修复。
  • 好的,感谢您的快速响应。绝对喜欢图书馆,即使几乎没有任何文档:D!
猜你喜欢
  • 2016-08-02
  • 2017-02-20
  • 1970-01-01
  • 2018-10-07
  • 2021-08-22
  • 2018-09-24
  • 2020-09-12
  • 2012-08-07
  • 2019-06-08
相关资源
最近更新 更多