leangen / graphql-spqr

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

SDL Printing Fails on Schema Directives with Arguments #482

Open sheppaga opened 6 months ago

sheppaga commented 6 months ago

Hi SPQR team / @kaqqao!

First, I'd like to say thanks for building such an incredible library. It is a really cool and powerful tool.

I am not sure if this bug pertains to just graphql-spqr-spring-boot-starter:1.0.0, graphql-spqr, or even graphql-java as a whole. I am trying to use graphql-java's schemaPrinter with the spqr generated schema:

    @Bean
    public GraphQL graphQL() {
        GraphQL gql =  GraphQL.newGraphQL(graphQLSchema())
        .build();

        SchemaPrinter schemaPrinter = new SchemaPrinter();
        String printedSchema = schemaPrinter.print(gql.getGraphQLSchema());
        System.out.println(printedSchema);

        return gql;
    }

This fails when I include a schema directive with an argument. If this is added, the SDL Printer fails:

@GraphQLDirective(name = "key")
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Key {
    String fields() default ""; //However, directives without arguments work. If I remove this line, SDL will print successfully 
}

Here is the error I am getting:

Caused by: graphql.AssertException: Internal error: should never happen: unexpected type GraphQLTypeReference{name='String'}
    at graphql.Assert.assertShouldNeverHappen(Assert.java:53)
    at graphql.execution.ValuesResolver.externalValueToLiteral(ValuesResolver.java:292)
    at graphql.execution.ValuesResolver.valueToLiteral(ValuesResolver.java:226)
    at graphql.execution.ValuesResolver.valueToLiteral(ValuesResolver.java:212)
    at graphql.execution.ValuesResolver.valueToLiteral(ValuesResolver.java:197)
    at graphql.schema.idl.SchemaPrinter.printAst(SchemaPrinter.java:719)
    at graphql.schema.idl.SchemaPrinter.directiveString(SchemaPrinter.java:898)
    at graphql.schema.idl.SchemaPrinter.directivesString(SchemaPrinter.java:862)
    at graphql.schema.idl.SchemaPrinter.directivesString(SchemaPrinter.java:832)
    at graphql.schema.idl.SchemaPrinter.directivesString(SchemaPrinter.java:827)
    at graphql.schema.idl.SchemaPrinter.lambda$objectPrinter$8(SchemaPrinter.java:626)
    at graphql.schema.idl.SchemaPrinter.printSchemaElement(SchemaPrinter.java:1013)
    at graphql.schema.idl.SchemaPrinter.print(SchemaPrinter.java:446)

Thanks in advance for your help. I am extremely motivated to solve this problem as it is blocking me from implementing Apollo federation. If I should post this in another repo like graphql-java, or there is anything else I can do, please let me know.

kaqqao commented 6 months ago

Ugh. graphql-java historically had a ton of issues with leaving type references unresolved, especially around directives (and it was usually me discovering and fixing those 😇), and this certainly smells like one of those. But, I can't rule out SPQR doing something wrong just yet. I'll have to investigate a bit. I'll try to poke around today.

kaqqao commented 6 months ago

Btw any chance you can reproduce this with a small example? That would help immensely... But I fear it won't be exactly easy to reproduce at will, as these bugs are all about the order in which types are discovered. So in a different schema it would simply not manifest... Still, it shouldn't be too difficult either.

sheppaga commented 6 months ago

Thanks so much for looking into this! Really appreciate it. I am currently working on building a smaller sample project so I can share with you.

sheppaga commented 6 months ago

Hey @kaqqao, I found it was relatively straight forward to reproduce the problem in a basic Springboot 2.7.0 project. Here is the link.

Once again, greatly appreciate your help! Please let me know if there's anything else I can do to support this fix.