Polishing in exception handling

See gh-996
This commit is contained in:
rstoyanchev
2024-06-25 16:00:45 +01:00
parent 09680e1c84
commit e43ef3a709
2 changed files with 30 additions and 30 deletions

View File

@@ -175,7 +175,7 @@ final class AnnotatedControllerExceptionResolver {
Throwable ex, DataFetchingEnvironment environment, @Nullable Object controller) {
Object controllerOrAdvice = null;
MethodHolder methodHolder = null;
MethodReturnValueAdapter methodReturnValueAdapter = null;
Class<?> controllerType = null;
if (controller != null) {
@@ -183,19 +183,19 @@ final class AnnotatedControllerExceptionResolver {
MethodResolver methodResolver = this.controllerCache.get(controllerType);
if (methodResolver != null) {
controllerOrAdvice = controller;
methodHolder = methodResolver.resolveMethod(ex);
methodReturnValueAdapter = methodResolver.resolveMethod(ex);
}
else if (logger.isWarnEnabled()) {
logger.warn("No registration for controller type: " + controllerType.getName());
}
}
if (methodHolder == null) {
if (methodReturnValueAdapter == null) {
for (Map.Entry<ControllerAdviceBean, MethodResolver> entry : this.controllerAdviceCache.entrySet()) {
ControllerAdviceBean advice = entry.getKey();
if (controller == null || advice.isApplicableToBeanType(controllerType)) {
methodHolder = entry.getValue().resolveMethod(ex);
if (methodHolder != null) {
methodReturnValueAdapter = entry.getValue().resolveMethod(ex);
if (methodReturnValueAdapter != null) {
controllerOrAdvice = advice.resolveBean();
break;
}
@@ -203,18 +203,19 @@ final class AnnotatedControllerExceptionResolver {
}
}
if (methodHolder == null) {
if (methodReturnValueAdapter == null) {
return Mono.empty();
}
return invokeExceptionHandler(ex, environment, controllerOrAdvice, methodHolder);
return invokeExceptionHandler(ex, environment, controllerOrAdvice, methodReturnValueAdapter);
}
private Mono<List<GraphQLError>> invokeExceptionHandler(
Throwable exception, DataFetchingEnvironment env, Object controllerOrAdvice, MethodHolder methodHolder) {
Throwable exception, DataFetchingEnvironment env, Object controllerOrAdvice,
MethodReturnValueAdapter methodReturnValueAdapter) {
DataFetcherHandlerMethod exceptionHandler = new DataFetcherHandlerMethod(
new HandlerMethod(controllerOrAdvice, methodHolder.getMethod()), this.argumentResolvers,
new HandlerMethod(controllerOrAdvice, methodReturnValueAdapter.getMethod()), this.argumentResolvers,
null, null, false);
List<Throwable> exceptions = new ArrayList<>();
@@ -236,7 +237,7 @@ final class AnnotatedControllerExceptionResolver {
Object result = exceptionHandler.invoke(env, arguments);
return methodHolder.adapt(result, exception);
return methodReturnValueAdapter.adapt(result, exception);
}
catch (Throwable invocationEx) {
// Any other than the original exception (or a cause) is unintended here,
@@ -256,17 +257,17 @@ final class AnnotatedControllerExceptionResolver {
private static final class MethodResolver {
@SuppressWarnings("DataFlowIssue")
private static final MethodHolder NO_MATCH =
new MethodHolder(ReflectionUtils.findMethod(MethodResolver.class, "noMatch"));
private static final MethodReturnValueAdapter NO_MATCH =
new MethodReturnValueAdapter(ReflectionUtils.findMethod(MethodResolver.class, "noMatch"));
private final Map<Class<? extends Throwable>, MethodHolder> exceptionMappings = new HashMap<>(16);
private final Map<Class<? extends Throwable>, MethodReturnValueAdapter> exceptionMappings = new HashMap<>(16);
private final Map<Class<? extends Throwable>, MethodHolder> resolvedExceptionCache = new ConcurrentReferenceHashMap<>(16);
private final Map<Class<? extends Throwable>, MethodReturnValueAdapter> resolvedExceptionCache = new ConcurrentReferenceHashMap<>(16);
MethodResolver(Map<Class<? extends Throwable>, Method> methodMap) {
methodMap.forEach((exceptionType, method) ->
this.exceptionMappings.put(exceptionType, new MethodHolder(method)));
this.exceptionMappings.put(exceptionType, new MethodReturnValueAdapter(method)));
}
/**
@@ -276,8 +277,8 @@ final class AnnotatedControllerExceptionResolver {
* @return the exception handler to use, or {@code null} if no match
*/
@Nullable
MethodHolder resolveMethod(Throwable exception) {
MethodHolder method = resolveMethodByExceptionType(exception.getClass());
MethodReturnValueAdapter resolveMethod(Throwable exception) {
MethodReturnValueAdapter method = resolveMethodByExceptionType(exception.getClass());
if (method == null) {
Throwable cause = exception.getCause();
if (cause != null) {
@@ -288,8 +289,8 @@ final class AnnotatedControllerExceptionResolver {
}
@Nullable
private MethodHolder resolveMethodByExceptionType(Class<? extends Throwable> exceptionType) {
MethodHolder method = this.resolvedExceptionCache.get(exceptionType);
private MethodReturnValueAdapter resolveMethodByExceptionType(Class<? extends Throwable> exceptionType) {
MethodReturnValueAdapter method = this.resolvedExceptionCache.get(exceptionType);
if (method == null) {
method = getMappedMethod(exceptionType);
this.resolvedExceptionCache.put(exceptionType, method);
@@ -297,7 +298,7 @@ final class AnnotatedControllerExceptionResolver {
return (method != NO_MATCH) ? method : null;
}
private MethodHolder getMappedMethod(Class<? extends Throwable> exceptionType) {
private MethodReturnValueAdapter getMappedMethod(Class<? extends Throwable> exceptionType) {
List<Class<? extends Throwable>> matches = new ArrayList<>();
for (Class<? extends Throwable> mappedException : this.exceptionMappings.keySet()) {
if (mappedException.isAssignableFrom(exceptionType)) {
@@ -323,9 +324,9 @@ final class AnnotatedControllerExceptionResolver {
/**
* Container for an exception handler method, and an adapter for its return values.
* Helps to adapt the return value of an exception handler method.
*/
private static class MethodHolder {
private static class MethodReturnValueAdapter {
private final Method method;
@@ -333,7 +334,7 @@ final class AnnotatedControllerExceptionResolver {
private final ReturnValueAdapter adapter;
MethodHolder(Method method) {
MethodReturnValueAdapter(Method method) {
Assert.notNull(method, "Method is required");
this.method = method;
this.returnType = new MethodParameter(method, -1);

View File

@@ -96,16 +96,15 @@ public abstract class DataFetcherExceptionResolverAdapter implements DataFetcher
@Nullable
@SuppressWarnings("deprecation")
private List<GraphQLError> resolveInternal(Throwable exception, DataFetchingEnvironment env) {
if (!this.threadLocalContextAware) {
return resolveToMultipleErrors(exception, env);
}
try {
return ContextSnapshot.captureFrom(env.getGraphQlContext())
.wrap(() -> resolveToMultipleErrors(exception, env))
.call();
return (this.threadLocalContextAware) ?
ContextSnapshot.captureFrom(env.getGraphQlContext())
.wrap(() -> resolveToMultipleErrors(exception, env))
.call() :
resolveToMultipleErrors(exception, env);
}
catch (Exception ex2) {
this.logger.warn("Failed to resolve " + exception, ex2);
this.logger.warn("Failure while resolving " + exception.getMessage(), ex2);
return null;
}
}