Execution

To execute a Query/Mutation against a Schema build a new GraphQL Object with the appropriate arguments and then call execute().

The result of a Query is a ExecutionResult Object with the result and/or a list of Errors.

Example: [GraphQL Test](src/test/groovy/graphql/GraphQLTest.groovy)

More complex examples: [StarWars query tests](src/test/groovy/graphql/StarWarsQueryTest.groovy)

Mutations

A good starting point to learn more about mutating data in graphql is http://graphql.org/learn/queries/#mutations.

In essence you need to define a GraphQLObjectType that takes arguments as input. Those arguments are what you can use to mutate your data store via the data fetcher invoked.

The mutation is invoked via a query like :

mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
  createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}

You need to send in arguments during that mutation operation, in this case for the variables for $ep and $review

You would create types like this to handle this mutation :

Notice that the input arguments are of type GraphQLInputObjectType. This is important. Input arguments can ONLY be of that type and you cannot use output types such as GraphQLObjectType. Scalars types are consider both input and output types.

The data fetcher here is responsible for executing the mutation and returning some sensible output values.

private DataFetcher mutationDataFetcher() {
    return new DataFetcher() {
        @Override
        public Review get(DataFetchingEnvironment environment) {
            Episode episode = environment.getArgument("episode");
            ReviewInput review = environment.getArgument("review");

            // make a call to your store to mutate your database
            Review updatedReview = reviewStore().update(episode, review);

            // this returns a new view of the data
            return updatedReview;
        }
    };
}

Notice how it calls a data store to mutate the backing database and then returns a Review object that can be used as the output values to the caller.

Execution strategies

All fields in a SelectionSet are executed serially per default.

You can however provide your own execution strategies, one to use while querying data and one to use when mutating data.

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        2, /* core pool size 2 thread */
        2, /* max pool size 2 thread */
        30, TimeUnit.SECONDS,
        new LinkedBlockingQueue<Runnable>(),
        new ThreadPoolExecutor.CallerRunsPolicy());

GraphQL graphQL = GraphQL.newObject(StarWarsSchema.starWarsSchema)
        .queryExecutionStrategy(new ExecutorServiceExecutionStrategy(threadPoolExecutor))
        .mutationExecutionStrategy(new SimpleExecutionStrategy())
        .build();

When provided fields will be executed parallel, except the first level of a mutation operation.

See specification for details.

Alternatively, schemas with nested lists may benefit from using a BatchedExecutionStrategy and creating batched DataFetchers with get() methods annotated @Batched.