-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Adding GraphQlContext in preference to the legacy context #2368
Conversation
cc @bclozel @rstoyanchev @rwinch |
Related to #2357 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM overall. A few comments below.
@@ -187,6 +206,7 @@ public static Builder newExecutionInput(String query) { | |||
private String query; | |||
private String operationName; | |||
private Object context = GraphQLContext.newContext().build(); | |||
private GraphQLContext graphQLContext = GraphQLContext.newContext().build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that context
is also an instance of GraphQLContext
by default, perhaps the new graphQLContext
can be initialized to the same instance, so that the new getGraphQLContext
simply exposes the existing default context
instance but for its actual type.
This can also be helpful for migration in cases where the existing context
is not replaced since code can be switched to simply access it through the new graphQLContext
methods. And it shouldn't change anything for cases where the existing context
is replaced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea - thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
public Builder graphQLContext(GraphQLContext.Builder contextBuilder) { | ||
return graphQLContext(contextBuilder.build()); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if there is even a need to replace the GraphQLContext
instance? A single instance that's not exposed for replacement seems fine for a shared context, or at least it could start out that way until there is evidence to allow it. I cannot think of reasons to replace it but if such reasons do surface, it could also lead to enhancingGraphQLContext
itself rather than allowing the instance to be replaced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is about trying to seed it up with information from outside the graphql query run
Eg imagine some how you now the principal of the user making the request at the time - you can set this in via this.
Of course you could do
ExecutionInput ei - ExecutionInput.newExecutionInput().query(s).variables(..).build()
ei.getGraphqlContext().put(Principal.class, requestPrincipal)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do see how key-value pairs can be inserted into the context through an:
ExecutionInput
instance viagetGraphQLContext
ExecutionInput.Builder
instance viagraphQLContext(UnaryOperator<GraphQLContext.Builder>)
although this one currently replaces the underlying context instance rather than transforming it (as per my next comment) so doesn't quite work for just seeding (without replacing) the context.
What I don't see is why even allow replacing the GraphQLContext
instance? If all you want to seed it, that should be possible with a single, shared instance only that isn't exposed for replacing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gerat idea - done - goes into the one and only context
GraphQLContext.Builder builder = GraphQLContext.newContext(); | ||
builder = contextBuilderFunction.apply(builder); | ||
return graphQLContext(builder.build()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Irrespective of my previous comment about whether graphQLContext
is a fixed instance that can or cannot be replaced, I think this method should operate on the default instance. I can imagine cases where some code only has access to GraphQLContext.Builder
and needs to update the context without actually replacing the instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment does not match any more
} | ||
|
||
/** | ||
* This will put all the valuyes from the map into the underlying {@link GraphQLContext} of this execution input |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* This will put all the valuyes from the map into the underlying {@link GraphQLContext} of this execution input | |
* This will put all the values from the map into the underlying {@link GraphQLContext} of this execution input |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I think this is doing what you want - its a new context here but that is "copied / putAll" into the one context object
* @return this builder | ||
*/ | ||
public Builder graphQLContext(Consumer<GraphQLContext.Builder> builderFunction) { | ||
GraphQLContext.Builder builder = GraphQLContext.newContext(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should operate on the underlying GraphQLContext
instance rather than creating a new one, right? It would be consistent with the changes we've been discussing and I think it's meant to be that way judging from the Javadoc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here - this is putAll into the one context object
Would it be possible to make this class extendable? In the DGS framework we have a DgsContext, which is very similar in concept to the If |
Yeah this makes sense to me - GraphQLContext probably should have been an interface in retrospect (said everyone in Java) but allowing it to extended is the next best thing. you won't get the fancy builders however because UNLESS you know of a tricky way there is no Java way to inherit static builder methods which is a PITA |
@paulbakker I have made it protected extendable |
I think it's important to emphasize the changes in this PR provide a migration path for existing APIs that currently rely on a custom object. Existing usage of the The idea is the new If this is all used in this way, I imagine there shouldn't be a need to extend |
@rstoyanchev - you right - there is no need for extension because long term we dont allow you to actually set a GraphqlContext in. @paulbakker - today there is two context objects (transitonary) - one is the old The second is the new Since longer term you don't SET the context object but rather set values into a fixed context value (we create a graphql context per Executionnput) then there is no need for extension I have reverted that change back - it is still fixed. |
Closes vert-x3#2023 With GraphQL-Java 17, te GraphQLContext object becomes the standard to share contextual data between components of a GraphQL Java application (see https://github.com/graphql-java/graphql-java/releases/tag/v17.0 and graphql-java/graphql-java#2368). This commit: - deprecates the current context hooks in Vert.x Web GraphQL handlers - adds a new hook that allows to manipulate the ExecutionInputBuilder - updates the docs Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
Closes #2023 With GraphQL-Java 17, te GraphQLContext object becomes the standard to share contextual data between components of a GraphQL Java application (see https://github.com/graphql-java/graphql-java/releases/tag/v17.0 and graphql-java/graphql-java#2368). This commit: - deprecates the current context hooks in Vert.x Web GraphQL handlers - adds a new hook that allows to manipulate the ExecutionInputBuilder - updates the docs Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
…ts` utility (#4201) Motivation: The context field of ExecutionInput/DataFetchingEnvironment is a deprecated method. This should be replaced. - See https://github.com/graphql-java/graphql-java/releases/tag/v17.0 - See graphql-java/graphql-java#2368 Modifications: - Added `ServiceRequestContex`t to `GraphQLContext` - Added `GraphqlServiceContexts` utility class for retrieving `ServiceRequestContext` from a `GraphQLContext`. Result: - `armeria-graphql` doesn't use deprecated API anymore. - A user can retrieve the current `ServiceRequestContext` using `GraphServiceContexts`. Co-authored-by: Trustin Lee <t@motd.kr> Co-authored-by: Ikhun Um <ih.pert@gmail.com>
The original graphql-java code copied the graphql-js pattern of having a opaque context object
Since everything in JS is untyped and mutable this works because one can just "wack" another property into the context
However we have learnt over time that since the context is sa shared place (for both frameworks and user code to use) we need to have a more formal mechanism that just a
Object getContext()
pattern.So we have made the
GraphqlContext getGraphqlContext()
the preferred context mechanism and deprecated the olderObject getContext
methods.At some point the legacy
getContext
will disappear but since this is a WIDELY used mechanism that will not be any time soon.