Skip to content

Commit 65be8ed

Browse files
committed
Do not skip DataFetcherFactories
Closes gh-440
1 parent 4718347 commit 65be8ed

File tree

2 files changed

+76
-6
lines changed

2 files changed

+76
-6
lines changed

spring-graphql/src/main/java/org/springframework/graphql/execution/ContextDataFetcherDecorator.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,14 @@ static GraphQLTypeVisitor createVisitor(List<SubscriptionExceptionResolver> reso
109109

110110
return new GraphQLTypeVisitorStub() {
111111
@Override
112-
public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition fieldDefinition,
113-
TraverserContext<GraphQLSchemaElement> context) {
112+
public TraversalControl visitGraphQLFieldDefinition(
113+
GraphQLFieldDefinition fieldDefinition, TraverserContext<GraphQLSchemaElement> context) {
114114

115115
GraphQLCodeRegistry.Builder codeRegistry = context.getVarFromParents(GraphQLCodeRegistry.Builder.class);
116116
GraphQLFieldsContainer parent = (GraphQLFieldsContainer) context.getParentNode();
117117
DataFetcher<?> dataFetcher = codeRegistry.getDataFetcher(parent, fieldDefinition);
118118

119-
if (dataFetcher.getClass().getPackage().getName().startsWith("graphql.")) {
119+
if (skipDataFetcher(dataFetcher)) {
120120
return TraversalControl.CONTINUE;
121121
}
122122

@@ -125,6 +125,14 @@ public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition field
125125
codeRegistry.dataFetcher(parent, fieldDefinition, dataFetcher);
126126
return TraversalControl.CONTINUE;
127127
}
128+
129+
private boolean skipDataFetcher(DataFetcher<?> dataFetcher) {
130+
Class<?> type = dataFetcher.getClass();
131+
if (type.getPackage().getName().startsWith("graphql.")) {
132+
return !type.getSimpleName().startsWith("DataFetcherFactories");
133+
}
134+
return false;
135+
}
128136
};
129137
}
130138

spring-graphql/src/test/java/org/springframework/graphql/execution/ContextDataFetcherDecoratorTests.java

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,19 @@
1919
import java.time.Duration;
2020
import java.util.Collections;
2121
import java.util.List;
22+
import java.util.concurrent.CompletableFuture;
23+
import java.util.function.BiConsumer;
2224

2325
import graphql.ExecutionInput;
2426
import graphql.ExecutionResult;
2527
import graphql.GraphQL;
2628
import graphql.GraphQLError;
2729
import graphql.GraphqlErrorBuilder;
30+
import graphql.schema.DataFetcher;
31+
import graphql.schema.DataFetcherFactories;
32+
import graphql.schema.GraphQLFieldDefinition;
33+
import graphql.schema.idl.SchemaDirectiveWiring;
34+
import graphql.schema.idl.SchemaDirectiveWiringEnvironment;
2835
import org.junit.jupiter.api.Test;
2936
import reactor.core.publisher.Flux;
3037
import reactor.core.publisher.Mono;
@@ -42,10 +49,18 @@
4249
* Tests for {@link ContextDataFetcherDecorator}.
4350
* @author Rossen Stoyanchev
4451
*/
52+
@SuppressWarnings("ReactiveStreamsUnusedPublisher")
4553
public class ContextDataFetcherDecoratorTests {
4654

47-
private static final String SCHEMA_CONTENT =
48-
"type Query { greeting: String, greetings: [String] } type Subscription { greetings: String }";
55+
private static final String SCHEMA_CONTENT = "" +
56+
"directive @UpperCase on FIELD_DEFINITION " +
57+
"type Query { " +
58+
" greeting: String @UpperCase, " +
59+
" greetings: [String] " +
60+
"} " +
61+
"type Subscription { " +
62+
" greetings: String " +
63+
"}";
4964

5065

5166
@Test
@@ -112,7 +127,7 @@ void fluxDataFetcherSubscription() throws Exception {
112127
}
113128

114129
@Test
115-
void fluxDataFetcherSubscriptionThrowException() throws Exception {
130+
void fluxDataFetcherSubscriptionThrowingException() throws Exception {
116131

117132
SubscriptionExceptionResolver resolver =
118133
SubscriptionExceptionResolver.forSingleError(exception ->
@@ -177,4 +192,51 @@ void dataFetcherWithThreadLocalContext() {
177192
}
178193
}
179194

195+
@Test // gh-440
196+
void dataFetcherDecoratedWithDataFetcherFactories() {
197+
198+
SchemaDirectiveWiring directiveWiring = new SchemaDirectiveWiring() {
199+
200+
@SuppressWarnings("unchecked")
201+
@Override
202+
public GraphQLFieldDefinition onField(SchemaDirectiveWiringEnvironment<GraphQLFieldDefinition> env) {
203+
if (env.getDirective("UpperCase") != null) {
204+
return env.setFieldDataFetcher(DataFetcherFactories.wrapDataFetcher(
205+
env.getFieldDataFetcher(),
206+
((dataFetchingEnv, value) -> {
207+
if (value instanceof String) {
208+
return ((String) value).toUpperCase();
209+
}
210+
else if (value instanceof Mono) {
211+
return ((Mono<String>) value).map(String::toUpperCase);
212+
}
213+
else {
214+
throw new IllegalArgumentException();
215+
}
216+
})));
217+
}
218+
else {
219+
return env.getElement();
220+
}
221+
}
222+
};
223+
224+
BiConsumer<SchemaDirectiveWiring, DataFetcher<?>> tester = (schemaDirectiveWiring, dataFetcher) -> {
225+
226+
GraphQL graphQl = GraphQlSetup.schemaContent(SCHEMA_CONTENT)
227+
.queryFetcher("greeting", dataFetcher)
228+
.runtimeWiring(builder -> builder.directiveWiring(directiveWiring))
229+
.toGraphQl();
230+
231+
ExecutionInput input = ExecutionInput.newExecutionInput().query("{ greeting }").build();
232+
Mono<ExecutionResult> resultMono = Mono.fromFuture(graphQl.executeAsync(input));
233+
234+
String greeting = ResponseHelper.forResult(resultMono).toEntity("greeting", String.class);
235+
assertThat(greeting).isEqualTo("HELLO");
236+
};
237+
238+
tester.accept(directiveWiring, env -> CompletableFuture.completedFuture("hello"));
239+
tester.accept(directiveWiring, env -> Mono.just("hello"));
240+
}
241+
180242
}

0 commit comments

Comments
 (0)