Skip to content

Unable to mix custom resolvers with pure data types with arguments #101

@nicholashagen

Description

@nicholashagen

Resolvers can either be automatic by binding to the data type's getter methods or they can be bound by looking for a class with Resolver appended such as HumanResolver handling Human data types. These types can also be mixed so that resolver classes resolve first and then the data type methods get bound together second. However, if those data type methods contain parameters/arguments, then it throws an NPE in Kotlin. This is due to the fact that the schema parser assigns each schema type as either a DataTypeResolver or a NormalResolver. When a Resolver class is used it gets bound to NormalResolver. When this occurs the parser attempts to associate the method signature and assumes that any field that takes arguments as part of its definition will always be at index + 1 since the first argument on a Resolver is the type itself. However, since the arguments are on the data type it fails to find said argument since only 1 arg exists.

The following update to the example shows this error on startup (mvn spring-boot:run)

https://github.com/graphql-java/graphql-java-tools/compare/master...nicholashagen:mixed-resolver-datatype-args?expand=1

Essentially, I added two new fields for testing to the schema. The first field is bestFriends and was added to the new HumanResolver (which triggers the schema type now as a NormalResolver). The second field is allFriends which takes a limit argument. This is handled by the Human class directly since it would know how to sublist the list and not need the resolver.

This is a contrived example. My particular use case is that I use a mixed state of resolver methods and data types. The data type knows how to handle the core data (user.id, user.name, user.type, etc). The resolver methods know how to handle relationships via stateful Spring IoC (data repository/dao, etc) such as user.shows, user.friends, user.settings. However, I also want to be able to add arguments to the general fields. For example, user.dateOfBirth should take a format or locale argument and return the data appropriately. In those cases, I keep the dateOfBirth on the User taking the arguments and it applies the formatting, rather than having to add all of these simple cases to UserResolver. With that example it fails because of the mixed state. If I add to the UserResolver it works or if I have the User class handle everything including relationships and have no UserResolver then it works as well.

Here is the particular code in error:

https://github.com/graphql-java/graphql-java-tools/blob/master/src/main/kotlin/com/coxautodev/graphql/tools/MethodFieldResolver.kt#L102

which calls getJavaMethodParameterType which calls getJavaMethodParameterIndex which calls getIndexOffset : https://github.com/graphql-java/graphql-java-tools/blob/master/src/main/kotlin/com/coxautodev/graphql/tools/MethodFieldResolver.kt#L106

which adds 1 if a NormalResolverInfo

I made an ugly hack here : https://github.com/graphql-java/graphql-java-tools/compare/master...nicholashagen:mixed-resolver-datatype-args?expand=1#diff-d5ee916ae35272fb34ccb0ee9360f8ddR106 that attempts to resolve by checking if the method is on the resolver or the data type, but I'm sure there are more appropriate fixes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions