Repository navigation
graphql.AssertException when using graphql-java-tools (5.6.1) with apollo federation-jvm #300
Description
Hi
I'm trying to use apollo federation-jvm together with graphql-java-tools (5.6.1)
https://github.com/apollographql/federation-jvm
This is a library that "federate" graphql-java schema so that this schema can be used later by apollo federation gateway.
https://www.apollographql.com/docs/apollo-server/federation/introduction/
federation-jvm works with graphql-java but does not work with graphql-java-tools.
When I try to run it with graphql-java-tools i got an error:
Caused by: graphql.AssertException: All types within a GraphQL schema must have unique names. No two provided types may have the same name.
No provided type may have a name which conflicts with any built in types (including Scalar and Introspection types).
You have redefined the type 'Query' from being a 'GraphQLObjectType' to a 'GraphQLObjectType'
at graphql.schema.GraphQLTypeCollectingVisitor.assertTypeUniqueness(GraphQLTypeCollectingVisitor.java:105) ~[graphql-java-13.0.jar:na]
at graphql.schema.GraphQLTypeCollectingVisitor.visitGraphQLObjectType(GraphQLTypeCollectingVisitor.java:38) ~[graphql-java-13.0.jar:na]
at graphql.schema.GraphQLObjectType.accept(GraphQLObjectType.java:174) ~[graphql-java-13.0.jar:na]
at graphql.schema.TypeTraverser$TraverserDelegateVisitor.enter(TypeTraverser.java:71) ~[graphql-java-13.0.jar:na]
at graphql.util.Traverser.traverse(Traverser.java:147) ~[graphql-java-13.0.jar:na]
at graphql.schema.TypeTraverser.doTraverse(TypeTraverser.java:58) ~[graphql-java-13.0.jar:na]
at graphql.schema.TypeTraverser.depthFirst(TypeTraverser.java:50) ~[graphql-java-13.0.jar:na]
at graphql.schema.TypeTraverser.depthFirst(TypeTraverser.java:38) ~[graphql-java-13.0.jar:na]
at graphql.schema.SchemaUtil.allTypes(SchemaUtil.java:42) ~[graphql-java-13.0.jar:na]
at graphql.schema.GraphQLSchema.<init>(GraphQLSchema.java:102) ~[graphql-java-13.0.jar:na]
at graphql.schema.GraphQLSchema.<init>(GraphQLSchema.java:37) ~[graphql-java-13.0.jar:na]
at graphql.schema.GraphQLSchema$Builder.build(GraphQLSchema.java:411) ~[graphql-java-13.0.jar:na]
at com.apollographql.federation.graphqljava.SchemaTransformer.build(SchemaTransformer.java:134) ~[classes/:na]
As I investigated this is because when graphql-java-tools creates schema it passes every type as additionalTypes.
See SchemaParser.kt line 129
return SchemaObjects(query, mutation, subscription, (objects + inputObjects + enums + interfaces + unions).toSet(), codeRegistryBuilder)
4th argument is used as additionalTypes and graphql-java-tools puts every type in it including "Query" type.
In graphql-java additionalTypes are only types that are not referenced from the top level operations.
See SchemaGenerator.java (graphq-java 13.0) line 362
/**
* We build the query / mutation / subscription path as a tree of referenced types
* but then we build the rest of the types specified and put them in as additional types
*
* @param buildCtx the context we need to work out what we are doing
*
* @return the additional types not referenced from the top level operations
*/
private Set<GraphQLType> buildAdditionalTypes(BuildContext buildCtx) {
To get example that does not work:
use federation-jvm example
https://github.com/apollographql/federation-jvm/tree/master/spring-example/src/main/java/com/apollographql/federation/springexample
with modifications:
- add graphql-java-tools 5.6.1 to pom.xml
- simplify graphql schema in inventory.graphql to
type Query {
aQuery: String!
}
- add simple resolver for this query
package com.apollographql.federation.springexample;
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
public class QueryResolver implements GraphQLQueryResolver {
public String aQuery() {
return "aValue";
}
}
- modify InventorySchemaProvider class:
@Component
public class InventorySchemaProvider extends DefaultGraphQLSchemaProvider implements
GraphQLSchemaProvider {
public InventorySchemaProvider(@Value("classpath:schemas/inventory.graphql") Resource sdl) throws Exception {
super(Federation.transform(buildSchema(sdl)).build());
}
private static GraphQLSchema buildSchema(Resource sdl) throws Exception {
SchemaParserBuilder parserBuilder = com.coxautodev.graphql.tools.SchemaParser.newParser();
parserBuilder.schemaString(CharStreams.toString(new InputStreamReader(sdl.getInputStream(), UTF_8)));
parserBuilder.resolvers(new QueryResolver());
return parserBuilder.build().makeExecutableSchema();
}
}
Activity
larslorenzen commentedon Sep 7, 2019
Hi, got the same problem when trying to use graphql-java-tools and federation-jvm in a ktor project.
Reduced it to the minimum amount of code:
it fails with the same exception.
gabrielbs commentedon Sep 23, 2019
I'm getting the same running the federation example
hendryluk commentedon Oct 23, 2019
Same for me too :(
hendryluk commentedon Oct 23, 2019
I've debugged into this and found what seems to be the problem:
GraphQLSchema that gets generated seems to have additionalTypes that includes the Query and Mutation objects (i.e. it duplicates schema.getQueryType() and schema.getMutationType()).
This causes the said exception whenever another library attempts to build another schema on top of it i.e. via GraphQLSchema.newSchema(schema).build(), because it would detect the duplication
hendryluk commentedon Oct 23, 2019
The workaround is to clear the additionalTypes before you pass it into Federation.transform, i.e.: schema = GraphQLSchema.newSchema(schema).clearAdditionalTypes().build()
Improve Schema Transformation
Improve Schema Transformation
Improve Schema Transformation