|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2021 the original author or authors. |
| 2 | + * Copyright 2002-2022 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
26 | 26 | import graphql.execution.DataFetcherExceptionHandler;
|
27 | 27 | import graphql.execution.DataFetcherExceptionHandlerParameters;
|
28 | 28 | import graphql.execution.DataFetcherExceptionHandlerResult;
|
| 29 | +import graphql.execution.ExecutionId; |
29 | 30 | import graphql.schema.DataFetchingEnvironment;
|
30 | 31 | import org.apache.commons.logging.Log;
|
31 | 32 | import org.apache.commons.logging.LogFactory;
|
@@ -67,44 +68,59 @@ public DataFetcherExceptionHandlerResult onException(DataFetcherExceptionHandler
|
67 | 68 |
|
68 | 69 | @Override
|
69 | 70 | public CompletableFuture<DataFetcherExceptionHandlerResult> handleException(DataFetcherExceptionHandlerParameters params) {
|
70 |
| - Throwable exception = getException(params); |
71 |
| - DataFetchingEnvironment environment = params.getDataFetchingEnvironment(); |
| 71 | + Throwable exception = unwrapException(params); |
| 72 | + DataFetchingEnvironment env = params.getDataFetchingEnvironment(); |
72 | 73 | try {
|
73 |
| - if (logger.isDebugEnabled()) { |
74 |
| - logger.debug("Resolving exception", exception); |
75 |
| - } |
76 | 74 | return Flux.fromIterable(this.resolvers)
|
77 |
| - .flatMap((resolver) -> resolver.resolveException(exception, environment)) |
| 75 | + .flatMap(resolver -> resolver.resolveException(exception, env)) |
| 76 | + .map(errors -> DataFetcherExceptionHandlerResult.newResult().errors(errors).build()) |
78 | 77 | .next()
|
79 |
| - .map((errors) -> DataFetcherExceptionHandlerResult.newResult().errors(errors).build()) |
80 |
| - .switchIfEmpty(Mono.fromCallable(() -> createInternalError(exception, environment))) |
| 78 | + .doOnNext(result -> logResolvedException(exception, result)) |
| 79 | + .onErrorResume(resolverEx -> Mono.just(handleResolverError(resolverEx, exception, env))) |
| 80 | + .switchIfEmpty(Mono.fromCallable(() -> createInternalError(exception, env))) |
81 | 81 | .contextWrite((context) -> {
|
82 |
| - ContextView contextView = ReactorContextManager.getReactorContext(environment); |
| 82 | + ContextView contextView = ReactorContextManager.getReactorContext(env); |
83 | 83 | return (contextView.isEmpty() ? context : context.putAll(contextView));
|
84 | 84 | })
|
85 | 85 | .toFuture();
|
86 | 86 | }
|
87 |
| - catch (Exception ex) { |
88 |
| - if (logger.isWarnEnabled()) { |
89 |
| - logger.warn("Failed to handle " + exception.getMessage(), ex); |
90 |
| - } |
91 |
| - return CompletableFuture.completedFuture(createInternalError(exception, environment)); |
| 87 | + catch (Exception resolverEx) { |
| 88 | + return CompletableFuture.completedFuture(handleResolverError(resolverEx, exception, env)); |
92 | 89 | }
|
93 | 90 | }
|
94 | 91 |
|
95 |
| - private Throwable getException(DataFetcherExceptionHandlerParameters params) { |
| 92 | + private DataFetcherExceptionHandlerResult handleResolverError( |
| 93 | + Throwable resolverException, Throwable originalException, DataFetchingEnvironment environment) { |
| 94 | + |
| 95 | + if (logger.isWarnEnabled()) { |
| 96 | + logger.warn("Failure while resolving " + originalException.getMessage(), resolverException); |
| 97 | + } |
| 98 | + return createInternalError(originalException, environment); |
| 99 | + } |
| 100 | + |
| 101 | + private Throwable unwrapException(DataFetcherExceptionHandlerParameters params) { |
96 | 102 | Throwable ex = params.getException();
|
97 | 103 | return ((ex instanceof CompletionException) ? ex.getCause() : ex);
|
98 | 104 | }
|
99 | 105 |
|
100 |
| - private DataFetcherExceptionHandlerResult createInternalError(Throwable ex, DataFetchingEnvironment env) { |
| 106 | + private void logResolvedException(Throwable ex, DataFetcherExceptionHandlerResult result) { |
| 107 | + if (logger.isDebugEnabled()) { |
| 108 | + logger.debug("Resolved " + ex.getClass().getSimpleName() + |
| 109 | + " to GraphQL error(s): " + result.getErrors(), ex); |
| 110 | + } |
| 111 | + } |
101 | 112 |
|
102 |
| - GraphQLError error = GraphqlErrorBuilder.newError(env) |
103 |
| - .errorType(ErrorType.INTERNAL_ERROR) |
104 |
| - .message((StringUtils.hasText(ex.getMessage()) ? ex.getMessage() : ex.getClass().getSimpleName())) |
| 113 | + private DataFetcherExceptionHandlerResult createInternalError(Throwable ex, DataFetchingEnvironment environment) { |
| 114 | + if (logger.isErrorEnabled()) { |
| 115 | + ExecutionId id = environment.getExecutionId(); |
| 116 | + logger.error("Unresolved " + ex.getClass().getSimpleName() + ", executionId= " + id, ex); |
| 117 | + } |
| 118 | + return DataFetcherExceptionHandlerResult |
| 119 | + .newResult(GraphqlErrorBuilder.newError(environment) |
| 120 | + .errorType(ErrorType.INTERNAL_ERROR) |
| 121 | + .message((StringUtils.hasText(ex.getMessage()) ? ex.getMessage() : ex.getClass().getSimpleName())) |
| 122 | + .build()) |
105 | 123 | .build();
|
106 |
| - |
107 |
| - return DataFetcherExceptionHandlerResult.newResult(error).build(); |
108 | 124 | }
|
109 | 125 |
|
110 | 126 | }
|
0 commit comments