-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support excluding directives in FederationSdlPrinter #79 #80
support excluding directives in FederationSdlPrinter #79 #80
Conversation
@ankit-joinwal: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Apollo Contributor License Agreement here: https://contribute.apollographql.com/ |
@ankit-joinwal
To make sure I understand, it sounds like you're saying that SQPR is creating a graphql-java This creates a particular issue, namely that the corresponding schema for that
And Section 3.13 of the spec covers directives in a schema:
That last part would presumably imply that directives must have definitions (otherwise they would have no locations). It's clear at least that this section covers the usage of type-system directives, as it later mentions:
Lee Byron, when asked about whether directive definitions need to exist for directives in schema SDL and whether locations need to match, makes this comment:
So from this, it looks like the schema for the It's worth noting that creating a One way to produce a valid schema here is to provide a directive definition (
Could you point to the specific portion of GraphQL spec you're talking about? I'm assuming you're talking about schema introspection here, so the relevant part of spec is Section 4.5.6:
This section though doesn't talk about restricting which directives are visible via introspection to just those that are "server-side" (by which, I presume you mean directives that are only valid on Another point worth noting is that federation doesn't use introspection to communicate schemas with Apollo Gateway, but instead exposes the schema by adding a new GraphQL field to the implementing service, specifically
It's worth noting here that "server-side" directives aren't exposed to clients by Apollo Gateway. Specifically, gateway's composition algorithm strips them out of the composed schema (in the Apollo docs, "server-side" directives are called type-system directives, to align more closely with spec language). This means that clients won't see such directive usages or definitions. Another relevant detail is that the Apollo federation programming model is predicated around implementing services remaining internal/not publicly accessible. This is because the Given this, my recommendation would be to add GraphQL definitions ( |
Thanks for the detailed response.
Yes i was talking about introspection. Two things from my side:
From SPQR standpoint, not every SPQR service will be exposed via Apollo Gateway so it makes sense for SPQR to have that protection for server side directives. In your view, does this Pull request violate any specification or principles of federation-jvm? |
@ankit-joinwal
When you say "removes those directives from introspection", I'm guessing the reason for this is because the While this is a clever way to avoid exposing those directives via introspection, it results in a
The user benefit is unclear. Type-system directive usages and definitions are already removed by gateway, and adding another place to do so adds a layer of complexity for little value other than supporting spec-invalid schemas (which we generally don't want to encourage), for which it looks like To be specific, developers would need to consider which directives to remove and why, and keep track of which directives those are while developing and debugging. This also creates a divergence between what schema is being executed by the server, and which schema is presented to gateway. For users tracking their schema in Apollo Studio (e.g. for managed federation), this difference would appear there as well and hinder observability.
That PR doesn't exclude both usages and definitions, but instead just definitions. That is because Apollo Gateway will add these definitions itself, and validation will still fail if usages don't match those definitions. (As an aside, this is a bug in Apollo Gateway that we intend to eventually fix; we'd like to eventually arrive at a world where
Could you elaborate here? I'm not sure in what way SPQR hiding certain directives from introspection facilitates an efficient code-first approach, especially given it involves the use of a spec-invalid schema. Producing spec-invalid schemas hurts interoperability with other libraries, which is what we're seeing here firsthand.
Two things here:
If there is a need to keep these directive usages and definitions private, I would recommend finding an alternative means to embedding the metadata so that the library may remain spec-compliant while maintaining privacy.
Given the above (namely that there's not a clear user benefit), I don't see the need for the added complexity and mental overhead for developers. If SPQR does not wish to add directive definitions to its |
Thanks @sachindshinde for clarifying on the questions.
What I meant by efficient code-first approach is that SPQR provides annotations which help a lot in developing GraphQL services quickly. More info here
This needs to be answered by the developer of SPQR library . I can only relay information what is present in leangen/graphql-spqr#290
I do not understand this. The directives and their definition have been defined in SPQR library. How can we add directive definitions for the directives already defined and part of SPQR library. Can you elaborate on this?
The @_mappedType and @_mappedOperation have been added by SPQR library and their definitions reside inside SPQR library. I understand that this Pull Request may not be merged which leaves us blocked in using federation with SPQR. |
Ah, you mean Java annotations. I don't think that part would need to change for SPQR to generate spec-valid schemas.
Let's look at the example in their README.md: UserService userService = new UserService();
GraphQLSchema schema = new GraphQLSchemaGenerator()
.withBasePackages("io.leangen")
.withOperationsFromSingleton(userService)
.generate();
GraphQL graphQL = new GraphQL.Builder(schema)
.build(); You'll need to modify the How the directive usages are generated is described in // UNREPRESENTABLE scalar
GraphQLScalarType unrepresentableScalar = (GraphQLScalarType) schema.getType("UNREPRESENTABLE");
// _mappedType directive definition
GraphQLDirective mappedTypeDirective = GraphQLDirective.newDirective()
.name("_mappedType")
.description("")
.validLocation(Introspection.DirectiveLocation.OBJECT)
.argument(GraphQLArgument.newArgument()
.name("type")
.description("")
.type(unrepresentableScalar)
.build()
)
.build();
// _mappedOperation directive definition
GraphQLDirective mappedOperationDirective = GraphQLDirective.newDirective()
.name("_mappedOperation")
.description("")
.validLocation(Introspection.DirectiveLocation.FIELD_DEFINITION)
.argument(GraphQLArgument.newArgument()
.name("operation")
.description("")
.type(unrepresentableScalar)
.build()
)
.build();
// _mappedInputField directive definition
GraphQLDirective mappedInputFieldDirective = GraphQLDirective.newDirective()
.name("_mappedInputField")
.description("")
.validLocation(Introspection.DirectiveLocation.INPUT_FIELD_DEFINITION)
.argument(GraphQLArgument.newArgument()
.name("inputField")
.description("")
.type(unrepresentableScalar)
.build()
)
.build();
// Add new definitions to schema
GraphQLSchema newSchema = GraphQLSchema.newSchema(schema)
.additionalDirective(mappedTypeDirective)
.additionalDirective(mappedOperationDirective)
.additionalDirective(mappedInputFieldDirective)
.build(); The |
Thanks @sachindshinde for patiently working with me on the resolution. I have tried above code and it works well with Gateway. So, even though i am not sure if this is the correct way of doing things with SPQR (means providing the directive definitions for SPQR directives in our code) , i think this will unblock us. |
@ankit-joinwal Good to hear that the code works with gateway and that you're unblocked, thanks for explaining the problem in detail! |
This is an extension for #53
Use Case:
There are some server side directives(_mappedType, _mappedInputField and _mappedOperation) added to original schema by graphql-spqr library which do not have directive definitions exposed in the schema.
grapqhl-spqr is correct in not exposing the server side directive definitions as per Graph Spec.
These directives break the Apollo Gateway while discovering the schema of the service.
As part of this fix, i have added support for excluding such directives.
Related leangen/graphql-spqr#290