From a1a941c88fa7dcbc6d0734ad095fb9a607bfe489 Mon Sep 17 00:00:00 2001 From: Patrick Strawderman Date: Tue, 2 Apr 2024 12:09:44 -0700 Subject: [PATCH] Fix bug in Spring query executors The Spring query executors would transform the ExecutionResult, but in the process would lose extensions of any GraphQLErrors returned. --- .../SpringGraphQLDgsQueryExecutor.kt | 19 ++++++----------- .../SpringGraphQLDgsReactiveQueryExecutor.kt | 21 +++++++------------ 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/SpringGraphQLDgsQueryExecutor.kt b/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/SpringGraphQLDgsQueryExecutor.kt index fdff921d5..93bf51ef4 100644 --- a/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/SpringGraphQLDgsQueryExecutor.kt +++ b/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/SpringGraphQLDgsQueryExecutor.kt @@ -30,16 +30,14 @@ import com.netflix.graphql.dgs.internal.DgsQueryExecutorRequestCustomizer import com.netflix.graphql.dgs.internal.DgsWebMvcRequestData import graphql.ExecutionResult import graphql.GraphQLContext -import graphql.GraphQLError import org.springframework.graphql.ExecutionGraphQlService import org.springframework.graphql.support.DefaultExecutionGraphQlRequest import org.springframework.http.HttpHeaders import org.springframework.web.context.request.RequestContextHolder import org.springframework.web.context.request.ServletWebRequest import org.springframework.web.context.request.WebRequest -import java.util.concurrent.CompletableFuture -class SpringGraphQLDgsQueryExecutor(val executionService: ExecutionGraphQlService, private val dgsContextBuilder: DefaultDgsGraphQLContextBuilder, private val dgsDataLoaderProvider: DgsDataLoaderProvider, private val requestCustomizer: DgsQueryExecutorRequestCustomizer = DgsQueryExecutorRequestCustomizer.DEFAULT_REQUEST_CUSTOMIZER) : DgsQueryExecutor { +class SpringGraphQLDgsQueryExecutor(private val executionService: ExecutionGraphQlService, private val dgsContextBuilder: DefaultDgsGraphQLContextBuilder, private val dgsDataLoaderProvider: DgsDataLoaderProvider, private val requestCustomizer: DgsQueryExecutorRequestCustomizer = DgsQueryExecutorRequestCustomizer.DEFAULT_REQUEST_CUSTOMIZER) : DgsQueryExecutor { override fun execute( query: String, @@ -60,8 +58,8 @@ class SpringGraphQLDgsQueryExecutor(val executionService: ExecutionGraphQlServic val httpRequest = requestCustomizer.apply(webRequest ?: RequestContextHolder.getRequestAttributes() as? WebRequest, headers) val dgsContext = dgsContextBuilder.build(DgsWebMvcRequestData(request.extensions, headers, httpRequest)) - val graphQLContextFuture = CompletableFuture() - val dataLoaderRegistry = dgsDataLoaderProvider.buildRegistryWithContextSupplier { graphQLContextFuture.get() } + lateinit var graphQLContext: GraphQLContext + val dataLoaderRegistry = dgsDataLoaderProvider.buildRegistryWithContextSupplier { graphQLContext } request.configureExecutionInput { _, builder -> builder @@ -70,16 +68,11 @@ class SpringGraphQLDgsQueryExecutor(val executionService: ExecutionGraphQlServic .dataLoaderRegistry(dataLoaderRegistry).build() } - graphQLContextFuture.complete(request.toExecutionInput().graphQLContext) + graphQLContext = request.toExecutionInput().graphQLContext - val execute = executionService.execute( - request - ).block() ?: throw IllegalStateException("Unexpected null response from Spring GraphQL client") + val response = executionService.execute(request).block() ?: throw IllegalStateException("Unexpected null response from Spring GraphQL client") - return ExecutionResult.newExecutionResult() - .data(execute.getData()) - .errors(execute.errors.map { GraphQLError.newError().message(it.message).build() }) - .build() + return response.executionResult } override fun executeAndExtractJsonPath( diff --git a/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/SpringGraphQLDgsReactiveQueryExecutor.kt b/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/SpringGraphQLDgsReactiveQueryExecutor.kt index 96d7c3b9f..401d50bb6 100644 --- a/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/SpringGraphQLDgsReactiveQueryExecutor.kt +++ b/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/SpringGraphQLDgsReactiveQueryExecutor.kt @@ -29,17 +29,15 @@ import com.netflix.graphql.dgs.reactive.internal.DefaultDgsReactiveGraphQLContex import com.netflix.graphql.dgs.reactive.internal.DgsReactiveRequestData import graphql.ExecutionResult import graphql.GraphQLContext -import graphql.GraphQLError import org.intellij.lang.annotations.Language import org.springframework.graphql.ExecutionGraphQlService import org.springframework.graphql.support.DefaultExecutionGraphQlRequest import org.springframework.http.HttpHeaders import org.springframework.web.reactive.function.server.ServerRequest import reactor.core.publisher.Mono -import java.util.concurrent.CompletableFuture class SpringGraphQLDgsReactiveQueryExecutor( - val executionService: ExecutionGraphQlService, + private val executionService: ExecutionGraphQlService, private val dgsContextBuilder: DefaultDgsReactiveGraphQLContextBuilder, private val dgsDataLoaderProvider: DgsDataLoaderProvider ) : DgsReactiveQueryExecutor { @@ -49,7 +47,7 @@ class SpringGraphQLDgsReactiveQueryExecutor( extensions: Map?, headers: HttpHeaders?, operationName: String?, - serverRequest: org.springframework.web.reactive.function.server.ServerRequest? + serverRequest: ServerRequest? ): Mono { val request = DefaultExecutionGraphQlRequest( query, @@ -60,8 +58,8 @@ class SpringGraphQLDgsReactiveQueryExecutor( null ) - val graphQLContextFuture = CompletableFuture() - val dataLoaderRegistry = dgsDataLoaderProvider.buildRegistryWithContextSupplier { graphQLContextFuture.get() } + lateinit var graphQLContext: GraphQLContext + val dataLoaderRegistry = dgsDataLoaderProvider.buildRegistryWithContextSupplier { graphQLContext } return dgsContextBuilder.build(DgsReactiveRequestData(request.extensions, headers, serverRequest)) .flatMap { context -> request.configureExecutionInput { _, builder -> @@ -71,16 +69,13 @@ class SpringGraphQLDgsReactiveQueryExecutor( .dataLoaderRegistry(dataLoaderRegistry).build() } - graphQLContextFuture.complete(request.toExecutionInput().graphQLContext) + graphQLContext = request.toExecutionInput().graphQLContext executionService.execute( request - ) ?: throw IllegalStateException("Unexpected null response from Spring GraphQL client") - }.map { execute -> - ExecutionResult.newExecutionResult() - .data(execute.getData()) - .errors(execute.errors.map { GraphQLError.newError().message(it.message).build() }) - .build() + ) ?: Mono.error(IllegalStateException("Unexpected null response from Spring GraphQL client")) + }.map { response -> + response.executionResult } }