-
Notifications
You must be signed in to change notification settings - Fork 320
Description
tl dr: Is the code in the sample project a good or bad solution for handling RelayConnections wrapped by a union? It uses a solution similar to the existing ConnectionFieldTypeVisitor
.
Problem Description
Relay Pagination is supported in Spring Boot GraphQL so that in the following schema the integers
field will work correctly, but the integersUnion
field will not.
You can get a sample project here here: https://github.com/starJammer/spring-graphql-unions-pagination
The project's README.md file contains the everything I've written below as well.
The sample project includes the proposed solution below so it can be looked at in code.
You can start the sample project and see the resulting errors for yourself. (sample query below)
type Query {
""" returns a list of integers from 1 to 1000 """
integers(first: Int, after: String): IntegerConnection!
""" Same as above except the connection object is wrapped in a union """
integersUnion(first: Int, after: String): IntegerResult!
}
union IntegerResult = IntegerConnection | NoIntegersFound
type IntegerConnection {
edges: [IntegerEdge]!
pageInfo: PageInfo
}
type NoIntegersFound {
message: String!
}
type IntegerEdge {
node: Int
cursor: String
}
type PageInfo {
startCursor: String
endCursor: String
hasNextPage: Boolean
hasPreviousPage: Boolean
}
# Sample query
query Integers {
integersUnion {
__typename
... on IntegerConnection {
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
edges {
node
}
}
... on NoIntegersFound {
message
}
}
}
The resulting error returned from the integersUnion
field is:
{
"errors": [
{
"message": "The field at path '/integersUnion/edges' was declared as a non null type, but the code involved in retrieving data has wrongly returned a null value. The graphql specification requires that the parent field be set to null, or if that is non nullable that it bubble up null to its parent and so on. The non-nullable type is '[IntegerEdge]' within parent type 'IntegerConnection'",
"path": [
"integersUnion",
"edges"
],
"extensions": {
"classification": "NullValueInNonNullableField"
}
}
],
"data": null
}
Solution Description
Open the GraphQLUnionConfiguration.kt file in the project and go to line 23 and add uncomment it so the bean gets created. (make sure to uncomment the related import too at the top of the file)
Run the project again and attempt the query again and notice that it works. (or it should the last time I tested)
If you pass in a negative first
value you will see that the NoIntegersFound
object is returned instead of an IntegerConnection
.
GraphQLUnionConfiguration
will register the ConnectionUnderUnionTypeVisitor
I created in the project.
Read comments on the class for more details but in short it will:
- Look for union types being returned and in a decorator data fetcher.
- The decorator data fecher will execute the original data fetcher and if the return value
is aSliceWrapper
orWindowWrapper
it will adapt the return value to aConnection
object
the same way thatConnectionFieldTypeVisitor
does. It also adds a type resolver for the union
so it resolves the connection object to the Connection type.
Limitations:
- Does not support multiple connection objects under a union.
- Not sure if this is a good approach or if there is a better one.