-
Notifications
You must be signed in to change notification settings - Fork 31
Description
Describe the bug
When I use orchestrator and merge two subgraphs with Apollo Federation Directives as given below ,
String inventorySchema = "type Product @key(fields: \"upc\") @extends {\n" +
" upc: String! @external\n" +
" weight: Int @external\n" +
" price: Int @external\n" +
" inStock: Boolean\n" +
" shippingEstimate: Int @requires(fields: \"price weight\")\n" +
"}";
String productSchema = "type Query {\n" +
" topProducts(first: Int = 5): [Product]\n" +
" productB (upc : String!): Product\n" +
"}\n" +
"\n" +
"type Product @key(fields: \"upc\") {\n" +
" upc: String!\n" +
" name: String\n" +
" price: Int\n" +
" weight: Int\n" +
"}\n";
String reviewSchema = "type Review @key(fields: \"id\") {\n" +
" id: ID!\n" +
" body: String\n" +
" product: Product @resolver(field:\"productB\", arguments: [{name : \"upc\", value: \"UPC001\"}])\n" +
"}\n" +
"\n" +
"type User @key(fields: \"id\") @extends {\n" +
" id: ID! @external\n" +
" username: String @external\n" +
" reviews: [Review]\n" +
"}\n" +
"\n" +
"type Product @key(fields: \"upc\") @extends {\n" +
" upc: String! @external\n" +
" reviews: [Review]\n" +
"}\n" +
"\n" +
"# ================================\n" +
"# define this as built-in directive\n" +
"directive @resolver(field: String!, arguments: [ResolverArgument!]) on FIELD_DEFINITION\n" +
"\n" +
"# define this as built-in type\n" +
"input ResolverArgument {\n" +
" name : String!\n" +
" value : String!\n" +
"}";
String userSchema = "type Query {\n" +
" me: User\n" +
"}\n" +
"\n" +
"type User @key(fields: \"id\") {\n" +
" id: ID!\n" +
" name: String\n" +
" username: String\n" +
"}";
// Creating providers for your GraphQL services
GenericProvider inventoryService = new GenericProvider("http://localhost:8084/graphql", httpClient,
inventorySchema, "inventory");
GenericProvider productService = new GenericProvider("http://localhost:8081/graphql", httpClient,
productSchema, "product");
GenericProvider reviewService = new GenericProvider("http://localhost:8083/graphql", httpClient,
reviewSchema, "review");
GenericProvider accountService = new GenericProvider("http://localhost:8082/graphql", httpClient,
userSchema, "user");
RuntimeGraph runtimeGraph = SchemaStitcher.newBuilder()
.service(accountService)
.service(productService)
.service(inventoryService)
.service(reviewService)
.build()
.stitchGraph();
The stitched Schema when output through
String printSchema = new SchemaPrinter().print(runtimeGraph.getExecutableSchema());
System.out.println(printSchema);
produces the output
"Directs the executor to include this field or fragment only when the `if` argument is true"
directive @include(
"Included when true."
if: Boolean!
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
"Directs the executor to skip this field or fragment when the `if`'argument is true."
directive @skip(
"Skipped when true."
if: Boolean!
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @provides(fields: String!) on FIELD_DEFINITION
"Exposes a URL that specifies the behaviour of this scalar."
directive @specifiedBy(
"The URL that specifies the behaviour of this scalar."
url: String!
) on SCALAR
directive @extends on OBJECT | INTERFACE
directive @deprecated(reason: String = "No longer supported") on FIELD_DEFINITION | ENUM_VALUE
directive @key(fields: _FieldSet) repeatable on OBJECT | INTERFACE
directive @requires(fields: _FieldSet!) on FIELD_DEFINITION
directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @tag(name: String!) repeatable on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
directive @external on FIELD_DEFINITION
"[product]"
type Product {
inStock: Boolean
name: String
price: Int
reviews: [Review]
shippingEstimate: Int
upc: String!
weight: Int
}
"[]"
type Query {
_namespace: String
me: User
productB(upc: String!): Product
topProducts(first: Int = 5): [Product]
}
"[review]"
type Review @key(fields : "id") {
body: String
id: ID!
product: Product @resolver(arguments : [{name : "upc", value : "UPC001"}], field : "productB")
}
"[user]"
type User {
id: ID!
name: String
reviews: [Review]
username: String
}
"A selection set"
scalar _FieldSet
"[review]"
input ResolverArgument {
name: String!
value: String!
}
When this is parsed
SchemaParser parser = new SchemaParser();
TypeDefinitionRegistry typeDefinitionRegistry = parser.parse(Paths.get("src/main/resources/supergraph.graphqls").toFile());
RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring().build();
GraphQLSchema federatedSchema = Federation.transform(typeDefinitionRegistry, runtimeWiring)
.build();
System.out.println(federatedSchema);
There are multiple issues that arise as below ,
SchemaProblem{errors=['product' [@50:3] tried to use an undeclared directive 'resolver']}
SchemaProblem{errors=['include' type [@28:1] tried to redefine existing directive 'include' type [@1:1], 'skip' type [@30:1] tried to redefine existing directive 'skip' type [@6:1]]}
When I remove the duplicate entries for @include and @Skip and add the
directive @resolver(field: String!, arguments: [ResolverArgument!]) on FIELD_DEFINITION
the validation is successful
Can you please let me know how this can be fixed.
I further want to know if this stitched graph can be considered and treated as a supergraph similar to the one in APOLLO Federation.