|
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