-
Notifications
You must be signed in to change notification settings - Fork 314
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 inspection of schema mappings on startup #386
Comments
I would expect this to be uncovered by tests, but I see your point, there is an opportunity to validate data fetcher registrations against schema fields. As far as I can see currently GraphQL Java iterates fields and looks up We could use a |
I agree that this is an important feature that is currently lacking the in the Spring for GraphQL implementation. We are looking at switching to using Spring for GraphQL from the GraphQL Kickstart project. We rely heavily on the startup introspection to catch any failures to implement or map resolvers correctly. Additionally, we use the com.kobylynskyi.graphql plugin to generate the API interfaces for our schema. This allows us to perform some amount of compile time checking of types against our implementation before we even get to the final startup introspection. It is very important that our implementation 100% matches the GraphQL schema so that we don't respond to clients with GraphQL specific errors that they cannot do anything about (or are unlikely to understand). |
Is there any update on this? I also agree that this is an important feature, especially during initial development it is very easy to miss a resolver and not notice it. |
This is now scheduled for 1.2 M1. We'll see if there is a way to backport it to 1.1.x in the mean time such that it can be enabled if desired. |
I confirm this is a major issue for me. I tried plain Java kickstart and it beautifully shows missing resolvers on startup, e.g.:
I'd assume Spring could inherit this feature. I don't want to write tests for things that can be detected on startup automatically. |
We should make this arrangement flexible enough to support sliced tests in Spring Boot. Right now |
Slice tests should be okay. My understanding of this issue is that GraphQL Java iterates over schema types/fields and then crosschecks against |
It appears my understanding is incorrect. @nort3x, or anyone else here, could you comment on your expectations for this. Do you expect us to very that: A) Every controller method is mapped to a valid schema field I think B) could be a challenge to do in some cases. For example:
|
@rstoyanchev despite the serious facts about the need comes from the idea "i have a schema which I'm implementing based on it, let's have some sanity checks at the startup" |
I agree B is what would be needed. I ended up using graphql-java-codegen (https://github.com/kobylynskyi/graphql-java-codegen) to solve this. I generate an interface for each query file and then wrote a unit test to make sure every interface was implemented. And then you get compile time checks on any missing queries from each interface. So I'm basically requiring a QueryMapping/MutationMapping for every query/mutation |
Yes, I'm also referring to option That being said, at least in these situations it makes sense to disable such validation:
|
Thanks for the feedback. Verifying root fields, i.e. those under Query, Mutation, Subscription, is straight. Verifying fields on all other GraphQL types is not as straight forward since looking at controller methods and their return types may not provide enough information. @JamesPeters98 I don't fully understand the approach you took, but are you only verifying Query and Mutation mappings, or are you also checking all other fields? Does anyone have union / interface types and are you able to validate those too, and if so how since a verification tool can't statically determine what types would be returned at runtime in order to match those to the schema types? |
@rstoyanchev Sorry yes I missed that bit out. It also generates TypeResolver interfaces with I don't use any union/interface types though |
I have a draft implementation for this and it covers quite a few cases already. I'm also documenting known limitations, like Unions. For a start, we'd like to introduce this feature with very little public API as we'd like to get feedback on the feature itself before possibly opening it up in the future. Initially, this feature would be included in the From a developer experience point of view, the important part is the information you get in the logs. I'm asking for opinions here about the logging level and the actual messages. Here's an example of what we could get:
We could add more information there, telling developers what could be missing. |
I've just pushed a first version for this feature. This will be available in 1.2.0-SNAPSHOT in a few minutes and in the upcoming 1.2.0-M1 release. I've mostly kept the logging information described in the previous commit. Because the information is minimal, the entire report is printed at the INFO level. The schema inspection visits the schema operations and types discovered along the way when those are exposed by a As a first step, we would like the community (including @nurkiewicz, @danielshiplett, @JamesPeters98 ) to give it a try and send us feedback about things we possibly missed. Once we've gathered enough feedback on it, we might open this up a bit more: configuring the behavior (just logging, failing the app), exposing the inspection report for consumption by user code, etc. |
After discussing with @rstoyanchev, it seems that performing the schema mapping inspection on the The I've also slightly changed the report format to remain on a single line:
|
So far, I think this looks promising. Here's some log output from my sample application that reports the missing schema resolvers:
Also, until there is another option for failure in case of missing schema, could I request that the logging of the report be done at the WARN level if there is anything missing? This might make it more visible. I do like the idea of being able to access the report via code. Doing this in an ApplicationReadyEvent listener would allow me to choose the behavior in case of missing schema resolvers. This could be a good extension if people want more than just an optional failure. |
My 2c here: With this new feature, Spring knows exactly how the schema should look and log mismatches on startup. A great feature and a perfect fit for an integration test. Since this schema is known, it is not such a far stretch to expand this feature to make Spring GrapQL code-first and have it generate the schema completely. This would put Spring GrapQL in the unique and powerful position of having the user choose between schema-first or code-first. Many users would prefer code-first as it is a lot less "duplicate" code and faster to get going. Other users would prefer the explicit schema in schema-first. Having the choice would be awesome! Any opinions @bclozel or @rstoyanchev ? |
This feature is not about integration tests, but more about development time. We don't expect those checks to be even complete and accurate as there are many cases we can't cover. Here it's the opposite: the schema is defined by the developer and we inspect the data fetchers available (controllers, "manually" registered ones, data repositories and more) and check whether we think something is missing.
I don't follow this line of reasoning - we have been able to implement this only because we assume the schema is mostly complete. We're adding new features to take the boilerplate out of the schema, like in #619. |
I understand it better now. I thought that for this introspection to work, the expected schema would be generated from the code and compared to the provided schema by the developer. As you explained, this searches for data fetchers matching the schema and thus my reasoning was wrong. I was just being optimistic and hoping this would enable a code-first option for Spring GraphQL, which would be a nice feature to have. |
@eduanb I understand better now - indeed, if we had taken that approach for inspection the code generation approach would have been very close. We're not investing in this space right now and it's not clear whether our current annotation model would allow to deterministically generate a full, compliant schema. |
Support not only GraphQLObjectType, but any GraphQLFieldsContainer, effectively also inspecting fields declared on an interface. Add skipped types to report that includes any non-simple types that have been skipped. Any type that is not a GraphQLFieldsContainer is skipped, including unions. Types may also be skipped because of insufficient Java object type information, e.g. controller method declared to return Object or Mono<?>. Do not report issues related to scalar and enum type fields, which don't have any structure and don't need further checks. See gh-386
Quick note to add a link to the reference documentation for those looking to understand and experiment with the feature. There have also been a few improvements. Most notably, basic support for schema |
Thanks for the update on the progress on this @rstoyanchev. Do you know, are there plans to add a hook into this inspection? Ideally, I'd like some way to listen for the inspection report event so that I can decide if I want to take further action based on the report result. Like an application failure. |
@danielshiplett, I've created #672 for this. |
@danielshiplett we didn't get much feedback so far on the actual feature: is it applicable to existing schemas, is the provided information actionable, are there false positives/negatives... we will probably refine that in the 1.2.x generation. We could expose a contract to help with custom behavior (such as failing at startup), but I guess we should consider this for 1.3.0. |
Hey, I just got around to testing this when upgrading to Spring Boot 3.1. I seem to be getting false positives for unmapped fields that have a java field. I think it happens when the controller method is a CompletableFuture of a List of the object:
GraphQL schema:
Object class:
|
@JamesPeters98 thanks for trying the RC version. Can you raise a new issue for this problem? |
i just started exploring this project, i read the documents and couldn't figure this out (so in that case i'm emphasizing on importance of configuration being much more straight forward and possibly default enabled )
for schema files we are supposed to write valid mappings by signature and return type
but if i make any mistake (not annotating Arguments, or methods) it remains silent until a request hit it
i was lucky i had defined not-null return type in schem otherwise i suppose it would remain completely silent
my point is this is not an issue at all!
but when i'm writing schema file i'm going with schema-first approach and it would be much more better experience if these mistakes would bubble up at startup rather than request resolving
The text was updated successfully, but these errors were encountered: