leangen / graphql-spqr

Build a GraphQL service in seconds
Apache License 2.0
1.09k stars 181 forks source link

Non-null subscription publisher returns list instead of singular #458

Closed IceBlizz6 closed 1 year ago

IceBlizz6 commented 1 year ago

I believe i found a bug in PublisherAdapter.

Let's say you have a subscription that returns a non-null Publisher value.

@GraphQLSubscription
@GraphQLNonNull
public Publisher<Integer> tick() {
    ........
}

Then the call to unwrapList is called as expected.

if (operation.getOperationType() == OperationDefinition.Operation.SUBSCRIPTION) {
    return field.transform(builder -> builder.type(unwrapList(field.getType())));
}
private GraphQLOutputType unwrapList(GraphQLOutputType type) { 
    if (type instanceof GraphQLList) {
         return (GraphQLOutputType) ((GraphQLList) type).getWrappedType();
    }
    return type;
}

But the call just returns type. This is because GraphQLList is now wrapped in GraphQLNonNull So 'type instanceof GraphQLList' becomes false.

I made an attempt to include an additional check for GraphQLNonNull wrapper and it seems to work. Code is a bit messy though, but hopefully it gives you the idea for a solution.

private GraphQLOutputType unwrapList(GraphQLOutputType type) {
    if (type instanceof GraphQLNonNull) {
        var wrapped = ((GraphQLNonNull) type).getWrappedType();
        if (wrapped instanceof GraphQLList) {
            return (GraphQLOutputType) ((GraphQLList) wrapped).getWrappedType();
        }
    } else if (type instanceof GraphQLList) {
        return (GraphQLOutputType) ((GraphQLList) type).getWrappedType();
    }
    return type;
}
IceBlizz6 commented 1 year ago

I spent many hours investigating this issue. I'm using Kotlin so Publisher return type is non-null by default unless i explicitly add the question mark in the type (Publisher<..>?)

I think the people using java may be happy for a fix here too though.

kaqqao commented 1 year ago

Nice catch! Will fix!