From 55876bdbca7f377e0908b4ef91cbd6e40a99418a Mon Sep 17 00:00:00 2001 From: "$(git --no-pager log --format=format:'%an' -n 1)" <$(git --no-pager log --format=format:'%ae' -n 1)> Date: Tue, 25 Feb 2025 11:37:22 +0300 Subject: [PATCH 1/8] feat(2132): unwrap invocation target exception --- .../exceptions/DefaultDataFetcherExceptionHandler.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt b/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt index 23cfbdb8f..4eb25c57a 100644 --- a/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt +++ b/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt @@ -25,6 +25,7 @@ import org.slf4j.Logger import org.slf4j.LoggerFactory import org.slf4j.event.Level import org.springframework.util.ClassUtils +import java.lang.reflect.InvocationTargetException import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletionException @@ -38,7 +39,9 @@ open class DefaultDataFetcherExceptionHandler : DataFetcherExceptionHandler { ): CompletableFuture = CompletableFuture.completedFuture(doHandleException(handlerParameters)) private fun doHandleException(handlerParameters: DataFetcherExceptionHandlerParameters): DataFetcherExceptionHandlerResult { - val exception = unwrapCompletionException(handlerParameters.exception) + val exception = handlerParameters.exception + .unwrapCompletionException() + .unwrapInvocationTargetException() val graphqlError = when (exception) { @@ -82,7 +85,11 @@ open class DefaultDataFetcherExceptionHandler : DataFetcherExceptionHandler { ) } - private fun unwrapCompletionException(e: Throwable): Throwable = if (e is CompletionException && e.cause != null) e.cause!! else e + private fun Throwable.unwrapCompletionException(): Throwable = + if (this is CompletionException && this.cause != null) this.cause!! else this + + private fun Throwable.unwrapInvocationTargetException(): Throwable = + if (this is InvocationTargetException && this.targetException != null) this.targetException!! else this protected val logger: Logger get() = DefaultDataFetcherExceptionHandler.logger From 30e21fc2ecd807bbf33ce4a6a9f3d271c1651b5c Mon Sep 17 00:00:00 2001 From: "$(git --no-pager log --format=format:'%an' -n 1)" <$(git --no-pager log --format=format:'%ae' -n 1)> Date: Tue, 25 Feb 2025 11:57:22 +0300 Subject: [PATCH 2/8] test(2132): add test for unwrapping --- .../DefaultDataFetcherExceptionHandlerTest.kt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt b/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt index 89edca0a7..be0f7e369 100644 --- a/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt +++ b/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt @@ -35,7 +35,7 @@ import org.slf4j.Logger import org.slf4j.event.Level import org.slf4j.spi.NOPLoggingEventBuilder import org.springframework.security.access.AccessDeniedException -import java.lang.IllegalStateException +import java.lang.reflect.InvocationTargetException import java.util.concurrent.CompletionException class DefaultDataFetcherExceptionHandlerTest { @@ -245,4 +245,18 @@ class DefaultDataFetcherExceptionHandlerTest { verify { loggerMock.atLevel(Level.ERROR) } confirmVerified(loggerMock) } + + @Test + fun `unwraps the invocation target exception`() { + val invocation = InvocationTargetException(IllegalStateException("I'm illegal!"), "Target invocation happened") + + val params = DataFetcherExceptionHandlerParameters + .newExceptionParameters() + .exception(invocation) + .dataFetchingEnvironment(environment) + .build() + val result = DefaultDataFetcherExceptionHandler().handleException(params).get() + assertThat(result.errors.size).isEqualTo(1) + assertThat(result.errors[0].message).containsSubsequence("java.lang.IllegalStateException: I'm illegal!") + } } From e2eb477adbf88baaab9f97b17a1c867fa1ce7b11 Mon Sep 17 00:00:00 2001 From: "$(git --no-pager log --format=format:'%an' -n 1)" <$(git --no-pager log --format=format:'%ae' -n 1)> Date: Tue, 25 Feb 2025 11:58:51 +0300 Subject: [PATCH 3/8] style(2132): formatting --- .../dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt b/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt index be0f7e369..ccc0e78fe 100644 --- a/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt +++ b/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt @@ -255,7 +255,9 @@ class DefaultDataFetcherExceptionHandlerTest { .exception(invocation) .dataFetchingEnvironment(environment) .build() + val result = DefaultDataFetcherExceptionHandler().handleException(params).get() + assertThat(result.errors.size).isEqualTo(1) assertThat(result.errors[0].message).containsSubsequence("java.lang.IllegalStateException: I'm illegal!") } From f667630e59947143fbcbdfb818cac257c3498a8d Mon Sep 17 00:00:00 2001 From: "$(git --no-pager log --format=format:'%an' -n 1)" <$(git --no-pager log --format=format:'%ae' -n 1)> Date: Tue, 25 Feb 2025 11:59:31 +0300 Subject: [PATCH 4/8] style(2132): formatting --- .../exceptions/DefaultDataFetcherExceptionHandler.kt | 7 ++++--- .../DefaultDataFetcherExceptionHandlerTest.kt | 11 ++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt b/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt index 4eb25c57a..0e6827061 100644 --- a/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt +++ b/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt @@ -39,9 +39,10 @@ open class DefaultDataFetcherExceptionHandler : DataFetcherExceptionHandler { ): CompletableFuture = CompletableFuture.completedFuture(doHandleException(handlerParameters)) private fun doHandleException(handlerParameters: DataFetcherExceptionHandlerParameters): DataFetcherExceptionHandlerResult { - val exception = handlerParameters.exception - .unwrapCompletionException() - .unwrapInvocationTargetException() + val exception = + handlerParameters.exception + .unwrapCompletionException() + .unwrapInvocationTargetException() val graphqlError = when (exception) { diff --git a/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt b/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt index ccc0e78fe..df165fa4f 100644 --- a/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt +++ b/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt @@ -250,11 +250,12 @@ class DefaultDataFetcherExceptionHandlerTest { fun `unwraps the invocation target exception`() { val invocation = InvocationTargetException(IllegalStateException("I'm illegal!"), "Target invocation happened") - val params = DataFetcherExceptionHandlerParameters - .newExceptionParameters() - .exception(invocation) - .dataFetchingEnvironment(environment) - .build() + val params = + DataFetcherExceptionHandlerParameters + .newExceptionParameters() + .exception(invocation) + .dataFetchingEnvironment(environment) + .build() val result = DefaultDataFetcherExceptionHandler().handleException(params).get() From f6726a131d7855a9fe827d2a1c9aca4c6aead252 Mon Sep 17 00:00:00 2001 From: "$(git --no-pager log --format=format:'%an' -n 1)" <$(git --no-pager log --format=format:'%ae' -n 1)> Date: Tue, 25 Feb 2025 12:01:02 +0300 Subject: [PATCH 5/8] style(2132): formatting --- .../exceptions/DefaultDataFetcherExceptionHandlerTest.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt b/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt index df165fa4f..4a97b30ab 100644 --- a/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt +++ b/graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandlerTest.kt @@ -31,6 +31,7 @@ import io.mockk.spyk import io.mockk.verify import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertAll import org.slf4j.Logger import org.slf4j.event.Level import org.slf4j.spi.NOPLoggingEventBuilder @@ -259,7 +260,9 @@ class DefaultDataFetcherExceptionHandlerTest { val result = DefaultDataFetcherExceptionHandler().handleException(params).get() - assertThat(result.errors.size).isEqualTo(1) - assertThat(result.errors[0].message).containsSubsequence("java.lang.IllegalStateException: I'm illegal!") + assertAll( + { assertThat(result.errors.size).isEqualTo(1) }, + { assertThat(result.errors[0].message).containsSubsequence("java.lang.IllegalStateException: I'm illegal!") }, + ) } } From 010a4aa2b60997ae3342c105b9f859df1a88db7b Mon Sep 17 00:00:00 2001 From: "$(git --no-pager log --format=format:'%an' -n 1)" <$(git --no-pager log --format=format:'%ae' -n 1)> Date: Tue, 25 Feb 2025 15:52:39 +0300 Subject: [PATCH 6/8] refactor(2132): back to single method --- .../DefaultDataFetcherExceptionHandler.kt | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt b/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt index 0e6827061..abd47fbb4 100644 --- a/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt +++ b/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt @@ -39,10 +39,7 @@ open class DefaultDataFetcherExceptionHandler : DataFetcherExceptionHandler { ): CompletableFuture = CompletableFuture.completedFuture(doHandleException(handlerParameters)) private fun doHandleException(handlerParameters: DataFetcherExceptionHandlerParameters): DataFetcherExceptionHandlerResult { - val exception = - handlerParameters.exception - .unwrapCompletionException() - .unwrapInvocationTargetException() + val exception = unwrapCompletionException(handlerParameters.exception) val graphqlError = when (exception) { @@ -54,6 +51,7 @@ open class DefaultDataFetcherExceptionHandler : DataFetcherExceptionHandler { isSpringSecurityAccessException( exception, ) -> TypedGraphQLError.newPermissionDeniedBuilder() + else -> TypedGraphQLError.newInternalErrorBuilder() } builder @@ -86,11 +84,12 @@ open class DefaultDataFetcherExceptionHandler : DataFetcherExceptionHandler { ) } - private fun Throwable.unwrapCompletionException(): Throwable = - if (this is CompletionException && this.cause != null) this.cause!! else this - - private fun Throwable.unwrapInvocationTargetException(): Throwable = - if (this is InvocationTargetException && this.targetException != null) this.targetException!! else this + private fun unwrapCompletionException(e: Throwable): Throwable = + when (val exception = e.cause) { + is CompletionException -> unwrapCompletionException(exception.cause ?: exception) + is InvocationTargetException -> unwrapCompletionException(exception.targetException) + else -> e + } protected val logger: Logger get() = DefaultDataFetcherExceptionHandler.logger From 3561bd670aeb13598f61dc4955a0e61f759f68d4 Mon Sep 17 00:00:00 2001 From: "$(git --no-pager log --format=format:'%an' -n 1)" <$(git --no-pager log --format=format:'%ae' -n 1)> Date: Tue, 25 Feb 2025 15:58:42 +0300 Subject: [PATCH 7/8] refactor(2132): back to single method --- .../dgs/exceptions/DefaultDataFetcherExceptionHandler.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt b/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt index abd47fbb4..1ebfe7606 100644 --- a/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt +++ b/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt @@ -36,7 +36,8 @@ import java.util.concurrent.CompletionException open class DefaultDataFetcherExceptionHandler : DataFetcherExceptionHandler { override fun handleException( handlerParameters: DataFetcherExceptionHandlerParameters, - ): CompletableFuture = CompletableFuture.completedFuture(doHandleException(handlerParameters)) + ): CompletableFuture = + CompletableFuture.completedFuture(doHandleException(handlerParameters)) private fun doHandleException(handlerParameters: DataFetcherExceptionHandlerParameters): DataFetcherExceptionHandlerResult { val exception = unwrapCompletionException(handlerParameters.exception) @@ -85,9 +86,9 @@ open class DefaultDataFetcherExceptionHandler : DataFetcherExceptionHandler { } private fun unwrapCompletionException(e: Throwable): Throwable = - when (val exception = e.cause) { - is CompletionException -> unwrapCompletionException(exception.cause ?: exception) - is InvocationTargetException -> unwrapCompletionException(exception.targetException) + when (e) { + is CompletionException -> unwrapCompletionException(e.cause ?: e) + is InvocationTargetException -> unwrapCompletionException(e.targetException) else -> e } From 22935563bf4b60f00ce4082551114a7f3b8803da Mon Sep 17 00:00:00 2001 From: "$(git --no-pager log --format=format:'%an' -n 1)" <$(git --no-pager log --format=format:'%ae' -n 1)> Date: Tue, 25 Feb 2025 16:07:26 +0300 Subject: [PATCH 8/8] style(2132): formatting --- .../dgs/exceptions/DefaultDataFetcherExceptionHandler.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt b/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt index 1ebfe7606..2f142d531 100644 --- a/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt +++ b/graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/exceptions/DefaultDataFetcherExceptionHandler.kt @@ -36,8 +36,7 @@ import java.util.concurrent.CompletionException open class DefaultDataFetcherExceptionHandler : DataFetcherExceptionHandler { override fun handleException( handlerParameters: DataFetcherExceptionHandlerParameters, - ): CompletableFuture = - CompletableFuture.completedFuture(doHandleException(handlerParameters)) + ): CompletableFuture = CompletableFuture.completedFuture(doHandleException(handlerParameters)) private fun doHandleException(handlerParameters: DataFetcherExceptionHandlerParameters): DataFetcherExceptionHandlerResult { val exception = unwrapCompletionException(handlerParameters.exception)