Skip to content

Commit 06a202c

Browse files
authored
Path support when traversing graph (#499)
* Path support when traversing graph #498 - now follows spec in regards to data fetcher errors * Added SerializationError path support * Added NonNullable path support * Fixed test
1 parent 304fab3 commit 06a202c

16 files changed

+421
-70
lines changed

src/main/java/graphql/Assert.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ public static <T> T assertNotNull(T object, String errorMessage) {
1010
throw new AssertException(errorMessage);
1111
}
1212

13+
public static <T> T assertNotNull(T object) {
14+
if (object != null) return object;
15+
throw new AssertException("Object required to be not null");
16+
}
17+
1318
public static <T> T assertNeverCalled() {
1419
throw new AssertException("Should never been called");
1520
}
@@ -39,6 +44,7 @@ public static void assertTrue(boolean condition, String errorMessage) {
3944
* currently non null, non empty,
4045
*
4146
* @param name - the name to be validated.
47+
*
4248
* @return the name if valid, or AssertException if invalid.
4349
*/
4450
public static String assertValidName(String name) {

src/main/java/graphql/ExceptionWhileDataFetching.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
package graphql;
22

33

4+
import graphql.execution.ExecutionPath;
45
import graphql.language.SourceLocation;
56

67
import java.util.List;
78

9+
import static graphql.Assert.assertNotNull;
10+
import static java.lang.String.format;
11+
812
@PublicApi
913
public class ExceptionWhileDataFetching implements GraphQLError {
1014

15+
private final ExecutionPath path;
1116
private final Throwable exception;
1217

13-
public ExceptionWhileDataFetching(Throwable exception) {
14-
this.exception = exception;
18+
public ExceptionWhileDataFetching(ExecutionPath path, Throwable exception) {
19+
this.path = assertNotNull(path);
20+
this.exception = assertNotNull(exception);
1521
}
1622

1723
public Throwable getException() {
@@ -21,14 +27,24 @@ public Throwable getException() {
2127

2228
@Override
2329
public String getMessage() {
24-
return "Exception while fetching data: " + exception.getMessage();
30+
return format("Exception while fetching data (%s) : %s", path, exception.getMessage());
2531
}
2632

2733
@Override
2834
public List<SourceLocation> getLocations() {
2935
return null;
3036
}
3137

38+
/**
39+
* The graphql spec says that that path field of any error should be a list
40+
* of path entries - http://facebook.github.io/graphql/#sec-Errors
41+
*
42+
* @return the path in list format
43+
*/
44+
public List<Object> getPath() {
45+
return path.toList();
46+
}
47+
3248
@Override
3349
public ErrorType getErrorType() {
3450
return ErrorType.DataFetchingException;
@@ -37,10 +53,12 @@ public ErrorType getErrorType() {
3753
@Override
3854
public String toString() {
3955
return "ExceptionWhileDataFetching{" +
56+
"path=" + path +
4057
"exception=" + exception +
4158
'}';
4259
}
4360

61+
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
4462
@Override
4563
public boolean equals(Object o) {
4664
return Helper.equals(this, o);

src/main/java/graphql/Scalars.java

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,7 @@ public class Scalars {
2828

2929

3030
private static boolean isNumberIsh(Object input) {
31-
if (input instanceof Number) {
32-
return true;
33-
}
34-
if (input instanceof String) {
35-
return true;
36-
}
37-
return false;
31+
return input instanceof Number || input instanceof String;
3832
}
3933

4034
public static GraphQLScalarType GraphQLInt = new GraphQLScalarType("Int", "Built-in Int", new Coercing<Integer, Integer>() {
@@ -64,7 +58,7 @@ private Integer convertImpl(Object input) {
6458
public Integer serialize(Object input) {
6559
Integer result = convertImpl(input);
6660
if (result == null) {
67-
throw new CoercingSerializeException("Invalid value " + input + " for Int");
61+
throw new CoercingSerializeException("Invalid value '" + input + "' for Int");
6862
}
6963
return result;
7064
}
@@ -73,7 +67,7 @@ public Integer serialize(Object input) {
7367
public Integer parseValue(Object input) {
7468
Integer result = convertImpl(input);
7569
if (result == null) {
76-
throw new CoercingParseValueException("Invalid value " + input + " for Int");
70+
throw new CoercingParseValueException("Invalid value '" + input + "' for Int");
7771
}
7872
return result;
7973
}
@@ -115,7 +109,7 @@ private Long convertImpl(Object input) {
115109
public Long serialize(Object input) {
116110
Long result = convertImpl(input);
117111
if (result == null) {
118-
throw new CoercingSerializeException("Invalid input " + input + " for Long");
112+
throw new CoercingSerializeException("Invalid input '" + input + "' for Long");
119113
}
120114
return result;
121115
}
@@ -124,7 +118,7 @@ public Long serialize(Object input) {
124118
public Long parseValue(Object input) {
125119
Long result = convertImpl(input);
126120
if (result == null) {
127-
throw new CoercingParseValueException("Invalid input " + input + " for Long");
121+
throw new CoercingParseValueException("Invalid input '" + input + "' for Long");
128122
}
129123
return result;
130124
}
@@ -175,7 +169,7 @@ private Short convertImpl(Object input) {
175169
public Short serialize(Object input) {
176170
Short result = convertImpl(input);
177171
if (result == null) {
178-
throw new CoercingSerializeException("Invalid input " + input + " for Short");
172+
throw new CoercingSerializeException("Invalid input '" + input + "' for Short");
179173
}
180174
return result;
181175
}
@@ -184,7 +178,7 @@ public Short serialize(Object input) {
184178
public Short parseValue(Object input) {
185179
Short result = convertImpl(input);
186180
if (result == null) {
187-
throw new CoercingParseValueException("Invalid input " + input + " for Short");
181+
throw new CoercingParseValueException("Invalid input '" + input + "' for Short");
188182
}
189183
return result;
190184
}
@@ -226,7 +220,7 @@ private Byte convertImpl(Object input) {
226220
public Byte serialize(Object input) {
227221
Byte result = convertImpl(input);
228222
if (result == null) {
229-
throw new CoercingSerializeException("Invalid input " + input + " for Byte");
223+
throw new CoercingSerializeException("Invalid input '" + input + "' for Byte");
230224
}
231225
return result;
232226
}
@@ -235,7 +229,7 @@ public Byte serialize(Object input) {
235229
public Byte parseValue(Object input) {
236230
Byte result = convertImpl(input);
237231
if (result == null) {
238-
throw new CoercingParseValueException("Invalid input " + input + " for Byte");
232+
throw new CoercingParseValueException("Invalid input '" + input + "' for Byte");
239233
}
240234
return result;
241235
}
@@ -276,7 +270,7 @@ private Double convertImpl(Object input) {
276270
public Double serialize(Object input) {
277271
Double result = convertImpl(input);
278272
if (result == null) {
279-
throw new CoercingSerializeException("Invalid input " + input + " for Byte");
273+
throw new CoercingSerializeException("Invalid input '" + input + "' for Float");
280274
}
281275
return result;
282276

@@ -286,7 +280,7 @@ public Double serialize(Object input) {
286280
public Double parseValue(Object input) {
287281
Double result = convertImpl(input);
288282
if (result == null) {
289-
throw new CoercingParseValueException("Invalid input " + input + " for Byte");
283+
throw new CoercingParseValueException("Invalid input '" + input + "' for Float");
290284
}
291285
return result;
292286
}
@@ -327,7 +321,7 @@ private BigInteger convertImpl(Object input) {
327321
public BigInteger serialize(Object input) {
328322
BigInteger result = convertImpl(input);
329323
if (result == null) {
330-
throw new CoercingSerializeException("Invalid input " + input + " for BigDecimal");
324+
throw new CoercingSerializeException("Invalid input '" + input + "' for BigInteger");
331325
}
332326
return result;
333327
}
@@ -336,7 +330,7 @@ public BigInteger serialize(Object input) {
336330
public BigInteger parseValue(Object input) {
337331
BigInteger result = convertImpl(input);
338332
if (result == null) {
339-
throw new CoercingParseValueException("Invalid input " + input + " for BigDecimal");
333+
throw new CoercingParseValueException("Invalid input '" + input + "' for BigInteger");
340334
}
341335
return result;
342336
}
@@ -380,7 +374,7 @@ private BigDecimal convertImpl(Object input) {
380374
public BigDecimal serialize(Object input) {
381375
BigDecimal result = convertImpl(input);
382376
if (result == null) {
383-
throw new CoercingSerializeException("Invalid input " + input + " for BigDecimal");
377+
throw new CoercingSerializeException("Invalid input '" + input + "' for BigDecimal");
384378
}
385379
return result;
386380
}
@@ -389,7 +383,7 @@ public BigDecimal serialize(Object input) {
389383
public BigDecimal parseValue(Object input) {
390384
BigDecimal result = convertImpl(input);
391385
if (result == null) {
392-
throw new CoercingParseValueException("Invalid input " + input + " for BigDecimal");
386+
throw new CoercingParseValueException("Invalid input '" + input + "' for BigDecimal");
393387
}
394388
return result;
395389
}
@@ -457,7 +451,7 @@ private Boolean convertImpl(Object input) {
457451
public Boolean serialize(Object input) {
458452
Boolean result = convertImpl(input);
459453
if (result == null) {
460-
throw new CoercingSerializeException("Invalid input " + input + " for Boolean");
454+
throw new CoercingSerializeException("Invalid input '" + input + "' for Boolean");
461455
}
462456
return result;
463457
}
@@ -466,7 +460,7 @@ public Boolean serialize(Object input) {
466460
public Boolean parseValue(Object input) {
467461
Boolean result = convertImpl(input);
468462
if (result == null) {
469-
throw new CoercingParseValueException("Invalid input " + input + " for Boolean");
463+
throw new CoercingParseValueException("Invalid input '" + input + "' for Boolean");
470464
}
471465
return result;
472466
}
@@ -498,7 +492,7 @@ private String convertImpl(Object input) {
498492
public String serialize(Object input) {
499493
String result = convertImpl(input);
500494
if (result == null) {
501-
throw new CoercingSerializeException("Invalid input " + input + " for ID");
495+
throw new CoercingSerializeException("Invalid input '" + input + "' for ID");
502496
}
503497
return result;
504498
}
@@ -507,7 +501,7 @@ public String serialize(Object input) {
507501
public String parseValue(Object input) {
508502
String result = convertImpl(input);
509503
if (result == null) {
510-
throw new CoercingParseValueException("Invalid input " + input + " for ID");
504+
throw new CoercingParseValueException("Invalid input '" + input + "' for ID");
511505
}
512506
return result;
513507
}
@@ -542,7 +536,7 @@ private Character convertImpl(Object input) {
542536
public Character serialize(Object input) {
543537
Character result = convertImpl(input);
544538
if (result == null) {
545-
throw new CoercingSerializeException("Invalid input " + input + " for Char");
539+
throw new CoercingSerializeException("Invalid input '" + input + "' for Char");
546540
}
547541
return result;
548542
}
@@ -551,7 +545,7 @@ public Character serialize(Object input) {
551545
public Character parseValue(Object input) {
552546
Character result = convertImpl(input);
553547
if (result == null) {
554-
throw new CoercingParseValueException("Invalid input " + input + " for Char");
548+
throw new CoercingParseValueException("Invalid input '" + input + "' for Char");
555549
}
556550
return result;
557551
}

src/main/java/graphql/SerializationError.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
package graphql;
22

33

4+
import graphql.execution.ExecutionPath;
45
import graphql.language.SourceLocation;
56
import graphql.schema.CoercingSerializeException;
67

78
import java.util.List;
89

10+
import static graphql.Assert.assertNotNull;
11+
import static java.lang.String.format;
12+
913
@PublicApi
1014
public class SerializationError implements GraphQLError {
1115

1216
private final CoercingSerializeException exception;
17+
private final ExecutionPath path;
1318

14-
public SerializationError(CoercingSerializeException exception) {
15-
this.exception = exception;
19+
public SerializationError(ExecutionPath path, CoercingSerializeException exception) {
20+
this.path = assertNotNull(path);
21+
this.exception = assertNotNull(exception);
1622
}
1723

1824
public CoercingSerializeException getException() {
@@ -22,7 +28,7 @@ public CoercingSerializeException getException() {
2228

2329
@Override
2430
public String getMessage() {
25-
return "Can't serialize value: " + exception.getMessage();
31+
return format("Can't serialize value (%s) : %s", path, exception.getMessage());
2632
}
2733

2834
@Override
@@ -35,13 +41,25 @@ public ErrorType getErrorType() {
3541
return ErrorType.DataFetchingException;
3642
}
3743

44+
/**
45+
* The graphql spec says that that path field of any error should be a list
46+
* of path entries - http://facebook.github.io/graphql/#sec-Errors
47+
*
48+
* @return the path in list format
49+
*/
50+
public List<Object> getPath() {
51+
return path.toList();
52+
}
53+
3854
@Override
3955
public String toString() {
4056
return "ExceptionWhileDataFetching{" +
57+
"path=" + path +
4158
"exception=" + exception +
4259
'}';
4360
}
4461

62+
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
4563
@Override
4664
public boolean equals(Object o) {
4765
return Helper.equals(this, o);

src/main/java/graphql/execution/Execution.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ private ExecutionResult executeOperation(
9898
.source(root)
9999
.fields(fields)
100100
.nonNullFieldValidator(nonNullableFieldValidator)
101+
.path(ExecutionPath.rootPath())
101102
.build();
102103

103104
ExecutionResult result;

0 commit comments

Comments
 (0)