Closed khteh closed 5 years ago
Sure. From https://github.com/graphql-java-kickstart/graphql-java-tools#why-graphql-java-tools:
GraphQL Java Tools allows you to register "Resolvers" for any type that can bring state along and use that to resolve fields.
Hi; To clarify what I asked, is it possible to have multiple concrete implementation classes of the GraphQLQueryResolver interface in a single .jar / .war file? Is it possible to have multiple GraphQLQueryReosolver types in the same schema?
For example, in one book.graphqls, I define type BookQuery
and in author.graphqls, I define another type AuthorQuery
instead of extend type Query
. Thanks!
I tried and received a runtime exception indicating missing root Query and Mutation types. So I added these empty "default" "root" resolver classes, added the miscellaneous
Hi @khteh, when I was learning GraphQL I was having the same sort of doubt. when I got my answer, that time, it wasn't possible (I'm not sure about current trends).
GraphQL is specification given by Facebook, where as, GraphQL Java is the implementation of that specification on Java Platform. So, by specification, it compels to follow the extend type ....
for more than one graphql schema definitions. And, in the same way we have our SchemaPraser
in Java implementation.
I had tried the same thing in apollo-graphql
(JavaScript/nodeJs based implementation). There to, the schema files had to be written in exact same way. I mean, you can actually use the same graphql schema file for both apollo-graphql
and for graphql-java
. So it is not an issue/bug with graphql-java
. It is just the implementation of specification how it should be done.
By the way, In java implementation, we can have single abstract class for Query Resolver
and each of our Schema based resolvers can extend them with their own functional logic.
But, for graphql schema definition file
should be written in the way it is suggested. I hope this was helpful.
root.graphqls:
type Query {
}
type Mutation {
}
book.graphqls:
type Book {
id: ID!
title: String!
isbn: String!
pageCount: Int
author: Author
}
type BookQuery {
findAllBooks: [Book]!
countBooks: Long!
}
type BookMutation {
newBook(title: String!, isbn: String!, pageCount: Int, author: ID!): Book!
deleteBook(id: ID!): Boolean
updateBookPageCount(id: ID!, pageCount: Int!): Book!
}
Query.java (To avoid runtime exception indicating missing root Query and Mutation types):
public class Query implements GraphQLQueryResolver { /* Empty */ }
Mutation.java (runtime exception indicating missing root Query and Mutation types):
public class Mutation implements GraphQLMutationResolver { /* Empty */ }
BookQuery.java:
public class BookQuery implements GraphQLQueryResolver { /* Implementations of the book.graphqls */ }
BookMutationJava:
public class BookMutation implements GraphQLMutationResolver { /* Implementations of the book.graphqls */ }
Is this valid according to the GraphQL specification?
Hi @khteh,
Sorry, I overlooked this issue :disappointed:
All types within a GraphQL schema must have unique names, so you can only have one Query type (and it's mandatory, that's why you got an exception about missing root Query). If you want to have multiple Query types defined in the schema, the only thing you can do is extend the type as @themanojshukla mentions (thanks!).
About the schema implementation, that's another thing. You can spread the Query definition between multiple GraphQLQueryResolver
classes (the same apply to GraphQLMutationResolver
).
For example, for this application, instead of one com.example.DemoGraphQL.resolver.Query
class, we can have two classes:
public class BookQuery implements GraphQLQueryResolver {
// ...
public Iterable<Book> findAllBooks() {
return bookRepository.findAll();
}
public long countBooks() {
return bookRepository.count();
}
}
And:
public class AuthorQuery implements GraphQLQueryResolver {
// ...
public Iterable<Author> findAllAuthors() {
return authorRepository.findAll();
}
public long countAuthors() {
return authorRepository.count();
}
}
Or as @themanojshukla also mentions, have a single abstract class and multiple concrete classes.
Hope this answer your question.
How does the extension hierarchy look like? I tried to use
type AuthorQuery extends Query { ...}
type BookQuery extends Query { ... }
which is a flat 2-level extension but it throws exception:
2019-03-18 09:29:27.680 ERROR 14366 --- [ main] o.s.b.web.embedded.tomcat.TomcatStarter : Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. Message: Error creating bean with name 'graphQLServletRegistrationBean' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLWebAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQLServletRegistrationBean' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQLHttpServlet' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLWebAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQLHttpServlet' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'invocationInputFactory' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLWebAutoConfiguration.class]: Unsatisfied dependency expressed through method 'invocationInputFactory' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQLSchemaProvider' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLWebAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQLSchemaProvider' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQLSchema' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLJavaToolsAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQLSchema' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schemaParser' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLJavaToolsAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.coxautodev.graphql.tools.SchemaParser]: Factory method 'schemaParser' threw exception; nested exception is org.antlr.v4.runtime.misc.ParseCancellationException: There are more tokens in the query that have not been consumed
Actually, I use type extension in this project, in book.graphqls
to extend the Query
type defined in author.graphqls
:
extend type Query {
findAllBooks: [Book]!
countBooks: Long!
}
Basically, extend
adds fields to an already-defined type.
Just tested both methods work. No build error and object instantiation of the query and mutation types work. There is no good reason to subclass an empty abstract class.
how to implement hierarchical mutations or nested mutations, can you guide me or help me on this with code
Hi @pramod-madha. Probably this is not the best place to get an answer for your question, personally, I haven't used GraphQL for a long time. However, this article and its associated repo may help you: https://fedidat.com/280-graphql-java-nesting/. Good luck!
Thanks eh3rrera for the reply. thanks for sharing the article, but I am using com.graphql-java-kickstart, but on an high level article it doesn't use com.graphql-java-kickstart library. can you please share or guide any other useful link or resource for the same. As I have an requirement to implement this functionality
Hi;
Is it possible to have multiple implementaions of GraphQLResolver classes? It would be very messy to put everything into a single ROOT implementation classes when the project grows bigger. Thanks.