Skip to content

Commit 02f96b6

Browse files
committed
Raise exception for any field error in retrieve
This commit aligns the behavior of retrieve with its Javadoc such that any field error, including errors on nested fields, raises a FieldAccessException Closes gh-499
1 parent 11fab7d commit 02f96b6

File tree

4 files changed

+23
-11
lines changed

4 files changed

+23
-11
lines changed

Diff for: spring-graphql/src/main/java/org/springframework/graphql/client/DefaultGraphQlClient.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,16 @@ protected RetrieveSpecSupport(String path) {
186186
}
187187

188188
/**
189-
* Return the field if valid, or {@code null} if {@code null} without errors.
190-
* @throws FieldAccessException for invalid response or failed field
189+
* Return the field or {@code null}, but only if the response is valid
190+
* and there are no field errors, or raise {@link FieldAccessException}
191+
* otherwise.
192+
* @throws FieldAccessException in case of an invalid response or any
193+
* field error at, above or below the field path
191194
*/
192195
@Nullable
193196
protected ClientResponseField getValidField(ClientGraphQlResponse response) {
194197
ClientResponseField field = response.field(this.path);
195-
if (!response.isValid() || field.getError() != null) {
198+
if (!response.isValid() || !field.getErrors().isEmpty()) {
196199
throw new FieldAccessException(
197200
((DefaultClientGraphQlResponse) response).getRequest(), response, field);
198201
}

Diff for: spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlClient.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,8 @@ interface RequestSpec {
191191
* client.document("..").execute().map(response -> response.toEntity(..))
192192
* </pre>
193193
* @return a spec with decoding options
194-
* @throws FieldAccessException if the target field has any errors,
195-
* including nested errors.
194+
* @throws FieldAccessException if the field has any field errors,
195+
* including errors at, above or below the field path.
196196
*/
197197
RetrieveSpec retrieve(String path);
198198

Diff for: spring-graphql/src/main/java/org/springframework/graphql/support/AbstractGraphQlResponse.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ private static Object initFieldValue(List<Object> path, GraphQlResponse response
133133
}
134134

135135
/**
136-
* Return field errors whose path starts with the given field path.
136+
* Return errors whose path is at, above, or below the given path.
137137
* @param path the field path to match
138138
* @return errors whose path starts with the dataPath
139139
*/
@@ -144,7 +144,7 @@ private static List<ResponseError> initFieldErrors(String path, GraphQlResponse
144144
return response.getErrors().stream()
145145
.filter(error -> {
146146
String errorPath = error.getPath();
147-
return !errorPath.isEmpty() && (errorPath.startsWith(path) || path.startsWith(errorPath));
147+
return (!errorPath.isEmpty() && (errorPath.startsWith(path) || path.startsWith(errorPath)));
148148
})
149149
.collect(Collectors.toList());
150150
}

Diff for: spring-graphql/src/test/java/org/springframework/graphql/client/GraphQlClientTests.java

+13-4
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,23 @@ void retrieveInvalidResponse() {
130130
}
131131

132132
@Test
133-
void retrievePartialResponse() {
133+
void retrieveFieldErrorAt() {
134+
String document = "fieldErrorResponse";
135+
getGraphQlService().setDataAsJsonAndErrors(document, "{\"me\": null}", errorForPath("/me"));
136+
testRetrieveFieldAccessException(document, "me");
137+
}
134138

139+
@Test // gh-499
140+
void retrieveFieldErrorBelow() {
135141
String document = "fieldErrorResponse";
136142
getGraphQlService().setDataAsJsonAndErrors(document, "{\"me\": {\"name\":null}}", errorForPath("/me/name"));
143+
testRetrieveFieldAccessException(document, "me");
144+
}
137145

138-
MovieCharacter character = graphQlClient().document(document).retrieve("me").toEntity(MovieCharacter.class).block();
139-
assertThat(character).isNotNull().extracting(MovieCharacter::getName).isNull();
140-
146+
@Test
147+
void retrieveFieldErrorAbove() {
148+
String document = "fieldErrorResponse";
149+
getGraphQlService().setDataAsJsonAndErrors(document, "{\"me\": null}", errorForPath("/me"));
141150
testRetrieveFieldAccessException(document, "me.name");
142151
}
143152

0 commit comments

Comments
 (0)