Skip to content

Commit 28796e1

Browse files
author
mattesja
committed
introduced typeRegistry for GraphQLType objects to prevent duplicate GraphQLType creations.
1 parent 2e6118c commit 28796e1

File tree

2 files changed

+125
-25
lines changed

2 files changed

+125
-25
lines changed

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

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,8 @@
1515
package graphql.annotations;
1616

1717
import graphql.relay.Relay;
18-
import graphql.schema.DataFetcher;
19-
import graphql.schema.DataFetchingEnvironment;
20-
import graphql.schema.FieldDataFetcher;
21-
import graphql.schema.GraphQLArgument;
22-
import graphql.schema.GraphQLFieldDefinition;
23-
import graphql.schema.GraphQLInputObjectField;
24-
import graphql.schema.GraphQLInputObjectType;
25-
import graphql.schema.GraphQLInputType;
26-
import graphql.schema.GraphQLInterfaceType;
27-
import graphql.schema.GraphQLList;
18+
import graphql.schema.*;
2819
import graphql.schema.GraphQLNonNull;
29-
import graphql.schema.GraphQLObjectType;
30-
import graphql.schema.GraphQLOutputType;
31-
import graphql.schema.GraphQLUnionType;
32-
import graphql.schema.PropertyDataFetcher;
33-
import graphql.schema.TypeResolver;
3420
import org.osgi.service.component.annotations.Component;
3521
import org.osgi.service.component.annotations.Reference;
3622

@@ -66,7 +52,6 @@
6652
import static graphql.schema.GraphQLObjectType.newObject;
6753
import static graphql.schema.GraphQLUnionType.newUnionType;
6854
import static java.util.Arrays.stream;
69-
import static java.util.Objects.isNull;
7055
import static java.util.Objects.nonNull;
7156

