Remove Context Propagation deprecated API usage

Prior to this commit, gh-676 fixed the local and global context
inheritance in the `ContextDataFetcherDecorator` with a workaround.
This commit undoes this workaround and uses the new Context Propagation
API for this, effectively raising the requirement for version 1.0.3 and
removing all deprecated APIs in the meantime.

Closes gh-688
This commit is contained in:
Brian Clozel
2024-02-13 21:25:32 +01:00
parent 610898c4c3
commit 98d39bc21d
10 changed files with 99 additions and 42 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ import java.util.concurrent.Executor;
import graphql.GraphQLContext;
import io.micrometer.context.ContextSnapshot;
import io.micrometer.context.ContextSnapshotFactory;
import reactor.core.publisher.Mono;
import org.springframework.core.CoroutinesUtils;
@@ -45,6 +46,8 @@ public abstract class InvocableHandlerMethodSupport extends HandlerMethod {
private static final Object NO_VALUE = new Object();
private static final ContextSnapshotFactory SNAPSHOT_FACTORY = ContextSnapshotFactory.builder().build();
private final boolean hasCallableReturnValue;
@@ -122,13 +125,12 @@ public abstract class InvocableHandlerMethodSupport extends HandlerMethod {
}
@Nullable
@SuppressWarnings("deprecation")
private Object handleReturnValue(GraphQLContext graphQLContext, @Nullable Object result) {
if (this.hasCallableReturnValue && result != null) {
return CompletableFuture.supplyAsync(
() -> {
try {
return ContextSnapshot.captureFrom(graphQLContext).wrap((Callable<?>) result).call();
return SNAPSHOT_FACTORY.captureFrom(graphQLContext).wrap((Callable<?>) result).call();
}
catch (Exception ex) {
throw new IllegalStateException(

View File

@@ -32,6 +32,7 @@ import graphql.schema.GraphQLTypeVisitorStub;
import graphql.util.TraversalControl;
import graphql.util.TraverserContext;
import io.micrometer.context.ContextSnapshot;
import io.micrometer.context.ContextSnapshotFactory;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -58,6 +59,8 @@ final class ContextDataFetcherDecorator implements DataFetcher<Object> {
private final SubscriptionExceptionResolver subscriptionExceptionResolver;
private final ContextSnapshotFactory snapshotFactory = ContextSnapshotFactory.builder().build();
private ContextDataFetcherDecorator(
DataFetcher<?> delegate, boolean subscription,
SubscriptionExceptionResolver subscriptionExceptionResolver) {
@@ -70,21 +73,15 @@ final class ContextDataFetcherDecorator implements DataFetcher<Object> {
}
@Override
@SuppressWarnings("deprecation")
public Object get(DataFetchingEnvironment environment) throws Exception {
GraphQLContext context;
// temporarily merge global and local graphql context until https://github.com/micrometer-metrics/context-propagation/pull/98
ContextSnapshot snapshot;
if (environment.getLocalContext() instanceof GraphQLContext localContext) {
context = GraphQLContext.newContext()
.of(environment.getGraphQlContext())
.of(localContext)
.build();
snapshot = snapshotFactory.captureFrom(environment.getGraphQlContext(), localContext);
}
else {
context = environment.getGraphQlContext();
snapshot = snapshotFactory.captureFrom(environment.getGraphQlContext());
}
ContextSnapshot snapshot = ContextSnapshot.captureFrom(context);
Object value = snapshot.wrap(() -> this.delegate.get(environment)).call();
if (this.subscription) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@ import java.util.function.BiFunction;
import graphql.GraphQLError;
import graphql.schema.DataFetchingEnvironment;
import io.micrometer.context.ContextSnapshot;
import io.micrometer.context.ContextSnapshotFactory;
import io.micrometer.context.ThreadLocalAccessor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -52,6 +52,8 @@ public abstract class DataFetcherExceptionResolverAdapter implements DataFetcher
protected final Log logger = LogFactory.getLog(getClass());
protected final ContextSnapshotFactory snapshotFactory = ContextSnapshotFactory.builder().build();
private boolean threadLocalContextAware;
@@ -93,13 +95,12 @@ public abstract class DataFetcherExceptionResolverAdapter implements DataFetcher
}
@Nullable
@SuppressWarnings("deprecation")
private List<GraphQLError> resolveInternal(Throwable exception, DataFetchingEnvironment env) {
if (!this.threadLocalContextAware) {
return resolveToMultipleErrors(exception, env);
}
try {
return ContextSnapshot.captureFrom(env.getGraphQlContext())
return snapshotFactory.captureFrom(env.getGraphQlContext())
.wrap(() -> resolveToMultipleErrors(exception, env))
.call();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ import java.util.function.Supplier;
import graphql.GraphQLContext;
import io.micrometer.context.ContextSnapshot;
import io.micrometer.context.ContextSnapshotFactory;
import org.dataloader.BatchLoaderContextProvider;
import org.dataloader.BatchLoaderEnvironment;
import org.dataloader.BatchLoaderWithContext;
@@ -52,6 +53,8 @@ import org.springframework.util.StringUtils;
*/
public class DefaultBatchLoaderRegistry implements BatchLoaderRegistry {
private static final ContextSnapshotFactory SNAPSHOT_FACTORY = ContextSnapshotFactory.builder().build();
private final List<ReactorBatchLoader<?,?>> loaders = new ArrayList<>();
private final List<ReactorMappedBatchLoader<?,?>> mappedLoaders = new ArrayList<>();
@@ -59,6 +62,7 @@ public class DefaultBatchLoaderRegistry implements BatchLoaderRegistry {
private final Supplier<DataLoaderOptions> defaultOptionsSupplier;
/**
* Default constructor.
*/
@@ -223,10 +227,9 @@ public class DefaultBatchLoaderRegistry implements BatchLoaderRegistry {
}
@Override
@SuppressWarnings("deprecation")
public CompletionStage<List<V>> load(List<K> keys, BatchLoaderEnvironment environment) {
GraphQLContext graphQLContext = environment.getContext();
ContextSnapshot snapshot = ContextSnapshot.captureFrom(graphQLContext);
ContextSnapshot snapshot = SNAPSHOT_FACTORY.captureFrom(graphQLContext);
try {
return snapshot.wrap(() ->
this.loader.apply(keys, environment)
@@ -272,10 +275,9 @@ public class DefaultBatchLoaderRegistry implements BatchLoaderRegistry {
}
@Override
@SuppressWarnings("deprecation")
public CompletionStage<Map<K, V>> load(Set<K> keys, BatchLoaderEnvironment environment) {
GraphQLContext graphQLContext = environment.getContext();
ContextSnapshot snapshot = ContextSnapshot.captureFrom(graphQLContext);
ContextSnapshot snapshot = SNAPSHOT_FACTORY.captureFrom(graphQLContext);
try {
return snapshot.wrap(() ->
this.loader.apply(keys, environment)

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@ import graphql.GraphQL;
import graphql.GraphQLContext;
import graphql.execution.ExecutionIdProvider;
import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentationState;
import io.micrometer.context.ContextSnapshot;
import io.micrometer.context.ContextSnapshotFactory;
import org.dataloader.DataLoaderRegistry;
import reactor.core.publisher.Mono;
@@ -46,6 +46,7 @@ public class DefaultExecutionGraphQlService implements ExecutionGraphQlService {
private static final BiFunction<ExecutionInput, ExecutionInput.Builder, ExecutionInput> RESET_EXECUTION_ID_CONFIGURER =
(executionInput, builder) -> builder.executionId(null).build();
private final ContextSnapshotFactory snapshotFactory = ContextSnapshotFactory.builder().build();
private final GraphQlSource graphQlSource;
@@ -72,14 +73,13 @@ public class DefaultExecutionGraphQlService implements ExecutionGraphQlService {
@Override
@SuppressWarnings("deprecation")
public final Mono<ExecutionGraphQlResponse> execute(ExecutionGraphQlRequest request) {
return Mono.deferContextual((contextView) -> {
if (!this.isDefaultExecutionIdProvider && request.getExecutionId() == null) {
request.configureExecutionInput(RESET_EXECUTION_ID_CONFIGURER);
}
ExecutionInput executionInput = request.toExecutionInput();
ContextSnapshot.captureFrom(contextView).updateContext(executionInput.getGraphQLContext());
snapshotFactory.captureFrom(contextView).updateContext(executionInput.getGraphQLContext());
ExecutionInput updatedExecutionInput = registerDataLoaders(executionInput);
return Mono.fromFuture(this.graphQlSource.graphQl().executeAsync(updatedExecutionInput))
.map(result -> new DefaultExecutionGraphQlResponse(updatedExecutionInput, result));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@ import graphql.execution.DataFetcherExceptionHandlerResult;
import graphql.execution.ExecutionId;
import graphql.schema.DataFetchingEnvironment;
import io.micrometer.context.ContextSnapshot;
import io.micrometer.context.ContextSnapshotFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Flux;
@@ -47,6 +48,8 @@ class ExceptionResolversExceptionHandler implements DataFetcherExceptionHandler
private static final Log logger = LogFactory.getLog(ExceptionResolversExceptionHandler.class);
private final ContextSnapshotFactory snapshotFactory = ContextSnapshotFactory.builder().build();
private final List<DataFetcherExceptionResolver> resolvers;
/**
@@ -60,11 +63,10 @@ class ExceptionResolversExceptionHandler implements DataFetcherExceptionHandler
@Override
@SuppressWarnings("deprecation")
public CompletableFuture<DataFetcherExceptionHandlerResult> handleException(DataFetcherExceptionHandlerParameters params) {
Throwable exception = unwrapException(params);
DataFetchingEnvironment env = params.getDataFetchingEnvironment();
ContextSnapshot snapshot = ContextSnapshot.captureFrom(env.getGraphQlContext());
ContextSnapshot snapshot = snapshotFactory.captureFrom(env.getGraphQlContext());
try {
return Flux.fromIterable(this.resolvers)
.flatMap(resolver -> resolver.resolveException(exception, env))

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -72,13 +72,31 @@ public class SecurityContextThreadLocalAccessor implements ThreadLocalAccessor<O
}
@Override
@SuppressWarnings("deprecation")
public void setValue() {
this.delegate.setValue();
}
@Override
@Deprecated
public void reset() {
this.delegate.reset();
}
@SuppressWarnings("deprecation")
@Override
public void restore(Object previousValue) {
restoreInternal(previousValue);
}
@SuppressWarnings("unchecked")
public <V> void restoreInternal(Object previousValue) {
((ThreadLocalAccessor<V>) this.delegate).restore((V) previousValue);
}
@Override
public void restore() {
this.delegate.restore();
}
private static class DelegateAccessor implements ThreadLocalAccessor<Object> {
@Override
@@ -97,6 +115,22 @@ public class SecurityContextThreadLocalAccessor implements ThreadLocalAccessor<O
}
@Override
public void setValue() {
SecurityContextHolder.clearContext();
}
@Override
public void restore(Object previousValue) {
SecurityContextHolder.setContext((SecurityContext) previousValue);
}
@Override
public void restore() {
SecurityContextHolder.clearContext();
}
@Override
@Deprecated
public void reset() {
SecurityContextHolder.clearContext();
}
@@ -104,7 +138,6 @@ public class SecurityContextThreadLocalAccessor implements ThreadLocalAccessor<O
}
@SuppressWarnings("deprecation")
private static class NoOpAccessor implements ThreadLocalAccessor<Object> {
@Override
@@ -122,6 +155,19 @@ public class SecurityContextThreadLocalAccessor implements ThreadLocalAccessor<O
}
@Override
public void setValue() {
}
@Override
public void restore(Object previousValue) {
}
@Override
public void restore() {
}
@Override
@Deprecated
public void reset() {
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import java.util.function.Function;
import graphql.GraphQLError;
import io.micrometer.context.ContextSnapshot;
import io.micrometer.context.ContextSnapshotFactory;
import io.micrometer.context.ThreadLocalAccessor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -50,6 +51,8 @@ public abstract class SubscriptionExceptionResolverAdapter implements Subscripti
protected final Log logger = LogFactory.getLog(getClass());
protected final ContextSnapshotFactory snapshotFactory = ContextSnapshotFactory.builder().build();
private boolean threadLocalContextAware;
@@ -78,12 +81,12 @@ public abstract class SubscriptionExceptionResolverAdapter implements Subscripti
}
@SuppressWarnings({"unused", "try", "deprecation"})
@SuppressWarnings({"unused", "try"})
@Override
public final Mono<List<GraphQLError>> resolveException(Throwable exception) {
if (this.threadLocalContextAware) {
return Mono.deferContextual(contextView -> {
ContextSnapshot snapshot = ContextSnapshot.captureFrom(contextView);
ContextSnapshot snapshot = snapshotFactory.captureFrom(contextView);
try {
List<GraphQLError> errors = snapshot.wrap(() -> resolveToMultipleErrors(exception)).call();
return Mono.justOrEmpty(errors);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import java.util.Arrays;
import java.util.List;
import io.micrometer.context.ContextSnapshot;
import io.micrometer.context.ContextSnapshotFactory;
import reactor.core.publisher.Mono;
import org.springframework.graphql.ExecutionGraphQlService;
@@ -70,6 +71,8 @@ class DefaultWebGraphQlHandlerBuilder implements WebGraphQlHandler.Builder {
@Override
public WebGraphQlHandler build() {
ContextSnapshotFactory snapshotFactory = ContextSnapshotFactory.builder().build();
Chain endOfChain = request -> this.service.execute(request).map(WebGraphQlResponse::new);
Chain executionChain = this.interceptors.stream()
@@ -86,9 +89,8 @@ class DefaultWebGraphQlHandlerBuilder implements WebGraphQlHandler.Builder {
}
@Override
@SuppressWarnings("deprecation")
public Mono<WebGraphQlResponse> handleRequest(WebGraphQlRequest request) {
ContextSnapshot snapshot = ContextSnapshot.captureAll();
ContextSnapshot snapshot = snapshotFactory.captureAll();
return executionChain.next(request).contextWrite(snapshot::updateContext);
}
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import graphql.ExecutionResult;
import graphql.GraphQLError;
import graphql.GraphqlErrorBuilder;
import io.micrometer.context.ContextSnapshot;
import io.micrometer.context.ContextSnapshotFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.reactivestreams.Publisher;
@@ -357,13 +358,14 @@ public class GraphQlWebSocketHandler extends TextWebSocketHandler implements Sub
private static final String KEY = ContextSnapshot.class.getName();
private static final ContextSnapshotFactory SNAPSHOT_FACTORY = ContextSnapshotFactory.builder().build();
@Override
@SuppressWarnings("deprecation")
public boolean beforeHandshake(
ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) {
attributes.put(KEY, ContextSnapshot.captureAll());
attributes.put(KEY, SNAPSHOT_FACTORY.captureAll());
return true;
}