Skip to content

Commit e1ceb93

Browse files
authored
Merge pull request #111 from Jahia/connections-non-null
Fixes Null / NonNull on GraphQLConnection
2 parents c20332f + ee80da5 commit e1ceb93

File tree

5 files changed

+89
-36
lines changed

5 files changed

+89
-36
lines changed

src/main/java/graphql/annotations/DefaultTypeFunction.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,7 @@ public GraphQLType buildType(boolean inputType, Class<?> aClass, AnnotatedType a
328328
}
329329

330330
GraphQLType result = typeFunction.buildType(inputType, aClass, annotatedType);
331-
if (aClass.getAnnotation(GraphQLNonNull.class) != null ||
332-
(annotatedType != null && annotatedType.getAnnotation(GraphQLNonNull.class) != null)) {
331+
if (annotatedType != null && annotatedType.isAnnotationPresent(GraphQLNonNull.class)) {
333332
result = new graphql.schema.GraphQLNonNull(result);
334333
}
335334
return result;

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

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.osgi.service.component.annotations.Component;
2222
import org.osgi.service.component.annotations.Reference;
2323

24-
import javax.validation.constraints.NotNull;
2524
import java.lang.reflect.*;
2625
import java.util.*;
2726
import java.util.function.Function;
@@ -470,12 +469,12 @@ protected GraphQLFieldDefinition getField(Field field) throws GraphQLAnnotations
470469
typeFunction = newInstance(annotation.value());
471470
}
472471

473-
GraphQLOutputType type = (GraphQLOutputType) typeFunction.buildType(field.getType(), field.getAnnotatedType());
472+
GraphQLOutputType outputType = (GraphQLOutputType) typeFunction.buildType(field.getType(), field.getAnnotatedType());
474473

475-
GraphQLOutputType outputType = field.getAnnotation(NotNull.class) == null ? type : new GraphQLNonNull(type);
476-
477-
boolean isConnection = isConnection(field, field.getType(), type);
478-
outputType = getGraphQLConnection(isConnection, field, type, outputType, builder);
474+
boolean isConnection = isConnection(field, outputType);
475+
if (isConnection) {
476+
outputType = getGraphQLConnection(field, outputType, builder);
477+
}
479478

480479
builder.type(outputType);
481480

@@ -575,24 +574,33 @@ private boolean checkIfPrefixGetterExists(Class c, String prefix, String propert
575574
return true;
576575
}
577576

