Skip to content

Commit 84f426a

Browse files
danielocampo2bbakerman
authored andcommitted
Add support for args for DataFetcher declared in method (#86)
* Add support for arguments for DataFetcher when GraphQLField is declared as method. * Use direct imports. * Formatting
1 parent 6bcb638 commit 84f426a

File tree

2 files changed

+93
-20
lines changed

2 files changed

+93
-20
lines changed

src/main/java/graphql/annotations/GraphQLAnnotations.java

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ public GraphQLInterfaceType.Builder getIfaceBuilder(Class<?> iface) throws Graph
188188
return builder;
189189
}
190190

191-
192191
public static GraphQLInterfaceType.Builder ifaceBuilder(Class<?> iface) throws GraphQLAnnotationsException,
193192
IllegalAccessException {
194193
return getInstance().getIfaceBuilder(iface);
@@ -410,22 +409,7 @@ protected GraphQLFieldDefinition getField(Field field) throws GraphQLAnnotations
410409
GraphQLDataFetcher dataFetcher = field.getAnnotation(GraphQLDataFetcher.class);
411410
DataFetcher actualDataFetcher = null;
412411
if (nonNull(dataFetcher)) {
413-
final String[] args;
414-
if (dataFetcher.firstArgIsTargetName()) {
415-
args = Stream.concat(Stream.of(field.getName()), stream(dataFetcher.args())).toArray(String[]::new);
416-
} else {
417-
args = dataFetcher.args();
418-
}
419-
if (args.length == 0) {
420-
actualDataFetcher = newInstance(dataFetcher.value());
421-
} else {
422-
try {
423-
final Constructor<? extends DataFetcher> ctr = dataFetcher.value().getDeclaredConstructor(
424-
stream(args).map(v -> String.class).toArray(Class[]::new));
425-
actualDataFetcher = constructNewInstance(ctr, (Object[]) args);
426-
} catch (final NoSuchMethodException e) {
427-
}
428-
}
412+
actualDataFetcher = constructDataFetcher(field.getName(), dataFetcher);
429413
}
430414

431415
if (actualDataFetcher == null) {
@@ -469,6 +453,26 @@ protected GraphQLFieldDefinition getField(Field field) throws GraphQLAnnotations
469453
return new GraphQLFieldDefinitionWrapper(builder.build());
470454
}
471455

456+
private DataFetcher constructDataFetcher(String fieldName, GraphQLDataFetcher annotatedDataFetcher) {
457+
final String[] args;
458+
if ( annotatedDataFetcher.firstArgIsTargetName() ) {
459+
args = Stream.concat(Stream.of(fieldName), stream(annotatedDataFetcher.args())).toArray(String[]::new);
460+
} else {
461+
args = annotatedDataFetcher.args();
462+
}
463+
if (args.length == 0) {
464+
return newInstance(annotatedDataFetcher.value());
465+
} else {
466+
try {
467+
final Constructor<? extends DataFetcher> ctr = annotatedDataFetcher.value().getDeclaredConstructor(
468+
stream(args).map(v -> String.class).toArray(Class[]::new));
469+
return constructNewInstance(ctr, (Object[]) args);
470+
} catch (final NoSuchMethodException e) {
471+
throw new GraphQLAnnotationsException("Unable to instantiate DataFetcher via constructor for: " + fieldName, e);
472+
}
473+
}
474+
}
475+
472476
protected GraphQLFieldDefinition field(Field field) throws IllegalAccessException, InstantiationException {
473477
return getInstance().getField(field);
474478
}
@@ -592,7 +596,7 @@ protected GraphQLFieldDefinition getField(Method method) throws GraphQLAnnotatio
592596
} else if (dataFetcher == null) {
593597
actualDataFetcher = new MethodDataFetcher(method, typeFunction);
594598
} else {
595-
actualDataFetcher = newInstance(dataFetcher.value());
599+
actualDataFetcher = constructDataFetcher(method.getName(), dataFetcher);
596600
}
597601

