Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GraphQL with Java - How to seperate resolvers into multiple classes

Tags:

java

api

graphql

first of all i have to apologize. Probably this is a stupid beginner question, but slowly i get frustrated after paging thorugh dozens of tutorials and issues...

Whats the Problem? I have a simple schema, looking like the following:

schema {
    query: Query
}

type Query {
    allVehicles: [Vehicle]!
    allPersons: [Person]!
}

type Vehicle{
    name: String!
}

Person{
    name: String!
}

Now im trying to let different classes resolve the queries for person and vehicle. So i build a query class for person and one for vehicle, both implement the GraphQLQueryResolver interface.

Than i have a class, which builds the schema, and it looks like the following:

@WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends SimpleGraphQLServlet {

public GraphQLEndpoint() {

    super(buildSchema());
}

private static GraphQLSchema buildSchema() {

    final VehicleRepository vehicleRepository = new VehicleRepository();
    final PersonRepository personRepository = new PersonRepository();

    return SchemaParser.newParser()
        .file("schema.graphqls")
        .resolvers(new VehicleQuery(vehicleRepository), 
                   new PersonQuery(personRepository)), 
        .build()
        .makeExecutableSchema();

    }
}

I can start the webapplication on my jetty server, but since i visit it from the browser, i get errors, which tell me, that the functions allVehicles and allPersons cannot be found.

(In other tutorials and issues, everybody has .js files beside their schema.graphqls but i neither don't understand, how they work nor why they are necessary. What's the point of the schema.graphqls, if it's not able to let me delegate which class has to deal the respective queries.)

So please, could anyone tell me, what i am doing wrong?

Edit: Maybe i should show you one of the query classes:

public class PersonQuery implements GraphQLRootResolver {

private final PersonRepository _personRepository;

public PersonQuery(
    final PersonRepository pPersonRepository) {

    this._personRepository = pPersonRepository;
}

public List<Person> allPersons() {

    return _personRepository.getAllPersons();
}

}
like image 664
NightroadSora Avatar asked Dec 19 '18 13:12

NightroadSora


1 Answers

I use the Spring Boot Graphql server and I split the GraphQLResolver into multiple classes as follows:

1) Create an abstract Query class which implements GraphQLQueryResolver

 import com.coxautodev.graphql.tools.GraphQLQueryResolver;
   public abstract class Query implements GraphQLQueryResolver {
   }

2) Create individual query resolver classes by extending Query. In my case I have two classes AuthorQuery and BookQuery:

The BookQuery class

import com.swissre.graphql.model.Book;
import com.swissre.graphql.repository.BookRepository;

public class BookQuery extends Query {
   // private BookRepository bookRepository;
    private BookRepository bookRepository;

    public BookQuery(BookRepository bookRepository) {
         super();
        this.bookRepository = bookRepository;
    }

    public Iterable<Book> findAllBooks() {
        return bookRepository.findAll();
    }

The AuthorQuery Class

import com.swissre.graphql.model.Author;
import com.swissre.graphql.repository.AuthorRepository;

public class AuthorQuery extends Query {

    private AuthorRepository authorRepository;

    public AuthorQuery(AuthorRepository authorRepository) {
         super();
        this.authorRepository = authorRepository;

    }

    public Iterable<Author> findAllAuthors() {
        return authorRepository.findAll();
    }

And you need to provide those resolver classes as a part of Graphql build schema. In my case, I use Spring Boot Graphql server and if you don't change the Graphql endpoint, then it doesn't need any extra configurations. All I do is to provide these Beans in the main Spring config file like below:

@SpringBootApplication
public class DemoGraphQLApplication  {




    public static void main(String[] args) {
        SpringApplication.run(DemoGraphQLApplication.class, args);
    }


     @Bean
        public BookResolver bookResolver(AuthorRepository authorRepository) {
            return new BookResolver(authorRepository);
        }

     @Bean
        public AuthorResolver authorResolver(BookRepository bookRepository) {
            return new AuthorResolver(bookRepository);
        }

With this set up, I am able to run the Graphql server with multiple resolver classes successfully. Hope this helps!

like image 77
Raghav Avatar answered Oct 23 '22 16:10

Raghav