From 388e3cb7755f91b7380972c3b16f5cd7e4cb2866 Mon Sep 17 00:00:00 2001 From: lorenzsimon Date: Thu, 23 Oct 2025 21:51:42 +0200 Subject: [PATCH 1/2] Add spring request context thread local accessor --- .../RequestContextHolderAccessor.kt | 39 +++++++++++++++++++ .../DgsSpringGraphQLAutoConfiguration.kt | 2 + 2 files changed, 41 insertions(+) create mode 100644 graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/RequestContextHolderAccessor.kt diff --git a/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/RequestContextHolderAccessor.kt b/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/RequestContextHolderAccessor.kt new file mode 100644 index 000000000..443ad1e85 --- /dev/null +++ b/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/RequestContextHolderAccessor.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2025 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.netflix.graphql.dgs.springgraphql + +import io.micrometer.context.ThreadLocalAccessor +import org.springframework.web.context.request.RequestAttributes +import org.springframework.web.context.request.RequestContextHolder + +internal class RequestContextHolderAccessor : ThreadLocalAccessor { + companion object { + private const val ACCESSOR_KEY = "dgs.spring.request-context" + } + + override fun key() = ACCESSOR_KEY + + override fun getValue(): RequestAttributes? = RequestContextHolder.getRequestAttributes() + + override fun setValue(value: RequestAttributes) { + RequestContextHolder.setRequestAttributes(value) + } + + override fun setValue() { + RequestContextHolder.resetRequestAttributes() + } +} diff --git a/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/autoconfig/DgsSpringGraphQLAutoConfiguration.kt b/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/autoconfig/DgsSpringGraphQLAutoConfiguration.kt index 1fa146070..e2d1551ea 100644 --- a/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/autoconfig/DgsSpringGraphQLAutoConfiguration.kt +++ b/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/autoconfig/DgsSpringGraphQLAutoConfiguration.kt @@ -63,6 +63,7 @@ import com.netflix.graphql.dgs.reactive.internal.DefaultDgsReactiveGraphQLContex import com.netflix.graphql.dgs.reactive.internal.method.SyncHandlerMethodArgumentResolverAdapter import com.netflix.graphql.dgs.springgraphql.DgsGraphQLSourceBuilder import com.netflix.graphql.dgs.springgraphql.ReloadableGraphQLSource +import com.netflix.graphql.dgs.springgraphql.RequestContextHolderAccessor import com.netflix.graphql.dgs.springgraphql.SpringGraphQLDgsQueryExecutor import com.netflix.graphql.dgs.springgraphql.SpringGraphQLDgsReactiveQueryExecutor import com.netflix.graphql.dgs.springgraphql.conditions.ConditionalOnDgsReload @@ -475,6 +476,7 @@ open class DgsSpringGraphQLAutoConfiguration( .loadContextAccessors() .loadThreadLocalAccessors() .registerThreadLocalAccessor(Slf4jThreadLocalAccessor()) + .registerThreadLocalAccessor(RequestContextHolderAccessor()) val executor = SimpleAsyncTaskExecutor("dgs-virtual-thread-") executor.setVirtualThreads(true) From f3026dc08df0fb3fecefdb4382f91eb1cb533aaa Mon Sep 17 00:00:00 2001 From: lorenzsimon Date: Fri, 24 Oct 2025 09:53:33 +0200 Subject: [PATCH 2/2] Use existing Spring RequestAttributesThreadLocalAccessor --- .../RequestContextHolderAccessor.kt | 39 ------------------- .../DgsSpringGraphQLAutoConfiguration.kt | 4 +- 2 files changed, 2 insertions(+), 41 deletions(-) delete mode 100644 graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/RequestContextHolderAccessor.kt diff --git a/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/RequestContextHolderAccessor.kt b/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/RequestContextHolderAccessor.kt deleted file mode 100644 index 443ad1e85..000000000 --- a/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/RequestContextHolderAccessor.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2025 Netflix, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.netflix.graphql.dgs.springgraphql - -import io.micrometer.context.ThreadLocalAccessor -import org.springframework.web.context.request.RequestAttributes -import org.springframework.web.context.request.RequestContextHolder - -internal class RequestContextHolderAccessor : ThreadLocalAccessor { - companion object { - private const val ACCESSOR_KEY = "dgs.spring.request-context" - } - - override fun key() = ACCESSOR_KEY - - override fun getValue(): RequestAttributes? = RequestContextHolder.getRequestAttributes() - - override fun setValue(value: RequestAttributes) { - RequestContextHolder.setRequestAttributes(value) - } - - override fun setValue() { - RequestContextHolder.resetRequestAttributes() - } -} diff --git a/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/autoconfig/DgsSpringGraphQLAutoConfiguration.kt b/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/autoconfig/DgsSpringGraphQLAutoConfiguration.kt index e2d1551ea..423632fd8 100644 --- a/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/autoconfig/DgsSpringGraphQLAutoConfiguration.kt +++ b/graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/autoconfig/DgsSpringGraphQLAutoConfiguration.kt @@ -63,7 +63,6 @@ import com.netflix.graphql.dgs.reactive.internal.DefaultDgsReactiveGraphQLContex import com.netflix.graphql.dgs.reactive.internal.method.SyncHandlerMethodArgumentResolverAdapter import com.netflix.graphql.dgs.springgraphql.DgsGraphQLSourceBuilder import com.netflix.graphql.dgs.springgraphql.ReloadableGraphQLSource -import com.netflix.graphql.dgs.springgraphql.RequestContextHolderAccessor import com.netflix.graphql.dgs.springgraphql.SpringGraphQLDgsQueryExecutor import com.netflix.graphql.dgs.springgraphql.SpringGraphQLDgsReactiveQueryExecutor import com.netflix.graphql.dgs.springgraphql.conditions.ConditionalOnDgsReload @@ -132,6 +131,7 @@ import org.springframework.http.HttpHeaders import org.springframework.mock.web.MockHttpServletRequest import org.springframework.web.bind.support.WebDataBinderFactory import org.springframework.web.context.request.NativeWebRequest +import org.springframework.web.context.request.RequestAttributesThreadLocalAccessor import org.springframework.web.context.request.WebRequest import org.springframework.web.filter.reactive.ServerWebExchangeContextFilter import org.springframework.web.method.annotation.RequestHeaderMapMethodArgumentResolver @@ -476,7 +476,7 @@ open class DgsSpringGraphQLAutoConfiguration( .loadContextAccessors() .loadThreadLocalAccessors() .registerThreadLocalAccessor(Slf4jThreadLocalAccessor()) - .registerThreadLocalAccessor(RequestContextHolderAccessor()) + .registerThreadLocalAccessor(RequestAttributesThreadLocalAccessor()) val executor = SimpleAsyncTaskExecutor("dgs-virtual-thread-") executor.setVirtualThreads(true)