Source:
<code>protected CompletableFuture<?> fetchField(ExecutionContext executionContext, ExecutionStrategyParameters parameters) { Field field = parameters.field().get(0); GraphQLObjectType parentType = parameters.typeInfo().castType(GraphQLObjectType.class); GraphQLFieldDefinition fieldDef = getFieldDef(executionContext.getGraphQLSchema(), parentType, field); Map<String, Object> argumentValues = valuesResolver.getArgumentValues(fieldDef.getArguments(), field.getArguments(), executionContext.getVariables()); GraphQLOutputType fieldType = fieldDef.getType(); DataFetchingFieldSelectionSet fieldCollector = DataFetchingFieldSelectionSetImpl.newCollector(executionContext, fieldType, parameters.field()); ExecutionTypeInfo fieldTypeInfo = fieldTypeInfo(parameters, fieldDef); DataFetchingEnvironment environment = newDataFetchingEnvironment(executionContext) .source(parameters.source()) .arguments(argumentValues) .fieldDefinition(fieldDef) .fields(parameters.field()) .fieldType(fieldType) .fieldTypeInfo(fieldTypeInfo) .parentType(parentType) .selectionSet(fieldCollector) .build(); Instrumentation instrumentation = executionContext.getInstrumentation(); InstrumentationFieldFetchParameters instrumentationFieldFetchParams = new InstrumentationFieldFetchParameters(executionContext, fieldDef, environment); InstrumentationContext<Object> fetchCtx = instrumentation.beginFieldFetch(instrumentationFieldFetchParams); CompletableFuture<?> fetchedValue = null; try { DataFetcher dataFetcher = fieldDef.getDataFetcher(); dataFetcher = instrumentation.instrumentDataFetcher(dataFetcher, instrumentationFieldFetchParams); Object fetchedValueRaw = dataFetcher.get(environment); if (fetchedValueRaw instanceof CompletableFuture) { fetchedValue = (CompletableFuture<?>) fetchedValueRaw; } else { fetchedValue = CompletableFuture.completedFuture(fetchedValueRaw); } fetchedValue.thenAccept(fetchCtx::onEnd); fetchedValue.exceptionally((e) -> { handleFetchingException(executionContext, parameters, field, fieldDef, argumentValues, environment, fetchCtx, e); <START> throw new RuntimeException(e); <END> }); } catch (Exception e) { handleFetchingException(executionContext, parameters, field, fieldDef, argumentValues, environment, fetchCtx, e); } return fetchedValue; }</code><technical_language>graphql.NonNullHandlingTest works well. Currently graphql.execution.NonNullableFieldWasNullException a jump out of a flow adjust behaviour. full async order of field evaluation is changed evaluating A -> B -C in order</technical_language>

Target:
protected CompletableFuture<Object> fetchField(ExecutionContext executionContext, ExecutionStrategyParameters parameters) { Field field = parameters.field().get(0); GraphQLObjectType parentType = parameters.typeInfo().castType(GraphQLObjectType.class); GraphQLFieldDefinition fieldDef = getFieldDef(executionContext.getGraphQLSchema(), parentType, field); Map<String, Object> argumentValues = valuesResolver.getArgumentValues(fieldDef.getArguments(), field.getArguments(), executionContext.getVariables()); GraphQLOutputType fieldType = fieldDef.getType(); DataFetchingFieldSelectionSet fieldCollector = DataFetchingFieldSelectionSetImpl.newCollector(executionContext, fieldType, parameters.field()); ExecutionTypeInfo fieldTypeInfo = fieldTypeInfo(parameters, fieldDef); DataFetchingEnvironment environment = newDataFetchingEnvironment(executionContext) .source(parameters.source()) .arguments(argumentValues) .fieldDefinition(fieldDef) .fields(parameters.field()) .fieldType(fieldType) .fieldTypeInfo(fieldTypeInfo) .parentType(parentType) .selectionSet(fieldCollector) .build(); Instrumentation instrumentation = executionContext.getInstrumentation(); InstrumentationFieldFetchParameters instrumentationFieldFetchParams = new InstrumentationFieldFetchParameters(executionContext, fieldDef, environment); InstrumentationContext<Object> fetchCtx = instrumentation.beginFieldFetch(instrumentationFieldFetchParams); CompletableFuture<?> fetchedValue; DataFetcher dataFetcher = fieldDef.getDataFetcher(); dataFetcher = instrumentation.instrumentDataFetcher(dataFetcher, instrumentationFieldFetchParams); try { Object fetchedValueRaw = dataFetcher.get(environment); if (fetchedValueRaw instanceof CompletionStage) { fetchedValue = ((CompletionStage) fetchedValueRaw).toCompletableFuture(); } else { fetchedValue = CompletableFuture.completedFuture(fetchedValueRaw); } } catch (Exception e) { fetchedValue = new CompletableFuture<>(); fetchedValue.completeExceptionally(e); } fetchedValue.thenAccept(fetchCtx::onEnd); return fetchedValue.handle((result, exception) -> { if (exception != null) { handleFetchingException(executionContext, parameters, field, fieldDef, argumentValues, environment, fetchCtx, exception); return null; } else { return result; } }); }