graphql-java-tools
graphql-java-tools copied to clipboard
SchemaClassScanner doesn't scan directive arguments
Description
Custom scalars and input objects used in directives are not scanned, and subsequently their type cannot be determined when building directives in SchemaParser
Expected behavior
scalar CustomScalar
directive @something(arg: CustomScalar) on FIELD_DEFINITION
type Query {
allProducts: [Product]
}
type Product {
name: String @something(arg: "1")
}
Should parse successfully
Actual behavior
graphql.kickstart.tools.SchemaError: Expected type 'CustomScalar' to be a GraphQLInputType, but it wasn't! Was a type only permitted for object types incorrectly used as an input type, or vice-versa?
This causes apollo-federated schemas to fail because _FieldSet
is only used in directives.
Caused by: graphql.kickstart.tools.SchemaError: Expected type '_FieldSet' to be a GraphQLInputType, but it wasn't! Was a type only permitted for object types incorrectly used as an input type, or vice-versa?
at graphql.kickstart.tools.SchemaParser.determineType(SchemaParser.kt:355) ~[graphql-java-tools-13.0.0.jar:na]
at graphql.kickstart.tools.SchemaParser.determineInputType(SchemaParser.kt:373) ~[graphql-java-tools-13.0.0.jar:na]
at graphql.kickstart.tools.SchemaParser.determineInputType(SchemaParser.kt:365) ~[graphql-java-tools-13.0.0.jar:na]
at graphql.kickstart.tools.SchemaParser.createDirective(SchemaParser.kt:307) ~[graphql-java-tools-13.0.0.jar:na]
at graphql.kickstart.tools.SchemaParser.parseSchemaObjects(SchemaParser.kt:83) ~[graphql-java-tools-13.0.0.jar:na]
at graphql.kickstart.tools.SchemaParser.makeExecutableSchema(SchemaParser.kt:110) ~[graphql-java-tools-13.0.0.jar:na]
this can be reproduced with:
package test;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Test;
import graphql.GraphQL;
import graphql.kickstart.tools.GraphQLQueryResolver;
import graphql.kickstart.tools.SchemaParser;
import graphql.kickstart.tools.SchemaParserBuilder;
import graphql.scalar.GraphqlStringCoercing;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.GraphQLScalarType;
import graphql.schema.GraphQLSchema;
public class IssueTest {
static class MockQueryResolver implements GraphQLQueryResolver {
public String mockField(String input, DataFetchingEnvironment environment) {
return null;
}
};
@Test
public void testUsedInField() {
// this passes
graphQl(
"scalar MockScalar",
"directive @mockDirective(arg: MockScalar) on FIELD_DEFINITION",
"type Query {",
" mockField(input: MockScalar): String @mockDirective(arg: \"mock-value\")",
"}"
);
}
@Test
public void testUsedOnlyInDirectives() {
// this fails with:
// graphql.kickstart.tools.SchemaError: Expected type 'MockScalar' to be
// a GraphQLInputType, but it wasn't! Was a type only permitted for
// object types incorrectly used as an input type, or vice-versa?
graphQl(
"scalar MockScalar",
"directive @mockDirective(arg: MockScalar) on FIELD_DEFINITION",
"type Query {",
" mockField(input: String) : String @mockDirective(arg: \"mock-value\")",
"}"
);
}
private GraphQL graphQl(String... sdl) {
SchemaParserBuilder builder = new SchemaParserBuilder();
builder.schemaString(Stream.of(sdl).collect(Collectors.joining("\n")));
SchemaParser schemaParser = builder
.resolvers(new MockQueryResolver())
.scalars(GraphQLScalarType.newScalar()
.name("MockScalar")
.coercing(new GraphqlStringCoercing())
.build()
)
.build();
GraphQLSchema schema = schemaParser.makeExecutableSchema();
return GraphQL.newGraphQL(schema).build();
}
}
@oryan-block is this easy to fix? i never coded in kotlin but if you give me a few pointers I can give it a shot.
Unfortunately because of the way the scanner works and how different directives are from everything else, this is not a trivial fix.
#725
This should be partially resolved by #763 for scalars. However, directives with input object arguments/parameters are still not supported (this was the case even before the applied directives change)
@oryan-block Any updates on this or work arounds?
This should be partially resolved by #763 for scalars. However, directives with input object arguments/parameters are still not supported (this was the case even before the applied directives change)
@airvine-r7 that fix is merged. You can test it now. #764 is a more complete solution I think should make directives fully supported.