diff --git a/spring-graphql/src/main/java/org/springframework/graphql/execution/ContextDataFetcherDecorator.java b/spring-graphql/src/main/java/org/springframework/graphql/execution/ContextDataFetcherDecorator.java index 90906458..4d53dc9f 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/execution/ContextDataFetcherDecorator.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/execution/ContextDataFetcherDecorator.java @@ -59,15 +59,15 @@ final class ContextDataFetcherDecorator implements DataFetcher { @Override public Object get(DataFetchingEnvironment environment) throws Exception { - ContextView contextView = ContextManager.getReactorContext(environment); + ContextView contextView = ReactorContextManager.getReactorContext(environment); Object value; try { - ContextManager.restoreThreadLocalValues(contextView); + ReactorContextManager.restoreThreadLocalValues(contextView); value = this.delegate.get(environment); } finally { - ContextManager.resetThreadLocalValues(contextView); + ReactorContextManager.resetThreadLocalValues(contextView); } if (this.subscription) { diff --git a/spring-graphql/src/main/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandler.java b/spring-graphql/src/main/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandler.java index c7d263ae..4a1dd645 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandler.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandler.java @@ -37,7 +37,7 @@ import org.springframework.web.client.ExtractingResponseErrorHandler; /** * {@link DataFetcherExceptionHandler} that invokes {@link DataFetcherExceptionResolver}'s - * in a sequence until one returns a non-null list of {@link GraphQLError}'s. + * in a sequence until one returns a list of {@link GraphQLError}'s. * * @author Rossen Stoyanchev */ @@ -75,7 +75,7 @@ class ExceptionResolversExceptionHandler implements DataFetcherExceptionHandler .map((errors) -> DataFetcherExceptionHandlerResult.newResult().errors(errors).build()) .switchIfEmpty(Mono.fromCallable(() -> applyDefaultHandling(ex, env))) .contextWrite((context) -> { - ContextView contextView = ContextManager.getReactorContext(env); + ContextView contextView = ReactorContextManager.getReactorContext(env); return (contextView.isEmpty() ? context : context.putAll(contextView)); }) .toFuture() @@ -92,13 +92,13 @@ class ExceptionResolversExceptionHandler implements DataFetcherExceptionHandler private Mono> resolveErrors( Throwable ex, DataFetchingEnvironment environment, DataFetcherExceptionResolver resolver) { - ContextView contextView = ContextManager.getReactorContext(environment); + ContextView contextView = ReactorContextManager.getReactorContext(environment); try { - ContextManager.restoreThreadLocalValues(contextView); + ReactorContextManager.restoreThreadLocalValues(contextView); return resolver.resolveException(ex, environment); } finally { - ContextManager.resetThreadLocalValues(contextView); + ReactorContextManager.resetThreadLocalValues(contextView); } } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/execution/ExecutionGraphQlService.java b/spring-graphql/src/main/java/org/springframework/graphql/execution/ExecutionGraphQlService.java index 871acc65..9d5636dd 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/execution/ExecutionGraphQlService.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/execution/ExecutionGraphQlService.java @@ -25,8 +25,8 @@ import org.springframework.graphql.GraphQlService; import org.springframework.graphql.RequestInput; /** - * Implementation of {@link GraphQlService} that performs GraphQL request execution - * through {@link GraphQL#executeAsync(ExecutionInput)}. + * {@link GraphQlService} that uses a {@link GraphQlSource} to obtain a + * {@link GraphQL} instance and perform query execution. * * @author Rossen Stoyanchev * @since 1.0.0 @@ -44,7 +44,7 @@ public class ExecutionGraphQlService implements GraphQlService { ExecutionInput executionInput = input.toExecutionInput(); GraphQL graphQl = this.graphQlSource.graphQl(); return Mono.deferContextual((contextView) -> { - ContextManager.setReactorContext(contextView, executionInput); + ReactorContextManager.setReactorContext(contextView, executionInput); return Mono.fromFuture(graphQl.executeAsync(executionInput)); }); } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/execution/ContextManager.java b/spring-graphql/src/main/java/org/springframework/graphql/execution/ReactorContextManager.java similarity index 82% rename from spring-graphql/src/main/java/org/springframework/graphql/execution/ContextManager.java rename to spring-graphql/src/main/java/org/springframework/graphql/execution/ReactorContextManager.java index 52bdd856..10e8efbf 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/execution/ContextManager.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/execution/ReactorContextManager.java @@ -28,21 +28,25 @@ import reactor.util.context.ContextView; import org.springframework.lang.Nullable; /** - * Package private utility class for propagating a Reactor {@link ContextView} through the - * {@link ExecutionInput} and the {@link DataFetchingEnvironment} of a request. + * Provides helper methods to save Reactor context in the {@link ExecutionInput} + * so it can be subsequently obtained from {@link DataFetchingEnvironment} and + * propagated to data fetchers or exception handlers. + * + *

The Reactor context is also used to carry ThreadLocal values that are also + * restored around the execution of data fetchers and exceptions handlers. * * @author Rossen Stoyanchev * @since 1.0.0 */ -public abstract class ContextManager { +public abstract class ReactorContextManager { - private static final String CONTEXT_VIEW_KEY = ContextManager.class.getName() + ".CONTEXT_VIEW"; + private static final String CONTEXT_VIEW_KEY = ReactorContextManager.class.getName() + ".CONTEXT_VIEW"; - private static final String THREAD_ID = ContextManager.class.getName() + ".THREAD_ID"; + private static final String THREAD_ID = ReactorContextManager.class.getName() + ".THREAD_ID"; - private static final String THREAD_LOCAL_VALUES_KEY = ContextManager.class.getName() + ".THREAD_VALUES_ACCESSOR"; + private static final String THREAD_LOCAL_VALUES_KEY = ReactorContextManager.class.getName() + ".THREAD_VALUES_ACCESSOR"; - private static final String THREAD_LOCAL_ACCESSOR_KEY = ContextManager.class.getName() + ".THREAD_LOCAL_ACCESSOR"; + private static final String THREAD_LOCAL_ACCESSOR_KEY = ReactorContextManager.class.getName() + ".THREAD_LOCAL_ACCESSOR"; /** * Save the given Reactor {@link ContextView} in the an {@link ExecutionInput} for diff --git a/spring-graphql/src/main/java/org/springframework/graphql/web/DefaultWebGraphQlHandlerBuilder.java b/spring-graphql/src/main/java/org/springframework/graphql/web/DefaultWebGraphQlHandlerBuilder.java index 0ba2c808..e53a14d4 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/web/DefaultWebGraphQlHandlerBuilder.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/web/DefaultWebGraphQlHandlerBuilder.java @@ -24,7 +24,7 @@ import java.util.List; import reactor.core.publisher.Mono; import org.springframework.graphql.GraphQlService; -import org.springframework.graphql.execution.ContextManager; +import org.springframework.graphql.execution.ReactorContextManager; import org.springframework.graphql.execution.ThreadLocalAccessor; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -115,7 +115,7 @@ class DefaultWebGraphQlHandlerBuilder implements WebGraphQlHandler.Builder { @Override public Mono handle(WebInput input) { return this.delegate.handle(input).contextWrite((context) -> - ContextManager.extractThreadLocalValues(this.accessor, context)); + ReactorContextManager.extractThreadLocalValues(this.accessor, context)); } } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/execution/ContextDataFetcherDecoratorTests.java b/spring-graphql/src/test/java/org/springframework/graphql/execution/ContextDataFetcherDecoratorTests.java index 005e54c0..b3cd633f 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/execution/ContextDataFetcherDecoratorTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/execution/ContextDataFetcherDecoratorTests.java @@ -51,7 +51,7 @@ public class ContextDataFetcherDecoratorTests { })); ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greeting }").build(); - ContextManager.setReactorContext(Context.of("name", "007"), input); + ReactorContextManager.setReactorContext(Context.of("name", "007"), input); Map data = graphQl.executeAsync(input).get().getData(); @@ -67,7 +67,7 @@ public class ContextDataFetcherDecoratorTests { }))); ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greetings }").build(); - ContextManager.setReactorContext(Context.of("name", "007"), input); + ReactorContextManager.setReactorContext(Context.of("name", "007"), input); Map data = graphQl.executeAsync(input).get().getData(); @@ -85,7 +85,7 @@ public class ContextDataFetcherDecoratorTests { }))); ExecutionInput input = ExecutionInput.newExecutionInput().query("subscription { greetings }").build(); - ContextManager.setReactorContext(Context.of("name", "007"), input); + ReactorContextManager.setReactorContext(Context.of("name", "007"), input); Publisher publisher = graphQl.executeAsync(input).get().getData(); @@ -109,8 +109,8 @@ public class ContextDataFetcherDecoratorTests { (env) -> "Hello " + nameThreadLocal.get()); ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greeting }").build(); - ContextView view = ContextManager.extractThreadLocalValues(accessor, Context.empty()); - ContextManager.setReactorContext(view, input); + ContextView view = ReactorContextManager.extractThreadLocalValues(accessor, Context.empty()); + ReactorContextManager.setReactorContext(view, input); ExecutionResult result = Mono.delay(Duration.ofMillis(10)) .flatMap((aLong) -> Mono.fromFuture(graphQl.executeAsync(input))) diff --git a/spring-graphql/src/test/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandlerTests.java b/spring-graphql/src/test/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandlerTests.java index 3623f313..1b693859 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandlerTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/execution/ExceptionResolversExceptionHandlerTests.java @@ -78,7 +78,7 @@ public class ExceptionResolversExceptionHandlerTests { .errorType(ErrorType.BAD_REQUEST).build())))); ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greeting }").build(); - ContextManager.setReactorContext(Context.of("name", "007"), input); + ReactorContextManager.setReactorContext(Context.of("name", "007"), input); ExecutionResult result = graphQl.executeAsync(input).get(); @@ -103,8 +103,8 @@ public class ExceptionResolversExceptionHandlerTests { .build())); ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greeting }").build(); - ContextView view = ContextManager.extractThreadLocalValues(accessor, Context.empty()); - ContextManager.setReactorContext(view, input); + ContextView view = ReactorContextManager.extractThreadLocalValues(accessor, Context.empty()); + ReactorContextManager.setReactorContext(view, input); ExecutionResult result = Mono.delay(Duration.ofMillis(10)) .flatMap((aLong) -> Mono.fromFuture(graphQl.executeAsync(input))) diff --git a/spring-graphql/src/test/java/org/springframework/graphql/execution/ContextManagerTests.java b/spring-graphql/src/test/java/org/springframework/graphql/execution/ReactorContextManagerTests.java similarity index 79% rename from spring-graphql/src/test/java/org/springframework/graphql/execution/ContextManagerTests.java rename to spring-graphql/src/test/java/org/springframework/graphql/execution/ReactorContextManagerTests.java index d3035730..dbea7df7 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/execution/ContextManagerTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/execution/ReactorContextManagerTests.java @@ -26,25 +26,25 @@ import org.springframework.graphql.TestThreadLocalAccessor; import static org.assertj.core.api.Assertions.assertThat; /** - * Unit tests for {@link ContextManager}. + * Unit tests for {@link ReactorContextManager}. * @author Rossen Stoyanchev */ -public class ContextManagerTests { +public class ReactorContextManagerTests { @Test void restoreThreadLocaValues() { ThreadLocal threadLocal = new ThreadLocal<>(); threadLocal.set("myValue"); - Context context = ContextManager.extractThreadLocalValues( + Context context = ReactorContextManager.extractThreadLocalValues( new TestThreadLocalAccessor<>(threadLocal), Context.empty()); try { Mono.delay(Duration.ofMillis(10)) .doOnNext(aLong -> { assertThat(threadLocal.get()).isNull(); - ContextManager.restoreThreadLocalValues(context); + ReactorContextManager.restoreThreadLocalValues(context); assertThat(threadLocal.get()).isEqualTo("myValue"); - ContextManager.resetThreadLocalValues(context); + ReactorContextManager.resetThreadLocalValues(context); }) .block(); } @@ -58,15 +58,15 @@ public class ContextManagerTests { ThreadLocal threadLocal = new ThreadLocal<>(); threadLocal.set("myValue"); - Context context = ContextManager.extractThreadLocalValues( + Context context = ReactorContextManager.extractThreadLocalValues( new TestThreadLocalAccessor<>(threadLocal, true), Context.empty()); threadLocal.remove(); - ContextManager.restoreThreadLocalValues(context); + ReactorContextManager.restoreThreadLocalValues(context); assertThat(threadLocal.get()).isNull(); threadLocal.set("anotherValue"); - ContextManager.resetThreadLocalValues(context); + ReactorContextManager.resetThreadLocalValues(context); assertThat(threadLocal.get()).isEqualTo("anotherValue"); }