Skip to content

Commit 6246639

Browse files
authored
Merge pull request #264 from singh-sardar/bugfix/graphql-constructor-annotation
bugfix for MethodDataFetcher:buildArg #262
2 parents 0fafe62 + 80af2df commit 6246639

File tree

2 files changed

+60
-18
lines changed

2 files changed

+60
-18
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
*/
13+
package graphql.annotations.annotationTypes;
14+
15+
import java.lang.annotation.ElementType;
16+
import java.lang.annotation.Retention;
17+
import java.lang.annotation.RetentionPolicy;
18+
import java.lang.annotation.Target;
19+
20+
/***
21+
* When using object as argument of query or mutation, a HashMap Constructor is used to initialize
22+
* the object fields. In order to identify the correct constructor this annotation must be used, otherwise
23+
* the object fields will be null
24+
*/
25+
@Retention(RetentionPolicy.RUNTIME)
26+
@Target(ElementType.CONSTRUCTOR)
27+
public @interface GraphQLConstructor {
28+
}

src/main/java/graphql/annotations/dataFetchers/MethodDataFetcher.java

+32-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
/**
2-
* Copyright 2016 Yurii Rashkovskii
3-
*
42
* Licensed under the Apache License, Version 2.0 (the "License");
53
* you may not use this file except in compliance with the License.
64
* You may obtain a copy of the License at
@@ -15,6 +13,7 @@
1513
package graphql.annotations.dataFetchers;
1614

1715
import graphql.annotations.annotationTypes.GraphQLBatched;
16+
import graphql.annotations.annotationTypes.GraphQLConstructor;
1817
import graphql.annotations.annotationTypes.GraphQLInvokeDetached;
1918
import graphql.annotations.annotationTypes.GraphQLName;
2019
import graphql.annotations.processor.ProcessingElementsContainer;
@@ -68,10 +67,9 @@ public MethodDataFetcher(Method method, TypeFunction typeFunction, ProcessingEle
6867
public T get(DataFetchingEnvironment environment) {
6968
try {
7069
T obj;
71-
if (Modifier.isStatic(method.getModifiers())){
70+
if (Modifier.isStatic(method.getModifiers())) {
7271
return (T) method.invoke(null, invocationArgs(environment, container));
73-
}
74-
else if (method.isAnnotationPresent(GraphQLBatched.class) || method.isAnnotationPresent(GraphQLInvokeDetached.class)) {
72+
} else if (method.isAnnotationPresent(GraphQLBatched.class) || method.isAnnotationPresent(GraphQLInvokeDetached.class)) {
7573
obj = newInstance((Class<T>) method.getDeclaringClass());
7674
} else if (!method.getDeclaringClass().isInstance(environment.getSource())) {
7775
obj = newInstance((Class<T>) method.getDeclaringClass(), environment.getSource());
@@ -130,21 +128,19 @@ private Object buildArg(Type p, GraphQLType graphQLType, Object arg) {
130128
}
131129
if (p instanceof Class<?> && graphQLType instanceof GraphQLInputObjectType) {
132130
Constructor<?> constructors[] = ((Class) p).getConstructors();
133-
for (Constructor<?> constructor : constructors) {
134-
Parameter[] parameters = constructor.getParameters();
135-
if (parameters.length == 1 && parameters[0].getType().isAssignableFrom(arg.getClass())) {
136-
return constructNewInstance(constructor, arg);
137-
} else {
138-
List<Object> objects = new ArrayList<>();
139-
Map map = (Map) arg;
140-
for (Parameter parameter : parameters) {
141-
String name = toGraphqlName(parameter.getAnnotation(GraphQLName.class) != null ? parameter.getAnnotation(GraphQLName.class).value() : parameter.getName());
142-
objects.add(buildArg(parameter.getParameterizedType(), ((GraphQLInputObjectType) graphQLType).getField(name).getType(), map.get(name)));
143-
}
144-
return constructNewInstance(constructor, objects.toArray(new Object[objects.size()]));
131+
Constructor<?> constructor = getBuildArgConstructor(constructors);
132+
Parameter[] parameters = constructor.getParameters();
133+
if (parameters.length == 1 && parameters[0].getType().isAssignableFrom(arg.getClass())) {
134+
return constructNewInstance(constructor, arg);
135+
} else {
136+
List<Object> objects = new ArrayList<>();
137+
Map map = (Map) arg;
138+
for (Parameter parameter : parameters) {
139+
String name = toGraphqlName(parameter.getAnnotation(GraphQLName.class) != null ? parameter.getAnnotation(GraphQLName.class).value() : parameter.getName());
140+
objects.add(buildArg(parameter.getParameterizedType(), ((GraphQLInputObjectType) graphQLType).getField(name).getType(), map.get(name)));
145141
}
142+
return constructNewInstance(constructor, objects.toArray(new Object[objects.size()]));
146143
}
147-
return null;
148144
} else if (p instanceof ParameterizedType && graphQLType instanceof GraphQLList) {
149145
List<Object> list = new ArrayList<>();
150146
Type subType = ((ParameterizedType) p).getActualTypeArguments()[0];
@@ -160,6 +156,24 @@ private Object buildArg(Type p, GraphQLType graphQLType, Object arg) {
160156
}
161157
}
162158

159+
160+
/***
161+
* return the constructor to call in order to build the object
162+
* @param constructors Object constructors
163+
* @return the annotated constructor if present else return the first constructor
164+
*/
165+
private Constructor getBuildArgConstructor(Constructor<?> constructors[]) {
166+
if (constructors != null) {
167+
for (Constructor<?> constructor : constructors) {
168+
if (constructor.isAnnotationPresent(GraphQLConstructor.class)) {
169+
return constructor;
170+
}
171+
}
172+
return constructors[0];
173+
}
174+
return null;
175+
}
176+
163177
private Object getGraphQLFieldValue(Object source, String fieldName) throws IllegalAccessException, NoSuchFieldException, InvocationTargetException {
164178
Object methodValue = getValueFromMethod(source, fieldName);
165179
if (methodValue != null) return methodValue;

0 commit comments

Comments
 (0)