diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/pagination/ConnectionFieldTypeVisitor.java b/spring-graphql/src/main/java/org/springframework/graphql/data/pagination/ConnectionFieldTypeVisitor.java index b2b2bf66..1cec047f 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/pagination/ConnectionFieldTypeVisitor.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/pagination/ConnectionFieldTypeVisitor.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.concurrent.CompletionStage; import graphql.TrivialDataFetcher; +import graphql.execution.DataFetcherResult; import graphql.relay.Connection; import graphql.relay.DefaultConnection; import graphql.relay.DefaultConnectionCursor; @@ -189,17 +190,30 @@ public final class ConnectionFieldTypeVisitor extends GraphQLTypeVisitorStub { public Object get(DataFetchingEnvironment environment) throws Exception { Object result = this.delegate.get(environment); if (result instanceof Mono mono) { - return mono.map(this::adapt); + return mono.map(this::adaptDataFetcherResult); } else if (result instanceof CompletionStage stage) { - return stage.thenApply(this::adapt); + return stage.thenApply(this::adaptDataFetcherResult); } else { - return adapt(result); + return adaptDataFetcherResult(result); } } - private Object adapt(@Nullable Object container) { + private Object adaptDataFetcherResult(@Nullable Object value) { + if (value instanceof DataFetcherResult dataFetcherResult) { + Object adapted = adaptDataContainer(dataFetcherResult.getData()); + return DataFetcherResult.newResult() + .data(adapted) + .errors(dataFetcherResult.getErrors()) + .localContext(dataFetcherResult.getLocalContext()).build(); + } + else { + return adaptDataContainer(value); + } + } + + private Object adaptDataContainer(@Nullable Object container) { if (container == null) { return EMPTY_CONNECTION; } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/pagination/ConnectionFieldTypeVisitorTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/pagination/ConnectionFieldTypeVisitorTests.java index 6412b8fd..389ccf63 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/pagination/ConnectionFieldTypeVisitorTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/pagination/ConnectionFieldTypeVisitorTests.java @@ -18,7 +18,9 @@ package org.springframework.graphql.data.pagination; import java.util.Collection; import java.util.List; +import java.util.function.Consumer; +import graphql.execution.DataFetcherResult; import graphql.schema.DataFetcher; import graphql.schema.FieldCoordinates; import graphql.schema.GraphQLFieldDefinition; @@ -52,36 +54,41 @@ public class ConnectionFieldTypeVisitorTests { @Test - void paginatedTypeIsAdapted() { + void adaptPaginatedType() { - ListConnectionAdapter adapter = new ListConnectionAdapter(); - adapter.setInitialOffset(30); - adapter.setHasNext(true); + Consumer> testConsumer = booksDataFetcher -> { + ListConnectionAdapter adapter = new ListConnectionAdapter(); + adapter.setInitialOffset(30); + adapter.setHasNext(true); - Mono response = GraphQlSetup.schemaResource(BookSource.paginationSchema) - .dataFetcher("Query", "books", env -> BookSource.books()) - .connectionSupport(adapter) - .toGraphQlService() - .execute(BookSource.booksConnectionQuery(null)); + Mono response = GraphQlSetup.schemaResource(BookSource.paginationSchema) + .dataFetcher("Query", "books", booksDataFetcher) + .connectionSupport(adapter) + .toGraphQlService() + .execute(BookSource.booksConnectionQuery(null)); - ResponseHelper.forResponse(response).assertData( - "{\"books\":{" + - "\"edges\":[" + - "{\"cursor\":\"O_30\",\"node\":{\"id\":\"1\",\"name\":\"Nineteen Eighty-Four\"}}," + - "{\"cursor\":\"O_31\",\"node\":{\"id\":\"2\",\"name\":\"The Great Gatsby\"}}," + - "{\"cursor\":\"O_32\",\"node\":{\"id\":\"3\",\"name\":\"Catch-22\"}}," + - "{\"cursor\":\"O_33\",\"node\":{\"id\":\"4\",\"name\":\"To The Lighthouse\"}}," + - "{\"cursor\":\"O_34\",\"node\":{\"id\":\"5\",\"name\":\"Animal Farm\"}}," + - "{\"cursor\":\"O_35\",\"node\":{\"id\":\"53\",\"name\":\"Breaking Bad\"}}," + - "{\"cursor\":\"O_36\",\"node\":{\"id\":\"42\",\"name\":\"Hitchhiker's Guide to the Galaxy\"}}" + - "]," + - "\"pageInfo\":{" + - "\"startCursor\":\"O_30\"," + - "\"endCursor\":\"O_36\"," + - "\"hasPreviousPage\":true," + - "\"hasNextPage\":true}" + - "}}" - ); + ResponseHelper.forResponse(response).assertData( + "{\"books\":{" + + "\"edges\":[" + + "{\"cursor\":\"O_30\",\"node\":{\"id\":\"1\",\"name\":\"Nineteen Eighty-Four\"}}," + + "{\"cursor\":\"O_31\",\"node\":{\"id\":\"2\",\"name\":\"The Great Gatsby\"}}," + + "{\"cursor\":\"O_32\",\"node\":{\"id\":\"3\",\"name\":\"Catch-22\"}}," + + "{\"cursor\":\"O_33\",\"node\":{\"id\":\"4\",\"name\":\"To The Lighthouse\"}}," + + "{\"cursor\":\"O_34\",\"node\":{\"id\":\"5\",\"name\":\"Animal Farm\"}}," + + "{\"cursor\":\"O_35\",\"node\":{\"id\":\"53\",\"name\":\"Breaking Bad\"}}," + + "{\"cursor\":\"O_36\",\"node\":{\"id\":\"42\",\"name\":\"Hitchhiker's Guide to the Galaxy\"}}" + + "]," + + "\"pageInfo\":{" + + "\"startCursor\":\"O_30\"," + + "\"endCursor\":\"O_36\"," + + "\"hasPreviousPage\":true," + + "\"hasNextPage\":true}" + + "}}" + ); + }; + + testConsumer.accept(env -> BookSource.books()); + testConsumer.accept(env -> DataFetcherResult.newResult().data(BookSource.books()).build()); } @Test // gh-709