Provide more information to TypeResolver to allow richer resolution logic#343
Provide more information to TypeResolver to allow richer resolution logic#343kaqqao wants to merge 5 commits into
Conversation
bbakerman
left a comment
There was a problem hiding this comment.
Since this breaks SPI compatibility anyway there is no need to call for Java 1.8 support
In order to unblock this change, decouple it from the 1.8 support. I think the changes are generally good but I would not require 1.8 support to get them in
| public interface TypeResolver { | ||
|
|
||
|
|
||
| default GraphQLObjectType getType(TypeResolutionEnvironment env) { |
There was a problem hiding this comment.
the fact is that because you changed the ExecutionStrategy above and hence this a breaking SPI change for people who extend execution strategy.
Hence the carefully crafted "default" here is backwards compatible but the whole PR is not
So I would remove the 1.8 requirement (which may come but you dont need to be dependent on it)
| return result; | ||
| } | ||
|
|
||
| protected GraphQLObjectType resolveType(GraphQLUnionType graphQLUnionType, Object value) { |
There was a problem hiding this comment.
Again technically a breaking changes for people who extend ExecutionEnvironment
But maybe we need to.
That or we move the "parameter objects" with builders so we can "optional" add new parameters more easily without breaking SPI.
There was a problem hiding this comment.
Not sure I got your 2nd suggestion... But anything that allows easier non-breaking modifications sounds like a good idea.
There was a problem hiding this comment.
The parameters pattern is simply taking N current parameters and moving them into an object with a builder so it takes only 1 parameters
eg:
resolveField(Field field, GraphQLInterfaceType graphQLInterfaceType,
Object value, Map<String, Object> argumentValues, GraphQLSchema schema)
becomes
resolveField(ResolveFieldParameters parameters)
this is useful because you are able to "add" new parameters to the builder while preserving backwards compatibility. This is more useful for "API / SPI" of course
The following is for "constructors" from Effective Java
http://www.informit.com/articles/article.aspx?p=1216151&seqNum=2
But it would be for methods as well
Note this is not really your problem in terms of this PR. But because you needed to add yet more parameters you exasperated the existing problem.
A parameters object would also be a breaking change, although we might be able to do it via overloading and deprecation
There was a problem hiding this comment.
I've reimplemented the changes to the ExecutionStrategy in the way you suggested and made overloads and deprecations for backward-compatibility. Please see when you get a chance what you think of this version.
Notes:
- I've only introduced the
...Parametersclasses where I needed them for this change, not everywhere where they should arguably go. Tell me If you want me refactor more places. - I made the
...Parametersconstructors private to avoid implementors relying on them and ending up in this same situation. I wanted them package private so that they can be used internally, butBatchedExecutionStrategyis in a different package so there wasn't much point. - I added Javadoc to the
@Deprecatedmethods only to link to the new options, but since this is not a full Javadoc, a lot of warnings are generated during the build. Would you rather have the incomplete docs removed or maybe provide the text you'd like in the Javadoc, or would you like me to add my own?
Now, the question comes back to the TypeResolver: do I re-introduce the Java 8 dependent default for backwards compatibility, or do I implement it in a different way?
One idea I have is to introduce a new interface, say TypeDecider, that would provide the new functionality: GraphQLObjectType getType(TypeResolutionEnvironment env), and then change the builders that accept TypeResolvers in a fashion similar to this:
//wrap the given TypeResolver in a simple TypeDecider that just delegates to it
public Builder typeResolver(TypeResolver typeResolver) {
this.typeDecider = new SimpleTypeDecider(typeResolver);
return this;
}
//add new method that accepts TypeDecider directly
public Builder typeDecider(TypeDecider typeDecider) {
this.typeDecider = typeDecider;
return this;
}
With both approaches, backwards-compatibility would be, I think, complete.
UPDATE: I've already implemented the TypeDecider approach, so if you like that option I can push it for review.
|
Yup, I somehow forgot the |
|
Bah, the useful part of the conversation is now getting buried under the hidden "outdated" reviews. But I guess you'll see it anyway. |
Closes #122
Gives
TypeResolveraccess to most of the info available inDataFetchingEnvironment, to allow for complex type resolution logic.I've updated the issue description to explain the rationale behind this PR and the investigation I've so far done on the benefits it would have on the wider ecosystem around this library.
The change is 100% backwards compatible due to the provided
defaultimplementation of the newly introducedGraphQLObjectType getType(TypeResolutionEnvironment env)method inTypeResolver. This obviously requires Java 8, but this should no longer be a problem as it seems the upgrade has been green-lit in #338