7257
/**
@@ -76,6 +61,8 @@
7661
@Component
7762
public class GraphQLAnnotations implements GraphQLAnnotationsProcessor {
7863

64+
private Map<String, graphql.schema.GraphQLType> typeRegistry = new HashMap<>();
65+
7966
public GraphQLAnnotations() {
8067
defaultTypeFunction = new DefaultTypeFunction();
8168
((DefaultTypeFunction) defaultTypeFunction).setAnnotationsProcessor(this);
@@ -89,13 +76,20 @@ public static GraphQLAnnotations getInstance() {
8976

9077
@Override
9178
public graphql.schema.GraphQLType getInterface(Class<?> iface) throws GraphQLAnnotationsException {
79+
String typeName = getTypeName(iface);
80+
graphql.schema.GraphQLType type = typeRegistry.get(typeName);
81+
if (type != null) { // type already exists, do not build a new new one
82+
return type;
83+
}
9284
if (iface.getAnnotation(GraphQLUnion.class) != null) {
93-
return getUnionBuilder(iface).build();
85+
type = getUnionBuilder(iface).build();
9486
} else if (!iface.isAnnotationPresent(GraphQLTypeResolver.class)) {
95-
return getObject(iface);
87+
type = getObject(iface);
9688
} else {
97-
return getIfaceBuilder(iface).build();
89+
type = getIfaceBuilder(iface).build();
9890
}
91+
typeRegistry.put(typeName, type);
92+
return type;
9993
}
10094

10195
public static graphql.schema.GraphQLType iface(Class<?> iface) throws GraphQLAnnotationsException {
@@ -110,8 +104,7 @@ public GraphQLUnionType.Builder getUnionBuilder(Class<?> iface) throws GraphQLAn
110104
GraphQLUnionType.Builder builder = newUnionType();
111105

112106
GraphQLUnion unionAnnotation = iface.getAnnotation(GraphQLUnion.class);
113-
GraphQLName name = iface.getAnnotation(GraphQLName.class);
114-
builder.name(name == null ? iface.getSimpleName() : name.value());
107+
builder.name(getTypeName(iface));
115108
GraphQLDescription description = iface.getAnnotation(GraphQLDescription.class);
116109
if (description != null) {
117110
builder.description(description.value());
@@ -143,6 +136,11 @@ public static GraphQLUnionType.Builder unionBuilder(Class<?> iface) throws Graph
143136
return getInstance().getUnionBuilder(iface);
144137
}
145138

139+
public String getTypeName(Class<?> objectClass) {
140+
GraphQLName name = objectClass.getAnnotation(GraphQLName.class);
141+
return (name == null ? objectClass.getSimpleName() : name.value());
142+
}
143+
146144
@Override
147145
public GraphQLInterfaceType.Builder getIfaceBuilder(Class<?> iface) throws GraphQLAnnotationsException,
148146
IllegalArgumentException {
@@ -151,8 +149,7 @@ public GraphQLInterfaceType.Builder getIfaceBuilder(Class<?> iface) throws Graph
151149
}
152150
GraphQLInterfaceType.Builder builder = newInterface();
153151

154-
GraphQLName name = iface.getAnnotation(GraphQLName.class);
155-
builder.name(name == null ? iface.getSimpleName() : name.value());
152+
builder.name(getTypeName(iface));
156153
GraphQLDescription description = iface.getAnnotation(GraphQLDescription.class);
157154
if (description != null) {
158155
builder.description(description.value());
@@ -274,8 +271,7 @@ public boolean equals(Object obj) {
274271
@Override
275272
public GraphQLObjectType.Builder getObjectBuilder(Class<?> object) throws GraphQLAnnotationsException {
276273
GraphQLObjectType.Builder builder = newObject();
277-
GraphQLName name = object.getAnnotation(GraphQLName.class);
278-
builder.name(name == null ? object.getSimpleName() : name.value());
274+
builder.name(getTypeName(object));
279275
GraphQLDescription description = object.getAnnotation(GraphQLDescription.class);
280276
if (description != null) {
281277
builder.description(description.value());
@@ -635,6 +631,9 @@ public static void register(TypeFunction typeFunction) {
635631
getInstance().registerType(typeFunction);
636632
}
637633

634+
public Map<String, graphql.schema.GraphQLType> getTypeRegistry() {
635+
return typeRegistry;
636+
}
638637

639638
private static class ConnectionDataFetcher implements DataFetcher {
640639
private final Class<? extends Connection> connection;
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package graphql.annotations;
2+
3+
import graphql.ExecutionResult;
4+
import graphql.ExecutionResultImpl;
5+
import graphql.GraphQL;
6+
import graphql.schema.GraphQLInterfaceType;
7+
import graphql.schema.GraphQLObjectType;
8+
import graphql.schema.GraphQLSchema;
9+
import graphql.schema.TypeResolver;
10+
import org.testng.annotations.Test;
11+
12+
import java.util.*;
13+
14+
import static org.testng.AssertJUnit.assertEquals;
15+
16+
17+
public class GraphQLFragmentTest {
18+
19+
static Map<String, GraphQLObjectType> registry;
20+
21+
@Test
22+
public void test() throws Exception {
23+
24+
registry = new HashMap<>();
25+
26+
GraphQLInterfaceType iface = (GraphQLInterfaceType) GraphQLAnnotations.iface(MyInterface.class);
27+
28+
GraphQLObjectType rootType = GraphQLAnnotations.object(RootObject.class);
29+
30+
GraphQLObjectType objectType2 = GraphQLAnnotations.object(MyObject2.class);
31+
32+
registry.put("MyObject2", objectType2);
33+
34+
GraphQLObjectType objectType = GraphQLAnnotations.object(MyObject.class);
35+
36+
registry.put("MyObject", objectType);
37+
38+
GraphQLSchema schema = GraphQLSchema.newSchema()
39+
.query(rootType)
40+
.build(new HashSet(Arrays.asList(iface, rootType, objectType, objectType2)));
41+
42+
GraphQL graphQL2 = new GraphQL(schema);
43+
44+
ExecutionResult graphQLResult = graphQL2.execute("{items { ... on MyObject {a, my {b}} ... on MyObject2 {a, b} }}", new RootObject());
45+
Set resultMap = ((Map) graphQLResult.getData()).entrySet();
46+
47+
assertEquals(graphQLResult.getErrors().size(), 0);
48+
assertEquals(resultMap.size(), 1);
49+
}
50+
51+
public static class RootObject {
52+
@GraphQLField
53+
public List<MyInterface> getItems() {
54+
return Arrays.asList(new MyObject(), new MyObject2());
55+
}
56+
}
57+
58+
public static class MyObject implements MyInterface {
59+
public String getA() {
60+
return "a1";
61+
}
62+
63+
public String getB() {
64+
return "b1";
65+
}
66+
67+
@GraphQLField
68+
public MyObject2 getMy() {
69+
return new MyObject2();
70+
}
71+
}
72+
73+
public static class MyObject2 implements MyInterface {
74+
public String getA() {
75+
return "a2";
76+
}
77+
78+
public String getB() {
79+
return "b2";
80+
}
81+
}
82+
83+
@GraphQLTypeResolver(value = MyTypeResolver.class)
84+
public static interface MyInterface {
85+
@GraphQLField
86+
public String getA();
87+
88+
@GraphQLField
89+
public String getB();
90+
}
91+
92+
public static class MyTypeResolver implements TypeResolver {
93+
94+
@Override
95+
public GraphQLObjectType getType(Object object) {
96+
return registry.get(object.getClass().getSimpleName());
97+
}
98+
}
99+
100+
101+
}

0 commit comments

Comments
 (0)