Skip to content

Commit 1628077

Browse files
author
Thomas Draier
committed
Avoid fields redefinition in extensions
1 parent 79d5b77 commit 1628077

File tree

2 files changed

+50
-12
lines changed

2 files changed

+50
-12
lines changed

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

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,17 @@ public GraphQLInterfaceType.Builder getIfaceBuilder(Class<?> iface) throws Graph
149149
if (description != null) {
150150
builder.description(description.value());
151151
}
152+
List<String> definedFields = new ArrayList<>();
152153
for (Method method : getOrderedMethods(iface)) {
153154
boolean valid = !Modifier.isStatic(method.getModifiers()) &&
154155
method.getAnnotation(GraphQLField.class) != null;
155156
if (valid) {
156-
builder.field(getField(method));
157+
GraphQLFieldDefinition gqlField = getField(method);
158+
definedFields.add(gqlField.getName());
159+
builder.field(gqlField);
157160
}
158161
}
159-
builder.fields(getExtensionFields(iface));
162+
builder.fields(getExtensionFields(iface, definedFields));
160163

161164
GraphQLTypeResolver typeResolver = iface.getAnnotation(GraphQLTypeResolver.class);
162165
builder.typeResolver(newInstance(typeResolver.value()));
@@ -292,13 +295,15 @@ public GraphQLObjectType.Builder getObjectBuilder(Class<?> object) throws GraphQ
292295
if (description != null) {
293296
builder.description(description.value());
294297
}
295-
298+
List<String> fieldsDefined = new ArrayList<>();
296299
for (Method method : getOrderedMethods(object)) {
297300
if (method.isBridge() || method.isSynthetic()) {
298301
continue;
299302
}
300303
if (breadthFirstSearch(method)) {
301-
builder.field(getField(method));
304+
GraphQLFieldDefinition gqlField = getField(method);
305+
fieldsDefined.add(gqlField.getName());
306+
builder.field(gqlField);
302307
}
303308
}
304309

@@ -307,23 +312,25 @@ public GraphQLObjectType.Builder getObjectBuilder(Class<?> object) throws GraphQ
307312
continue;
308313
}
309314
if (parentalSearch(field)) {
310-
builder.field(getField(field));
315+
GraphQLFieldDefinition gqlField = getField(field);
316+
fieldsDefined.add(gqlField.getName());
317+
builder.field(gqlField);
311318
}
312319
}
313320

314321
for (Class<?> iface : object.getInterfaces()) {
315322
if (iface.getAnnotation(GraphQLTypeResolver.class) != null) {
316323
builder.withInterface((GraphQLInterfaceType) getInterface(iface));
317-
builder.fields(getExtensionFields(iface));
324+
builder.fields(getExtensionFields(iface, fieldsDefined));
318325
}
319326
}
320327

321-
builder.fields(getExtensionFields(object));
328+
builder.fields(getExtensionFields(object, fieldsDefined));
322329

323330
return builder;
324331
}
325332

326-
private List<GraphQLFieldDefinition> getExtensionFields(Class<?> object) {
333+
private List<GraphQLFieldDefinition> getExtensionFields(Class<?> object, List<String> fieldsDefined) {
327334
List<GraphQLFieldDefinition> fields = new ArrayList<>();
328335
if (extensionsTypeRegistry.containsKey(object)) {
329336
for (Class<?> aClass : extensionsTypeRegistry.get(object)) {
@@ -332,22 +339,31 @@ private List<GraphQLFieldDefinition> getExtensionFields(Class<?> object) {
332339
continue;
333340
}
334341
if (breadthFirstSearch(method)) {
335-
fields.add(getField(method));
342+
addExtensionField(getField(method), fields, fieldsDefined);
336343
}
337344
}
338345
for (Field field : getAllFields(aClass).values()) {
339346
if (Modifier.isStatic(field.getModifiers())) {
340347
continue;
341348
}
342349
if (parentalSearch(field)) {
343-
fields.add(getField(field));
350+
addExtensionField(getField(field), fields, fieldsDefined);
344351
}
345352
}
346353
}
347354
}
348355
return fields;
349356
}
350357

358+
private void addExtensionField(GraphQLFieldDefinition gqlField, List<GraphQLFieldDefinition> fields, List<String> fieldsDefined) {
359+
if (!fieldsDefined.contains(gqlField.getName())) {
360+
fieldsDefined.add(gqlField.getName());
361+
fields.add(gqlField);
362+
} else {
363+
throw new GraphQLAnnotationsException("Duplicate field found in extension : " + gqlField.getName(), null);
364+
}
365+
}
366+
351367
public static GraphQLObjectType.Builder objectBuilder(Class<?> object) throws GraphQLAnnotationsException {
352368
return getInstance().getObjectBuilder(object);
353369
}
@@ -459,7 +475,7 @@ protected GraphQLFieldDefinition getField(Field field) throws GraphQLAnnotations
459475

460476
private DataFetcher constructDataFetcher(String fieldName, GraphQLDataFetcher annotatedDataFetcher) {
461477
final String[] args;
462-
if ( annotatedDataFetcher.firstArgIsTargetName() ) {
478+
if (annotatedDataFetcher.firstArgIsTargetName()) {
463479
args = Stream.concat(Stream.of(fieldName), stream(annotatedDataFetcher.args())).toArray(String[]::new);
464480
} else {
465481
args = annotatedDataFetcher.args();

src/test/java/graphql/annotations/GraphQLExtensionsTest.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import graphql.ExecutionResult;
1818
import graphql.GraphQL;
1919
import graphql.schema.*;
20+
import org.testng.Assert;
2021
import org.testng.annotations.AfterTest;
2122
import org.testng.annotations.BeforeTest;
2223
import org.testng.annotations.Test;
@@ -26,7 +27,7 @@
2627

2728
import static graphql.Scalars.GraphQLString;
2829
import static graphql.schema.GraphQLSchema.newSchema;
29-
import static org.testng.Assert.assertEquals;
30+
import static org.testng.Assert.*;
3031

3132
public class GraphQLExtensionsTest {
3233

@@ -70,6 +71,20 @@ public String getField5() {
7071
}
7172
}
7273

74+
@GraphQLTypeExtension(GraphQLExtensionsTest.TestObject.class)
75+
public static class TestObjectExtensionInvalid {
76+
private TestObject obj;
77+
78+
public TestObjectExtensionInvalid(TestObject obj) {
79+
this.obj = obj;
80+
}
81+
82+
@GraphQLField
83+
public String getField() {
84+
return "invalid";
85+
}
86+
}
87+
7388
public static class TestDataFetcher implements DataFetcher {
7489
@Override
7590
public Object get(DataFetchingEnvironment environment) {
@@ -113,4 +128,11 @@ public void values() {
113128
assertEquals(data.get("field5"), "test test5");
114129
}
115130

131+
@Test
132+
public void testDuplicateField() {
133+
GraphQLAnnotations.getInstance().registerTypeExtension(TestObjectExtensionInvalid.class);
134+
GraphQLAnnotationsException e = expectThrows(GraphQLAnnotationsException.class, () -> GraphQLAnnotations.object(TestObject.class));
135+
assertTrue(e.getMessage().startsWith("Duplicate field"));
136+
GraphQLAnnotations.getInstance().unregisterTypeExtension(TestObjectExtensionInvalid.class);
137+
}
116138
}

0 commit comments

Comments
 (0)