From 474fbcafa14861cba2862d8012fcad0c2fa680ad Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 29 Jan 2025 16:41:32 +0000 Subject: [PATCH] Handler failure from GraphQlExceptionHandler method Closes gh-1090 --- .../AnnotatedControllerExceptionResolver.java | 11 +++++++- ...tatedControllerExceptionResolverTests.java | 25 ++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolver.java b/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolver.java index 97e6551f..1ddc505d 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolver.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -356,7 +356,16 @@ final class AnnotatedControllerExceptionResolver implements HandlerDataFetcherEx return this.method; } + @SuppressWarnings("unchecked") Mono> adapt(@Nullable Object result, Throwable ex) { + if (result instanceof Mono errorMono && this.adapter != ReturnValueAdapter.forMono) { + return (Mono>) errorMono.onErrorMap((ex2) -> { + if (logger.isWarnEnabled()) { + logger.warn("Failure in @GraphQlExceptionHandler " + this.method, ex2); + } + return ex; // fall back to original exception + }); + } return this.adapter.adapt(result, this.returnType, ex); } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolverTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolverTests.java index c0845378..46260800 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolverTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -111,6 +111,19 @@ public class AnnotatedControllerExceptionResolverTests { StepVerifier.create(resolver.resolveException(ex, this.environment, controller)).verifyComplete(); } + @Test // gh-1090 + void failureFromResolver() { + ExceptionThrowingController controller = new ExceptionThrowingController(); + + Exception ex = new IllegalArgumentException("Bad input"); + AnnotatedControllerExceptionResolver resolver = exceptionResolver(); + resolver.registerController(controller.getClass()); + + StepVerifier.create(resolver.resolveException(ex, this.environment, controller)) + .expectErrorSatisfies(actual -> assertThat(actual).isSameAs(ex)) + .verify(); + } + @Test void resolveWithControllerAdvice() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); @@ -304,4 +317,14 @@ public class AnnotatedControllerExceptionResolverTests { } + + private static class ExceptionThrowingController { + + @GraphQlExceptionHandler + GraphQLError handle(IllegalArgumentException ex) { + throw new IllegalStateException("failure in exception handler"); + } + + } + }