@@ -16,6 +16,7 @@ call ``execute()``.
1616The result of a query is an `` ExecutionResult `` which is the query data and/or a list of errors.
1717
1818{{< highlight java "linenos=table" >}}
19+
1920 GraphQLSchema schema = GraphQLSchema.newSchema()
2021 .query(queryType)
2122 .build();
@@ -53,6 +54,7 @@ opinionated on user authorisation to that data. You should push all that logic
5354A data fetcher might look like this:
5455
5556{{< highlight java "linenos=table" >}}
57+
5658 DataFetcher userDataFetcher = new DataFetcher() {
5759 @Override
5860 public Object get(DataFetchingEnvironment environment) {
@@ -78,6 +80,7 @@ partial results with errors.
7880Here is the code for the standard behaviour.
7981
8082{{< highlight java "linenos=table" >}}
83+
8184 public class SimpleDataFetcherExceptionHandler implements DataFetcherExceptionHandler {
8285 private static final Logger log = LoggerFactory.getLogger(SimpleDataFetcherExceptionHandler.class);
8386
@@ -102,6 +105,7 @@ For example imagine your data fetcher threw this exception. The `foo` and `fizz
102105graphql error.
103106
104107{{< highlight java "linenos=table" >}}
108+
105109 class CustomRuntimeException extends RuntimeException implements GraphQLError {
106110 @Override
107111 public Map<String, Object> getExtensions() {
@@ -133,6 +137,7 @@ may prefer not to see that in the output error list. So you can use this mechan
133137behaviour.
134138
135139{{< highlight java "linenos=table" >}}
140+
136141 DataFetcherExceptionHandler handler = new DataFetcherExceptionHandler() {
137142 @Override
138143 public void accept(DataFetcherExceptionHandlerParameters handlerParameters) {
@@ -155,13 +160,14 @@ GraphQL resource.
155160In this example, the `` DataFetcher `` retrieves a user from another GraphQL resource and returns its data and errors.
156161
157162{{< highlight java "linenos=table" >}}
163+
158164 DataFetcher userDataFetcher = new DataFetcher() {
159165 @Override
160166 public Object get(DataFetchingEnvironment environment) {
161167 Map response = fetchUserFromRemoteGraphQLResource(environment.getArgument("userId"));
162- List<GraphQLError > errors = ((List) response.get("errors")).stream()
168+ List<GraphQLError> errors = response.get("errors")).stream()
163169 .map(MyMapGraphQLError::new)
164- .collect(Collectors.toList()) ;
170+ .collect(Collectors.toList();
165171 return new DataFetcherResult(response.get("data"), errors);
166172 }
167173 };
@@ -206,6 +212,7 @@ via the data fetcher invoked.
206212The mutation is invoked via a query like :
207213
208214{{< highlight graphql "linenos=table" >}}
215+
209216 mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
210217 createReview(episode: $ep, review: $review) {
211218 stars
@@ -221,55 +228,62 @@ You would create types like this to handle this mutation :
221228
222229{{< highlight java "linenos=table" >}}
223230
231+ GraphQLInputObjectType episodeType = newInputObject()
232+ .name("Episode")
233+ .field(newInputObjectField()
234+ .name("episodeNumber")
235+ .type(Scalars.GraphQLInt))
236+ .build();
224237
225- GraphQLInputObjectType episodeType = GraphQLInputObjectType.newInputObject()
226- .name("Episode")
227- .field(newInputObjectField()
228- .name("episodeNumber")
229- .type(Scalars.GraphQLInt))
230- .build();
238+ GraphQLInputObjectType reviewInputType = newInputObject()
239+ .name("ReviewInput")
240+ .field(newInputObjectField()
241+ .name("stars")
242+ .type(Scalars.GraphQLString)
243+ .name("commentary")
244+ .type(Scalars.GraphQLString))
245+ .build();
231246
232- GraphQLInputObjectType reviewInputType = GraphQLInputObjectType.newInputObject ()
233- .name("ReviewInput ")
234- .field(newInputObjectField ()
235- .name("stars")
236- .type(Scalars. GraphQLString))
237- .field(newInputObjectField ()
238- .name("commentary")
239- .type(Scalars. GraphQLString))
240- .build();
247+ GraphQLObjectType reviewType = newObject ()
248+ .name("Review ")
249+ .field(newFieldDefinition ()
250+ .name("stars")
251+ .type(GraphQLString))
252+ .field(newFieldDefinition ()
253+ .name("commentary")
254+ .type(GraphQLString))
255+ .build();
241256
242- GraphQLObjectType reviewType = newObject()
243- .name("Review")
244- .field(newFieldDefinition()
245- .name("stars")
246- .type(GraphQLString))
247- .field(newFieldDefinition()
248- .name("commentary")
249- .type(GraphQLString))
250- .build();
257+ GraphQLObjectType createReviewForEpisodeMutation = newObject()
258+ .name("CreateReviewForEpisodeMutation")
259+ .field(newFieldDefinition()
260+ .name("createReview")
261+ .type(reviewType)
262+ .argument(newArgument()
263+ .name("episode")
264+ .type(episodeType)
265+ )
266+ .argument(newArgument()
267+ .name("review")
268+ .type(reviewInputType)
269+ )
270+ )
271+ .build();
251272
252- GraphQLObjectType createReviewForEpisodeMutation = newObject()
253- .name("CreateReviewForEpisodeMutation")
254- .field(newFieldDefinition()
255- .name("createReview")
256- .type(reviewType)
257- .argument(newArgument()
258- .name("episode")
259- .type(episodeType)
260- )
261- .argument(newArgument()
262- .name("review")
263- .type(reviewInputType)
264- )
265- .dataFetcher(mutationDataFetcher())
266- )
267- .build();
273+ GraphQLCodeRegistry codeRegistry = newCodeRegistry()
274+ .dataFetcher(
275+ coordinates("CreateReviewForEpisodeMutation", "createReview"),
276+ mutationDataFetcher()
277+ )
278+ .build();
279+
280+
281+ GraphQLSchema schema = GraphQLSchema.newSchema()
282+ .query(queryType)
283+ .mutation(createReviewForEpisodeMutation)
284+ .codeRegistry(codeRegistry)
285+ .build();
268286
269- GraphQLSchema schema = GraphQLSchema.newSchema()
270- .query(queryType)
271- .mutation(createReviewForEpisodeMutation)
272- .build();
273287{{< / highlight >}}
274288
275289
@@ -344,6 +358,7 @@ In fact under the covers, the graphql-java engine uses asynchronous execution an
344358calling join for you. So the following code is in fact the same.
345359
346360{{< highlight java "linenos=table" >}}
361+
347362 ExecutionResult executionResult = graphQL.execute(executionInput);
348363
349364 // the above is equivalent to the following code (in long hand)
@@ -363,6 +378,7 @@ The following code uses the standard Java ``java.util.concurrent.ForkJoinPool.co
363378thread.
364379
365380{{< highlight java "linenos=table" >}}
381+
366382 DataFetcher userDataFetcher = new DataFetcher() {
367383 @Override
368384 public Object get(DataFetchingEnvironment environment) {
@@ -379,8 +395,10 @@ thread.
379395The code above is written in long form. With Java 8 lambdas it can be written more succinctly as follows
380396
381397{{< highlight java "linenos=table" >}}
398+
382399 DataFetcher userDataFetcher = environment -> CompletableFuture.supplyAsync(
383400 () -> fetchUserViaHttp(environment.getArgument("userId")));
401+
384402{{< / highlight >}}
385403
386404The graphql-java engine ensures that all the `` CompletableFuture `` objects are composed together to provide an execution result
@@ -391,6 +409,7 @@ Use ``graphql.schema.AsyncDataFetcher.async(DataFetcher<T>)`` to wrap a
391409`` DataFetcher `` . This can be used with static imports to produce more readable code.
392410
393411{{< highlight java "linenos=table" >}}
412+
394413 DataFetcher userDataFetcher = async(environment -> fetchUserViaHttp(environment.getArgument("userId")));
395414
396415{{< / highlight >}}
@@ -404,6 +423,7 @@ You can wire in what execution strategy to use when you create the ``GraphQL`` o
404423
405424
406425{{< highlight java "linenos=table" >}}
426+
407427 GraphQL.newGraphQL(schema)
408428 .queryExecutionStrategy(new AsyncExecutionStrategy())
409429 .mutationExecutionStrategy(new AsyncSerialExecutionStrategy())
@@ -425,6 +445,7 @@ fully asynchronous behaviour.
425445So imagine a query as follows
426446
427447{{< highlight graphql "linenos=table" >}}
448+
428449 query {
429450 hero {
430451 enemies {
@@ -461,30 +482,6 @@ field is completed before it processes the next one and so forth. You can still
461482in the mutation data fetchers, however they will be executed serially and will be completed before the next
462483mutation field data fetcher is dispatched.
463484
464- ## ExecutorServiceExecutionStrategy
465-
466- The `` graphql.execution.ExecutorServiceExecutionStrategy `` execution strategy will always dispatch each field
467- fetch in an asynchronous manner, using the executor you give it. It differs from `` AsyncExecutionStrategy `` in that
468- it does not rely on the data fetchers to be asynchronous but rather makes the field fetch invocation asynchronous by
469- submitting each field to the provided ` java.util.concurrent.ExecutorService ` .
470-
471- This behaviour makes it unsuitable to be used as a mutation execution strategy.
472-
473- {{< highlight java "linenos=table" >}}
474- ExecutorService executorService = new ThreadPoolExecutor(
475- 2, /* core pool size 2 thread * /
476- 2, /* max pool size 2 thread * /
477- 30, TimeUnit.SECONDS,
478- new LinkedBlockingQueue<Runnable >(),
479- new ThreadPoolExecutor.CallerRunsPolicy());
480-
481- GraphQL graphQL = GraphQL.newGraphQL(StarWarsSchema.starWarsSchema)
482- .queryExecutionStrategy(new ExecutorServiceExecutionStrategy(executorService))
483- .mutationExecutionStrategy(new AsyncSerialExecutionStrategy())
484- .build();
485- {{< / highlight >}}
486-
487-
488485## SubscriptionExecutionStrategy
489486
490487Graphql subscriptions allows you to create stateful subscriptions to graphql data. You uses `` SubscriptionExecutionStrategy ``
@@ -505,6 +502,7 @@ You can do this by using a `graphql.schema.visibility.GraphqlFieldVisibility` im
505502A simple ` graphql.schema.visibility.BlockedFields ` implementation based on fully qualified field name is provided.
506503
507504{{< highlight java "linenos=table" >}}
505+
508506 GraphqlFieldVisibility blockedFields = BlockedFields.newBlock()
509507 .addPattern("Character.id")
510508 .addPattern("Droid.appearsIn")
@@ -525,6 +523,7 @@ Note that this puts your server in contravention of the graphql specification an
525523
526524
527525{{< highlight java "linenos=table" >}}
526+
528527 GraphQLSchema schema = GraphQLSchema.newSchema()
529528 .query(StarWarsSchema.queryType)
530529 .fieldVisibility(NoIntrospectionGraphqlFieldVisibility.NO_INTROSPECTION_FIELD_VISIBILITY)
@@ -536,6 +535,7 @@ You can create your own derivation of `GraphqlFieldVisibility` to check what eve
536535should be visible or not.
537536
538537{{< highlight java "linenos=table" >}}
538+
539539 class CustomFieldVisibility implements GraphqlFieldVisibility {
540540
541541 final YourUserAccessService userAccessService;
0 commit comments