578-
private GraphQLOutputType getGraphQLConnection(boolean isConnection, AccessibleObject field, GraphQLOutputType type, GraphQLOutputType outputType, GraphQLFieldDefinition.Builder builder) {
579-
if (isConnection) {
580-
if (type instanceof GraphQLList) {
581-
graphql.schema.GraphQLType wrappedType = ((GraphQLList) type).getWrappedType();
582-
assert wrappedType instanceof GraphQLObjectType;
583-
String annValue = field.getAnnotation(GraphQLConnection.class).name();
584-
String connectionName = annValue.isEmpty() ? wrappedType.getName() : annValue;
585-
GraphQLObjectType edgeType = relay.edgeType(connectionName, (GraphQLOutputType) wrappedType, null, Collections.<GraphQLFieldDefinition>emptyList());
586-
outputType = relay.connectionType(connectionName, edgeType, Collections.emptyList());
587-
builder.argument(relay.getConnectionFieldArguments());
588-
}
577+
private GraphQLOutputType getGraphQLConnection(AccessibleObject field, GraphQLOutputType type, GraphQLFieldDefinition.Builder builder) {
578+
if (type instanceof GraphQLNonNull) {
579+
type = (GraphQLOutputType) ((GraphQLNonNull) type).getWrappedType();
580+
return new GraphQLNonNull(internalGetGraphQLConnection(field, type, builder));
581+
} else {
582+
return internalGetGraphQLConnection(field, type, builder);
589583
}
590-
return outputType;
591584
}
592585

593-
private boolean isConnection(AccessibleObject obj, Class<?> klass, GraphQLOutputType type) {
586+
private GraphQLOutputType internalGetGraphQLConnection(AccessibleObject field, GraphQLOutputType type, GraphQLFieldDefinition.Builder builder) {
587+
graphql.schema.GraphQLType wrappedType = ((GraphQLList) type).getWrappedType();
588+
assert wrappedType instanceof GraphQLObjectType;
589+
String connectionName = field.getAnnotation(GraphQLConnection.class).name();
590+
connectionName = connectionName.isEmpty() ? wrappedType.getName() : connectionName;
591+
GraphQLObjectType edgeType = relay.edgeType(connectionName, (GraphQLOutputType) wrappedType, null, Collections.<GraphQLFieldDefinition>emptyList());
592+
type = relay.connectionType(connectionName, edgeType, Collections.emptyList());
593+
builder.argument(relay.getConnectionFieldArguments());
594+
return type;
595+
}
596+
597+
private boolean isConnection(AccessibleObject obj, GraphQLOutputType type) {
598+
if (type instanceof GraphQLNonNull) {
599+
type = (GraphQLOutputType) ((GraphQLNonNull) type).getWrappedType();
600+
}
601+
final GraphQLOutputType actualType = type;
594602
return obj.isAnnotationPresent(GraphQLConnection.class) &&
595-
type instanceof GraphQLList && TYPES_FOR_CONNECTION.stream().anyMatch(aClass -> aClass.isInstance(((GraphQLList) type).getWrappedType()));
603+
actualType instanceof GraphQLList && TYPES_FOR_CONNECTION.stream().anyMatch(aClass -> aClass.isInstance(((GraphQLList) actualType).getWrappedType()));
596604
}
597605

598606
protected GraphQLFieldDefinition getField(Method method) throws GraphQLAnnotationsException {
@@ -618,11 +626,12 @@ protected GraphQLFieldDefinition getField(Method method) throws GraphQLAnnotatio
618626
outputTypeFunction = typeFunction;
619627
}
620628

621-
GraphQLOutputType type = (GraphQLOutputType) outputTypeFunction.buildType(method.getReturnType(), annotatedReturnType);
622-
GraphQLOutputType outputType = method.getAnnotation(NotNull.class) == null ? type : new GraphQLNonNull(type);
629+
GraphQLOutputType outputType = (GraphQLOutputType) outputTypeFunction.buildType(method.getReturnType(), annotatedReturnType);
623630

624-
boolean isConnection = isConnection(method, method.getReturnType(), type);
625-
outputType = getGraphQLConnection(isConnection, method, type, outputType, builder);
631+
boolean isConnection = isConnection(method, outputType);
632+
if (isConnection) {
633+
outputType = getGraphQLConnection(method, outputType, builder);
634+
}
626635

627636
builder.type(outputType);
628637

@@ -632,7 +641,7 @@ protected GraphQLFieldDefinition getField(Method method) throws GraphQLAnnotatio
632641
filter(p -> !DataFetchingEnvironment.class.isAssignableFrom(p.getType())).
633642
map(parameter -> {
634643
Class<?> t = parameter.getType();
635-
graphql.schema.GraphQLType graphQLType = getInputObject(finalTypeFunction.buildType(t, parameter.getAnnotatedType()), DEFAULT_INPUT_PREFIX);
644+
graphql.schema.GraphQLInputType graphQLType = getInputObject(finalTypeFunction.buildType(t, parameter.getAnnotatedType()), DEFAULT_INPUT_PREFIX);
636645
return getArgument(parameter, graphQLType);
637646
}).collect(Collectors.toList());
638647

@@ -743,10 +752,9 @@ public static GraphQLInputObjectType inputObject(GraphQLObjectType graphQLType,
743752
return (GraphQLInputObjectType) getInstance().getInputObject(graphQLType, newNamePrefix);
744753
}
745754

746-
protected GraphQLArgument getArgument(Parameter parameter, graphql.schema.GraphQLType t) throws
755+
protected GraphQLArgument getArgument(Parameter parameter, graphql.schema.GraphQLInputType t) throws
747756
GraphQLAnnotationsException {
748-
GraphQLArgument.Builder builder = newArgument();
749-
builder.type(parameter.getAnnotation(NotNull.class) == null ? (GraphQLInputType) t : new graphql.schema.GraphQLNonNull(t));
757+
GraphQLArgument.Builder builder = newArgument().type(t);
750758
GraphQLDescription description = parameter.getAnnotation(GraphQLDescription.class);
751759
if (description != null) {
752760
builder.description(description.value());
@@ -837,8 +845,12 @@ public Object get(DataFetchingEnvironment environment) {
837845
DataFetchingEnvironment env = new DataFetchingEnvironmentImpl(environment.getSource(), arguments, environment.getContext(),
838846
environment.getFields(), environment.getFieldType(), environment.getParentType(), environment.getGraphQLSchema(),
839847
environment.getFragmentsByName(), environment.getExecutionId(), environment.getSelectionSet());
840-
Connection conn = constructNewInstance(constructor, actualDataFetcher.get(env));
841-
return conn.get(environment);
848+
Object data = actualDataFetcher.get(env);
849+
if (data != null) {
850+
Connection conn = constructNewInstance(constructor, data);
851+
return conn.get(environment);
852+
}
853+
return null;
842854
}
843855
}
844856

src/main/java/graphql/annotations/GraphQLNonNull.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import java.lang.annotation.RetentionPolicy;
2020
import java.lang.annotation.Target;
2121

22-
@Target({ElementType.TYPE, ElementType.TYPE_USE, ElementType.METHOD, ElementType.PARAMETER})
22+
@Target({ElementType.FIELD, ElementType.TYPE_USE, ElementType.METHOD, ElementType.PARAMETER})
2323
@Retention(RetentionPolicy.RUNTIME)
2424
public @interface GraphQLNonNull {
2525
}

src/test/java/graphql/annotations/GraphQLConnectionTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,19 @@ public Stream<Obj> getObjStreamWithParam(@GraphQLName("filter") String filter) {
104104
return this.objs.stream().filter( obj -> obj.val.startsWith(filter));
105105
}
106106

107+
@GraphQLField
108+
@GraphQLConnection(name = "nonNullObjs")
109+
@GraphQLNonNull
110+
public List<Obj> getNonNullObjs() {
111+
return this.objs;
112+
}
113+
114+
@GraphQLField
115+
@GraphQLConnection(name = "null")
116+
public List<Obj> getNull() {
117+
return null;
118+
}
119+
107120

108121
}
109122

@@ -164,6 +177,36 @@ public void methodStream() {
164177
testResult("objStream", result);
165178
}
166179

180+
@Test
181+
public void methodNonNull() {
182+
GraphQLObjectType object = GraphQLAnnotations.object(TestConnections.class);
183+
GraphQLSchema schema = newSchema().query(object).build();
184+
185+
GraphQL graphQL = GraphQL.newGraphQL(schema).build();
186+
ExecutionResult result = graphQL.execute("{ nonNullObjs(first: 1) { edges { cursor node { id, val } } } }",
187+
new TestConnections(Arrays.asList(new Obj("1", "test"), new Obj("2", "hello"), new Obj("3", "world"))));
188+
189+
assertTrue(result.getErrors().isEmpty());
190+
191+
testResult("nonNullObjs", result);
192+
}
193+
194+
@Test
195+
public void methodNull() {
196+
GraphQLObjectType object = GraphQLAnnotations.object(TestConnections.class);
197+
GraphQLSchema schema = newSchema().query(object).build();
198+
199+
GraphQL graphQL = GraphQL.newGraphQL(schema).build();
200+
ExecutionResult result = graphQL.execute("{ null(first: 1) { edges { cursor node { id, val } } } }",
201+
new TestConnections(Arrays.asList(new Obj("1", "test"), new Obj("2", "hello"), new Obj("3", "world"))));
202+
203+
assertTrue(result.getErrors().isEmpty());
204+
205+
Map<String, Map<String, List<Map<String, Map<String, Object>>>>> data = result.getData();
206+
207+
assertEquals(data.get("null"), null);
208+
}
209+
167210
@Test
168211
public void methodListWithParam() {
169212
GraphQLObjectType object = GraphQLAnnotations.object(TestConnections.class);

src/test/java/graphql/annotations/GraphQLObjectTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.testng.annotations.BeforeMethod;
3232
import org.testng.annotations.Test;
3333

34-
import javax.validation.constraints.NotNull;
3534
import java.lang.reflect.AnnotatedType;
3635
import java.util.*;
3736
import java.util.function.Supplier;
@@ -67,13 +66,13 @@ private static class TestObject {
6766
@GraphQLName("field0")
6867
@GraphQLDescription("field")
6968
public
70-
@NotNull
69+
@GraphQLNonNull
7170
String field() {
7271
return "test";
7372
}
7473

7574
@GraphQLField
76-
public String fieldWithArgs(@NotNull String a, @GraphQLDefaultValue(DefaultAValue.class) @GraphQLDescription("b") String b) {
75+
public String fieldWithArgs(@GraphQLNonNull String a, @GraphQLDefaultValue(DefaultAValue.class) @GraphQLDescription("b") String b) {
7776
return b;
7877
}
7978

0 commit comments

Comments
 (0)