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
This commit is contained in:
rstoyanchev
2022-11-03 17:11:23 +00:00
parent 11fab7dafd
commit 02f96b6bf4
4 changed files with 23 additions and 11 deletions

View File

@@ -186,13 +186,16 @@ final class DefaultGraphQlClient implements GraphQlClient {
}
/**
* Return the field if valid, or {@code null} if {@code null} without errors.
* @throws FieldAccessException for invalid response or failed field
* Return the field or {@code null}, but only if the response is valid
* and there are no field errors, or raise {@link FieldAccessException}
* otherwise.
* @throws FieldAccessException in case of an invalid response or any
* field error at, above or below the field path
*/
@Nullable
protected ClientResponseField getValidField(ClientGraphQlResponse response) {
ClientResponseField field = response.field(this.path);
if (!response.isValid() || field.getError() != null) {
if (!response.isValid() || !field.getErrors().isEmpty()) {
throw new FieldAccessException(
((DefaultClientGraphQlResponse) response).getRequest(), response, field);
}

View File

@@ -191,8 +191,8 @@ public interface GraphQlClient {
* client.document("..").execute().map(response -> response.toEntity(..))
* </pre>
* @return a spec with decoding options
* @throws FieldAccessException if the target field has any errors,
* including nested errors.
* @throws FieldAccessException if the field has any field errors,
* including errors at, above or below the field path.
*/
RetrieveSpec retrieve(String path);

View File

@@ -133,7 +133,7 @@ public abstract class AbstractGraphQlResponse implements GraphQlResponse {
}
/**
* Return field errors whose path starts with the given field path.
* Return errors whose path is at, above, or below the given path.
* @param path the field path to match
* @return errors whose path starts with the dataPath
*/
@@ -144,7 +144,7 @@ public abstract class AbstractGraphQlResponse implements GraphQlResponse {
return response.getErrors().stream()
.filter(error -> {
String errorPath = error.getPath();
return !errorPath.isEmpty() && (errorPath.startsWith(path) || path.startsWith(errorPath));
return (!errorPath.isEmpty() && (errorPath.startsWith(path) || path.startsWith(errorPath)));
})
.collect(Collectors.toList());
}

View File

@@ -130,14 +130,23 @@ public class GraphQlClientTests extends GraphQlClientTestSupport {
}
@Test
void retrievePartialResponse() {
void retrieveFieldErrorAt() {
String document = "fieldErrorResponse";
getGraphQlService().setDataAsJsonAndErrors(document, "{\"me\": null}", errorForPath("/me"));
testRetrieveFieldAccessException(document, "me");
}
@Test // gh-499
void retrieveFieldErrorBelow() {
String document = "fieldErrorResponse";
getGraphQlService().setDataAsJsonAndErrors(document, "{\"me\": {\"name\":null}}", errorForPath("/me/name"));
testRetrieveFieldAccessException(document, "me");
}
MovieCharacter character = graphQlClient().document(document).retrieve("me").toEntity(MovieCharacter.class).block();
assertThat(character).isNotNull().extracting(MovieCharacter::getName).isNull();
@Test
void retrieveFieldErrorAbove() {
String document = "fieldErrorResponse";
getGraphQlService().setDataAsJsonAndErrors(document, "{\"me\": null}", errorForPath("/me"));
testRetrieveFieldAccessException(document, "me.name");
}