Repository navigation
Description
I want to suggest an idea and checked that ...
- ... to my best knowledge, my idea wouldn't break something for other users
- ... the documentation does not mention anything about my idea
- ... there are no open or closed issues that are related to my idea
Description
Expose what each field data fetcher is bound to through a public, read-only interface.
When the schema is built, MethodFieldResolver, PropertyFieldResolver and MapFieldResolver pick the Java member for each field and wrap it in MethodFieldResolverDataFetcher, LightMethodFieldResolverDataFetcher, PropertyFieldResolverDataFetcher or MapFieldResolverDataFetcher. These classes are internal, and the member, the resolver instance and the argument to parameter mapping are private. The only public hook, getWrappedFetchingObject(environment), needs an environment and cannot tell a GraphQLResolver<T> instance from a source object.
Something like this, implemented by all four fetchers:
interface FieldResolverDataFetcher : DataFetcher<Any?> {
// the Java member backing the field: a Method, a Field, or null for map entries
val member: Member?
// the GraphQLResolver instance the member is invoked on, or null when it is invoked on the source object
val resolver: Any?
// the Java parameter index a schema argument is bound to, accounting for the source parameter and trailing context
fun parameterIndexOf(argumentName: String): Int?
}All of this is already known in MethodFieldResolver.createDataFetcher() (method, search.source, getJavaMethodParameterIndex), so it would mostly mean keeping it on the fetcher and exposing it. Adding a public interface to the internal classes should not break existing users.
Use Cases
Checking the schema against the Java code that resolves it, from a test or at startup. Ours is deprecation: every @deprecated field and argument must be resolved by a method or parameter annotated with @Deprecated, so an AOP aspect can log usage and tell us when a field is safe to remove. Doing that correctly requires the member tools actually bound. Matching by name gets overrides, inherited methods, data class getters and renamed parameters wrong.
Today this needs:
- reflection on the private
methodandsourceResolverfields of the internal fetcher classes, which can break on any upgrade; - calling
sourceResolver.resolve(null, null)and treating an exception as "bound to the source object"; - re-implementing
getIndexOffset()to find the parameter behind an argument.
With the interface, all three become codeRegistry.getDataFetcher(coordinates, field) as? FieldResolverDataFetcher. The same information would help other tooling too: authorization or validation checks on resolver methods, documentation generators, and tracing instrumentation that names the Java method.
A smaller, related addition: a read-only lookup from GraphQL type name to the Java class tools mapped it to. This would let the same kind of check find the Java class behind an input type.
Activity