{"action":"created","issue":{"url":"https://api.github.com/repos/graphql-java/graphql-java/issues/122","repository_url":"https://api.github.com/repos/graphql-java/graphql-java","labels_url":"https://api.github.com/repos/graphql-java/graphql-java/issues/122/labels{/name}","comments_url":"https://api.github.com/repos/graphql-java/graphql-java/issues/122/comments","events_url":"https://api.github.com/repos/graphql-java/graphql-java/issues/122/events","html_url":"https://github.com/graphql-java/graphql-java/issues/122","id":149431799,"number":122,"title":"TypeResolver often needs more input to resolve (Relay Node) type","user":{"login":"kaqqao","id":831171,"avatar_url":"https://avatars3.githubusercontent.com/u/831171?v=3","gravatar_id":"","url":"https://api.github.com/users/kaqqao","html_url":"https://github.com/kaqqao","followers_url":"https://api.github.com/users/kaqqao/followers","following_url":"https://api.github.com/users/kaqqao/following{/other_user}","gists_url":"https://api.github.com/users/kaqqao/gists{/gist_id}","starred_url":"https://api.github.com/users/kaqqao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaqqao/subscriptions","organizations_url":"https://api.github.com/users/kaqqao/orgs","repos_url":"https://api.github.com/users/kaqqao/repos","events_url":"https://api.github.com/users/kaqqao/events{/privacy}","received_events_url":"https://api.github.com/users/kaqqao/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":8,"created_at":"2016-04-19T11:34:38Z","updated_at":"2017-04-09T19:22:05Z","closed_at":null,"body":"**NOTE:** My original example was tragically bad, so I've completely replaced it. As a result, the comments discussing my original example will not make sense. I apologize for that. The gist of the issue is still the same though.\r\n\r\nAn example of the problem is when resolving a type for a GraphQL interface. The only information available to the `TypeResolver` is the resulting Java object itself, from which the resolver is supposed to deduce the corresponding GraphQL type. This forces the implementor to manually maintain a map of `GraphQLObjectType`s (as the schema object isn't (easily) reachable) and, more importantly, **if the resulting object is an instance of a generic class, this decision is impossible without further information**.\r\n\r\nSuppose the following:\r\n\r\n```\r\ninterface Repository { ... } \r\n \r\nclass InMemoryRepository<T> implements Repository { ... }\r\n```\r\n\r\n`InMemoryRepository<Order>` might map to e.g. `InMemoryRepository_Order` GraphQL type (that has a `containedItem` field of type `Order`), while `InMemoryRepository<Product>` might map to `InMemoryRepository_Product` GraphQL type (that has a `containedItem` field of type `Product`), both implementing `Repository`:\r\n\r\n```\r\ntype InMemoryRepository_Order implements Repository {\r\n  containedItem: Order\r\n}\r\n\r\ntype InMemoryRepository_Product implements Repository {\r\n  containedItem: Product\r\n}\r\n```\r\n\r\nWhen `TypeResolver` receives an instance of `InMemoryRepository`, there's no way to decide the GraphQL type: as it may be `InMemoryRepository_Order` or `InMemoryRepository_Product`.\r\n\r\nIf `TypeResolver` were to receive more information, it may be able to deduce the type. E.g. if it had access to the `Field` object, it could get the Java type of the field e.g. `InMemoryRepository<Order>` and it may deduce the corresponding type should be `InMemoryRepository_Order`. (It's possible to store the mapped Java type into `Field`'s GraphQL type, as demonstrated by _graphql-java-annotations_ [here](https://github.com/graphql-java/graphql-java-annotations/blob/master/src/main/java/graphql/annotations/GraphQLObjectTypeWrapper.java#L31)). With some advanced type analysis, even subtypes can be dealt with, e.g. if the runtime type of the resulting object wasn't `InMemoryRepository` but some subtype of it. I use this type of advanced analysis in my project (link below).\r\n\r\nFor example, in [graphql-java-annotations](https://github.com/graphql-java/graphql-java-annotations/blob/master/src/main/java/graphql/annotations/GraphQLObjectBackedByClass.java#L18) and [schemagen-graphql](https://github.com/bpatters/schemagen-graphql/blob/master/src/main/java/com/bretpatterson/schemagen/graphql/impl/GraphQLObjectMapper.java#L741) this exact strategy could be used for a much richer type resolution logic (a `Type` could be used instead of just a `Class` and combined with the runtime type of the resulting object).\r\nIn general, this change is especially of value to the maintainers of libraries that rely on GraphQL-Java (and we fortunately have a few of those now, [mine](https://github.com/leangen/GraphQL-SPQR) included), because when developing a library as opposed the final project, the Java types can not be known ahead of time, so strategies like inspecting the runtime type of `containedItem` in the example above e.g. `repo.getContainedItem().getClass()` are impossible.\r\n\r\nThe change I propose to allow such advanced type resolution logic is providing `TypeResolver` most of the data available to `DataFetchingEnvironment` (this object is called `TypeResolutionEnvironment` in [my PR](https://github.com/graphql-java/graphql-java/pull/343/files#diff-e23cffe7fe924557fcea3c3e038c2617)) instead of just the resulting object. You can see this in use in my project: https://github.com/leangen/graphql-spqr/blob/master/src/main/java/io/leangen/graphql/generator/HintedTypeResolver.java#L44 \r\n\r\nIt can be argued that this is an edge case, but that would imply usage of generics with this library in general is an edge case. I firmly believe that the fact we're dealing with a _Java_ implementation of the GraphQL spec means it needs to deeply support _Java_ idioms."},"comment":{"url":"https://api.github.com/repos/graphql-java/graphql-java/issues/comments/292806661","html_url":"https://github.com/graphql-java/graphql-java/issues/122#issuecomment-292806661","issue_url":"https://api.github.com/repos/graphql-java/graphql-java/issues/122","id":292806661,"user":{"login":"kaqqao","id":831171,"avatar_url":"https://avatars3.githubusercontent.com/u/831171?v=3","gravatar_id":"","url":"https://api.github.com/users/kaqqao","html_url":"https://github.com/kaqqao","followers_url":"https://api.github.com/users/kaqqao/followers","following_url":"https://api.github.com/users/kaqqao/following{/other_user}","gists_url":"https://api.github.com/users/kaqqao/gists{/gist_id}","starred_url":"https://api.github.com/users/kaqqao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaqqao/subscriptions","organizations_url":"https://api.github.com/users/kaqqao/orgs","repos_url":"https://api.github.com/users/kaqqao/repos","events_url":"https://api.github.com/users/kaqqao/events{/privacy}","received_events_url":"https://api.github.com/users/kaqqao/received_events","type":"User","site_admin":false},"created_at":"2017-04-09T19:22:05Z","updated_at":"2017-04-09T19:22:05Z","body":"I've just tried removing the dependency on our forked version of graphql-java in out project and realized it's more painful than expected as `TypeResolver` doesn't even give access to the schema. And since `TypeResolver`s are instantiated before the schema is even built, it means there's no way to even provide the schema through constructor... which either means mutability/synchronization issues with adding the schema later or manually maintaining a schema-like registry of GraphQL types. And both are rather awful :(\r\nI really hope the next release will bring some resolution."}}
{"actor":{"display_login":"kaqqao"}}