-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Support returning DataFetcherResult from subscriptions #1795
Description
Describe the bug
In graphql-java, a subscription must return a Publisher<T> from its data fetcher. This is enforced by the SubscriptionExecutionStrategy here:
graphql-java/src/main/java/graphql/execution/SubscriptionExecutionStrategy.java
Lines 70 to 77 in 101dc6c
| CompletableFuture<FetchedValue> fieldFetched = fetchField(executionContext, newParameters); | |
| return fieldFetched.thenApply(fetchedValue -> { | |
| Object publisher = fetchedValue.getFetchedValue(); | |
| if (publisher != null) { | |
| assertTrue(publisher instanceof Publisher, "You data fetcher must return a Publisher of events when using graphql subscriptions"); | |
| } | |
| //noinspection unchecked | |
| return (Publisher<Object>) publisher; |
Just before the check for a type of Publisher, graphql-java calls the base ExecutionStrategy.fetchField. In that method, it checks if the result is of type DataFetcherResult and if it is, unboxes it:
graphql-java/src/main/java/graphql/execution/ExecutionStrategy.java
Lines 300 to 302 in 101dc6c
| if (result instanceof DataFetcherResult) { | |
| //noinspection unchecked | |
| DataFetcherResult<?> dataFetcherResult = (DataFetcherResult) result; |
That means however that the object passed to fetchField is a Publisher so it will never unbox a DataFetcherResult.
To support partial results, a second check in the SubscriptionExecutionStrategy after unboxing the Publisher, should be added to check for a DataFetcherResult again. With some refactoring of the base ExecutionStrategy some of the existing code could be used to do this.
The GraphQL spec does allow subscription to return data and errors in a single message: https://spec.graphql.org/June2018/#sec-Response-Stream
To Reproduce
Create a subscription that returns a Publisher<DataFetcherResult<T>> and it fails to parse the proper data and errors fields.
Related Issues
This was brought to our attention in graphql-kotlin ExpediaGroup/graphql-kotlin#608