598602
if (method.isAnnotationPresent(GraphQLRelayMutation.class) && relay != null) {

src/test/java/graphql/annotations/GraphQLDataFetcherTest.java

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.HashMap;
2727

2828
import static graphql.schema.GraphQLSchema.newSchema;
29+
import static org.testng.Assert.assertFalse;
2930
import static org.testng.Assert.assertNotNull;
3031
import static org.testng.Assert.assertTrue;
3132

@@ -48,15 +49,58 @@ public void shouldUsePreferredConstructor() {
4849
assertTrue(((HashMap<String, Boolean>) data.get("sample")).get("isBad"));
4950
}
5051

52+
@Test
53+
public void shouldUseProvidedSoloArgumentForDataFetcherDeclaredInMethod() {
54+
// Given
55+
final GraphQLObjectType object = GraphQLAnnotations.object(TestMethodWithDataFetcherGraphQLQuery.class);
56+
final GraphQLSchema schema = newSchema().query(object).build();
57+
final GraphQL graphql = GraphQL.newGraphQL(schema).build();
58+
59+
// When
60+
final ExecutionResult result = graphql.execute("{great}");
61+
62+
// Then
63+
final HashMap<String, Object> data = (HashMap) result.getData();
64+
assertNotNull(data);
65+
assertFalse((Boolean)data.get("great"));
66+
}
67+
68+
@Test
69+
public void shouldUseTargetAndArgumentsForDataFetcherDeclaredInMethod() {
70+
// Given
71+
final GraphQLObjectType object = GraphQLAnnotations.object(TestMethodWithDataFetcherGraphQLQuery.class);
72+
final GraphQLSchema schema = newSchema().query(object).build();
73+
final GraphQL graphql = GraphQL.newGraphQL(schema).build();
74+
75+
// When
76+
final ExecutionResult result = graphql.execute("{sample {bad}}");
77+
78+
// Then
79+
final HashMap<String, Object> data = (HashMap) result.getData();
80+
assertNotNull(data);
81+
assertTrue(((HashMap<String,Boolean>)data.get("sample")).get("bad"));
82+
}
83+
5184
@GraphQLName("Query")
5285
public static class TestGraphQLQuery {
5386
@GraphQLField
5487
@GraphQLDataFetcher(SampleDataFetcher.class)
5588
public TestSample sample() { // Note that GraphQL uses TestSample to build the graph
56-
return null;
89+
return null;
5790
}
5891
}
5992

93+
@GraphQLName("Query")
94+
public static class TestMethodWithDataFetcherGraphQLQuery {
95+
@GraphQLField
96+
@GraphQLDataFetcher(value = SampleOneArgDataFetcher.class, args = "true")
97+
public Boolean great() { return false; }
98+
99+
@GraphQLField
100+
@GraphQLDataFetcher(SampleDataFetcher.class)
101+
public TestSampleMethod sample() { return null; }
102+
}
103+
60104
public static class TestSample {
61105
@GraphQLField
62106
@GraphQLDataFetcher(value = PropertyDataFetcher.class, args = "isGreat")
@@ -68,13 +112,38 @@ public static class TestSample {
68112

69113
}
70114

115+
public static class TestSampleMethod {
116+
117+
@GraphQLField
118+
@GraphQLDataFetcher(value = SampleMultiArgDataFetcher.class, firstArgIsTargetName = true, args = {"true"})
119+
public Boolean isBad() { return false; } // Defaults to FieldDataFetcher
120+
121+
}
122+
71123
public static class SampleDataFetcher implements DataFetcher {
72124
@Override
73125
public Object get(final DataFetchingEnvironment environment) {
74126
return new Sample(); // Notice that it return a Sample, not a TestSample
75127
}
76128
}
77129

130+
public static class SampleOneArgDataFetcher implements DataFetcher {
131+
private boolean flip = false;
132+
133+
public SampleOneArgDataFetcher(String flip) {
134+
this.flip = Boolean.valueOf(flip);
135+
}
136+
137+
@Override
138+
public Object get(DataFetchingEnvironment environment) {
139+
if ( flip ) {
140+
return !flip;
141+
} else {
142+
return flip;
143+
}
144+
}
145+
}
146+
78147
public static class SampleMultiArgDataFetcher extends PropertyDataFetcher {
79148
private boolean flip = false;
80149

@@ -87,7 +156,7 @@ public SampleMultiArgDataFetcher(String target, String flip) {
87156
public Object get(DataFetchingEnvironment environment) {
88157
final Object result = super.get(environment);
89158
if (flip) {
90-
return !(Boolean) result;
159+
return !(Boolean)result;
91160
} else {
92161
return result;
93162
}

0 commit comments

Comments
 (0)