Do not skip DataFetcherFactories

Closes gh-440
This commit is contained in:
rstoyanchev
2022-09-09 07:16:47 +01:00
parent 471834782d
commit 65be8ed35f
2 changed files with 76 additions and 6 deletions

View File

@@ -109,14 +109,14 @@ final class ContextDataFetcherDecorator implements DataFetcher<Object> {
return new GraphQLTypeVisitorStub() {
@Override
public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition fieldDefinition,
TraverserContext<GraphQLSchemaElement> context) {
public TraversalControl visitGraphQLFieldDefinition(
GraphQLFieldDefinition fieldDefinition, TraverserContext<GraphQLSchemaElement> context) {
GraphQLCodeRegistry.Builder codeRegistry = context.getVarFromParents(GraphQLCodeRegistry.Builder.class);
GraphQLFieldsContainer parent = (GraphQLFieldsContainer) context.getParentNode();
DataFetcher<?> dataFetcher = codeRegistry.getDataFetcher(parent, fieldDefinition);
if (dataFetcher.getClass().getPackage().getName().startsWith("graphql.")) {
if (skipDataFetcher(dataFetcher)) {
return TraversalControl.CONTINUE;
}
@@ -125,6 +125,14 @@ final class ContextDataFetcherDecorator implements DataFetcher<Object> {
codeRegistry.dataFetcher(parent, fieldDefinition, dataFetcher);
return TraversalControl.CONTINUE;
}
private boolean skipDataFetcher(DataFetcher<?> dataFetcher) {
Class<?> type = dataFetcher.getClass();
if (type.getPackage().getName().startsWith("graphql.")) {
return !type.getSimpleName().startsWith("DataFetcherFactories");
}
return false;
}
};
}

View File

@@ -19,12 +19,19 @@ package org.springframework.graphql.execution;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import graphql.ExecutionInput;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.GraphQLError;
import graphql.GraphqlErrorBuilder;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetcherFactories;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.idl.SchemaDirectiveWiring;
import graphql.schema.idl.SchemaDirectiveWiringEnvironment;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -42,10 +49,18 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link ContextDataFetcherDecorator}.
* @author Rossen Stoyanchev
*/
@SuppressWarnings("ReactiveStreamsUnusedPublisher")
public class ContextDataFetcherDecoratorTests {
private static final String SCHEMA_CONTENT =
"type Query { greeting: String, greetings: [String] } type Subscription { greetings: String }";
private static final String SCHEMA_CONTENT = "" +
"directive @UpperCase on FIELD_DEFINITION " +
"type Query { " +
" greeting: String @UpperCase, " +
" greetings: [String] " +
"} " +
"type Subscription { " +
" greetings: String " +
"}";
@Test
@@ -112,7 +127,7 @@ public class ContextDataFetcherDecoratorTests {
}
@Test
void fluxDataFetcherSubscriptionThrowException() throws Exception {
void fluxDataFetcherSubscriptionThrowingException() throws Exception {
SubscriptionExceptionResolver resolver =
SubscriptionExceptionResolver.forSingleError(exception ->
@@ -177,4 +192,51 @@ public class ContextDataFetcherDecoratorTests {
}
}
@Test // gh-440
void dataFetcherDecoratedWithDataFetcherFactories() {
SchemaDirectiveWiring directiveWiring = new SchemaDirectiveWiring() {
@SuppressWarnings("unchecked")
@Override
public GraphQLFieldDefinition onField(SchemaDirectiveWiringEnvironment<GraphQLFieldDefinition> env) {
if (env.getDirective("UpperCase") != null) {
return env.setFieldDataFetcher(DataFetcherFactories.wrapDataFetcher(
env.getFieldDataFetcher(),
((dataFetchingEnv, value) -> {
if (value instanceof String) {
return ((String) value).toUpperCase();
}
else if (value instanceof Mono) {
return ((Mono<String>) value).map(String::toUpperCase);
}
else {
throw new IllegalArgumentException();
}
})));
}
else {
return env.getElement();
}
}
};
BiConsumer<SchemaDirectiveWiring, DataFetcher<?>> tester = (schemaDirectiveWiring, dataFetcher) -> {
GraphQL graphQl = GraphQlSetup.schemaContent(SCHEMA_CONTENT)
.queryFetcher("greeting", dataFetcher)
.runtimeWiring(builder -> builder.directiveWiring(directiveWiring))
.toGraphQl();
ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greeting }").build();
Mono<ExecutionResult> resultMono = Mono.fromFuture(graphQl.executeAsync(input));
String greeting = ResponseHelper.forResult(resultMono).toEntity("greeting", String.class);
assertThat(greeting).isEqualTo("HELLO");
};
tester.accept(directiveWiring, env -> CompletableFuture.completedFuture("hello"));
tester.accept(directiveWiring, env -> Mono.just("hello"));
}
}