From 020abdd3033dc71a16602fb091251a3865469c4a Mon Sep 17 00:00:00 2001 From: oryan Date: Wed, 2 Aug 2023 10:33:42 -0400 Subject: [PATCH 1/4] Remove usage of UndeclaredThrowableException --- .../tools/resolver/MethodFieldResolver.kt | 18 +++++------- .../tools/MethodFieldResolverTest.kt | 29 +++++++++++++++++++ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt b/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt index efd60cf7..d350a8e7 100644 --- a/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt +++ b/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt @@ -15,6 +15,7 @@ import graphql.schema.DataFetchingEnvironment import graphql.schema.GraphQLTypeUtil.isScalar import kotlinx.coroutines.future.future import org.slf4j.LoggerFactory +import java.lang.reflect.InvocationTargetException import java.lang.reflect.Method import java.util.* import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn @@ -251,20 +252,15 @@ private suspend inline fun invokeSuspend(target: Any, resolverMethod: Method, ar } } -@Suppress("NOTHING_TO_INLINE") -private inline fun invoke(method: Method, instance: Any, args: Array): Any? { +private fun invoke(method: Method, instance: Any, args: Array): Any? { try { return method.invoke(instance, *args) - } catch (invocationException: java.lang.reflect.InvocationTargetException) { - val e = invocationException.cause - if (e is RuntimeException) { - throw e + } catch (invocationException: InvocationTargetException) { + when (val e = invocationException.cause) { + is RuntimeException -> throw e + is Error -> throw e + else -> throw e ?: RuntimeException("Unknown error occurred while invoking resolver method") } - if (e is Error) { - throw e - } - - throw java.lang.reflect.UndeclaredThrowableException(e) } } diff --git a/src/test/kotlin/graphql/kickstart/tools/MethodFieldResolverTest.kt b/src/test/kotlin/graphql/kickstart/tools/MethodFieldResolverTest.kt index 1c647da0..642fe6c5 100644 --- a/src/test/kotlin/graphql/kickstart/tools/MethodFieldResolverTest.kt +++ b/src/test/kotlin/graphql/kickstart/tools/MethodFieldResolverTest.kt @@ -1,5 +1,6 @@ package graphql.kickstart.tools +import graphql.ExceptionWhileDataFetching import graphql.ExecutionInput import graphql.GraphQL import graphql.GraphQLContext @@ -210,6 +211,34 @@ class MethodFieldResolverTest { assertEquals(result.getData(), mapOf("test" to 6)) } + @Test + fun `should unwrap and rethrow resolver exceptions`() { + val schema = SchemaParser.newParser() + .schemaString( + """ + type Query { + test: String + } + """) + .resolvers(object : GraphQLQueryResolver { + fun test(): String = throw Exception("Whoops") + }) + .build() + .makeExecutableSchema() + + val gql = GraphQL.newGraphQL(schema).build() + val result = gql.execute(ExecutionInput.newExecutionInput().query( + """ + query { + test + } + """)) + + assertEquals(result.errors.size, 1) + val exceptionWhileDataFetching = result.errors[0] as ExceptionWhileDataFetching + assertEquals(exceptionWhileDataFetching.exception.message, "Whoops") + } + /** * Custom Scalar Class type that doesn't work with Jackson serialization/deserialization */ From a8eb748d5dd3c47e1367d47183159cd12f6fa3ab Mon Sep 17 00:00:00 2001 From: oryan Date: Wed, 2 Aug 2023 10:37:16 -0400 Subject: [PATCH 2/4] Remove usage of UndeclaredThrowableException --- .../kickstart/tools/resolver/MethodFieldResolver.kt | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt b/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt index d350a8e7..b74ab211 100644 --- a/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt +++ b/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt @@ -30,7 +30,7 @@ internal class MethodFieldResolver( field: FieldDefinition, search: FieldResolverScanner.Search, options: SchemaParserOptions, - val method: Method + val method: Method, ) : FieldResolver(field, search, options, search.type) { private val log = LoggerFactory.getLogger(javaClass) @@ -187,7 +187,7 @@ internal open class MethodFieldResolverDataFetcher( private val sourceResolver: SourceResolver, method: Method, private val args: List, - private val options: SchemaParserOptions + private val options: SchemaParserOptions, ) : DataFetcher { private val resolverMethod = method @@ -242,7 +242,7 @@ internal class TrivialMethodFieldResolverDataFetcher( sourceResolver: SourceResolver, method: Method, args: List, - options: SchemaParserOptions + options: SchemaParserOptions, ) : MethodFieldResolverDataFetcher(sourceResolver, method, args, options), TrivialDataFetcher // just to mark it for tracing and optimizations @@ -256,11 +256,7 @@ private fun invoke(method: Method, instance: Any, args: Array): Any? { try { return method.invoke(instance, *args) } catch (invocationException: InvocationTargetException) { - when (val e = invocationException.cause) { - is RuntimeException -> throw e - is Error -> throw e - else -> throw e ?: RuntimeException("Unknown error occurred while invoking resolver method") - } + throw invocationException.cause ?: RuntimeException("Unknown error occurred while invoking resolver method") } } From 8cf2f09fb9576b767bfabc445199aa740a38c393 Mon Sep 17 00:00:00 2001 From: oryan Date: Wed, 2 Aug 2023 10:38:05 -0400 Subject: [PATCH 3/4] Revert --- .../graphql/kickstart/tools/resolver/MethodFieldResolver.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt b/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt index b74ab211..8a56ee34 100644 --- a/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt +++ b/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt @@ -30,7 +30,7 @@ internal class MethodFieldResolver( field: FieldDefinition, search: FieldResolverScanner.Search, options: SchemaParserOptions, - val method: Method, + val method: Method ) : FieldResolver(field, search, options, search.type) { private val log = LoggerFactory.getLogger(javaClass) @@ -187,7 +187,7 @@ internal open class MethodFieldResolverDataFetcher( private val sourceResolver: SourceResolver, method: Method, private val args: List, - private val options: SchemaParserOptions, + private val options: SchemaParserOptions ) : DataFetcher { private val resolverMethod = method @@ -242,7 +242,7 @@ internal class TrivialMethodFieldResolverDataFetcher( sourceResolver: SourceResolver, method: Method, args: List, - options: SchemaParserOptions, + options: SchemaParserOptions ) : MethodFieldResolverDataFetcher(sourceResolver, method, args, options), TrivialDataFetcher // just to mark it for tracing and optimizations From 41737d3f2323a83163f911d92ae278c0a2ebe1ed Mon Sep 17 00:00:00 2001 From: oryan Date: Wed, 2 Aug 2023 10:39:13 -0400 Subject: [PATCH 4/4] Remove usage of UndeclaredThrowableException --- .../graphql/kickstart/tools/resolver/MethodFieldResolver.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt b/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt index 8a56ee34..c76023d5 100644 --- a/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt +++ b/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt @@ -255,8 +255,8 @@ private suspend inline fun invokeSuspend(target: Any, resolverMethod: Method, ar private fun invoke(method: Method, instance: Any, args: Array): Any? { try { return method.invoke(instance, *args) - } catch (invocationException: InvocationTargetException) { - throw invocationException.cause ?: RuntimeException("Unknown error occurred while invoking resolver method") + } catch (e: InvocationTargetException) { + throw e.cause ?: RuntimeException("Unknown error occurred while invoking resolver method") } }