private CompletableFuture<ExecutionResult> completeValueForNull(ExecutionStrategyParameters parameters) { return Async.tryCatch(() -> { Object nullValue = parameters.getNonNullFieldValidator().validate(parameters.getPath(), null); return completedFuture(new ExecutionResultImpl(nullValue, null)); }); }
@SuppressWarnings("SameReturnValue") private Object handleCoercionProblem(ExecutionContext context, ExecutionStrategyParameters parameters, CoercingSerializeException e) { SerializationError error = new SerializationError(parameters.getPath(), e); log.warn(error.getMessage(), e); context.addError(error); parameters.deferredErrorSupport().onError(error); return null; }
private BiFunction<List<Object>, Throwable, FetchedValues> handleResult(ExecutionContext executionContext, ExecutionStrategyParameters parameters, List<MapOrList> parentResults, DataFetchingEnvironment environment) { return (result, exception) -> { if (exception != null) { if (exception instanceof CompletionException) { exception = exception.getCause(); } DataFetcherExceptionHandlerParameters handlerParameters = DataFetcherExceptionHandlerParameters.newExceptionParameters() .dataFetchingEnvironment(environment) .exception(exception) .build(); DataFetcherExceptionHandlerResult handlerResult = dataFetcherExceptionHandler.onException(handlerParameters); handlerResult.getErrors().forEach(executionContext::addError); result = Collections.nCopies(parentResults.size(), null); } List<Object> values = result; List<FetchedValue> retVal = new ArrayList<>(); for (int i = 0; i < parentResults.size(); i++) { Object value = unboxPossibleOptional(values.get(i)); retVal.add(new FetchedValue(parentResults.get(i), value)); } return new FetchedValues(retVal, parameters.getExecutionStepInfo(), parameters.getPath()); }; }
private void handleTypeMismatchProblem(ExecutionContext context, ExecutionStrategyParameters parameters, Object result) { TypeMismatchError error = new TypeMismatchError(parameters.getPath(), parameters.getExecutionStepInfo().getUnwrappedNonNullType()); log.warn("{} got {}", error.getMessage(), result.getClass()); context.addError(error); parameters.deferredErrorSupport().onError(error); }
private void handleUnresolvedTypeProblem(ExecutionContext context, ExecutionStrategyParameters parameters, UnresolvedTypeException e) { UnresolvedTypeError error = new UnresolvedTypeError(parameters.getPath(), parameters.getExecutionStepInfo(), e); log.warn(error.getMessage(), e); context.addError(error); parameters.deferredErrorSupport().onError(error); }
public AbsoluteGraphQLError(ExecutionStrategyParameters executionStrategyParameters, GraphQLError relativeError) { assertNotNull(executionStrategyParameters); assertNotNull(relativeError); this.absolutePath = createAbsolutePath(executionStrategyParameters.getPath(), relativeError); this.locations = createAbsoluteLocations(relativeError, executionStrategyParameters.getField()); this.message = relativeError.getMessage(); this.errorType = relativeError.getErrorType(); if (relativeError.getExtensions() != null) { this.extensions = new LinkedHashMap<>(); this.extensions.putAll(relativeError.getExtensions()); } else { this.extensions = null; } }
MergedField currentField = fields.getSubField(fieldName); ExecutionPath fieldPath = parameters.getPath().segment(mkNameForPath(currentField)); ExecutionStrategyParameters newParameters = parameters .transform(builder -> builder.field(currentField).path(fieldPath).parent(parameters));
public void onFetchingException(ExecutionStrategyParameters parameters, Throwable e) { ExceptionWhileDataFetching error = new ExceptionWhileDataFetching(parameters.getPath(), e, parameters.getField().getSingleField().getSourceLocation()); onError(error); }
DeferredFieldInstrumentationContext beginDeferredField(InstrumentationDeferredFieldParameters parameters) { CallStack callStack = parameters.getInstrumentationState(); int level = parameters.getExecutionStrategyParameters().getPath().getLevel(); synchronized (callStack) { callStack.clearAndMarkCurrentLevelAsReady(level); } return new DeferredFieldInstrumentationContext() { @Override public void onDispatched(CompletableFuture<ExecutionResult> result) { } @Override public void onCompleted(ExecutionResult result, Throwable t) { } @Override public void onFieldValueInfo(FieldValueInfo fieldValueInfo) { boolean dispatchNeeded; synchronized (callStack) { dispatchNeeded = handleOnFieldValuesInfo(Collections.singletonList(fieldValueInfo), callStack, level); } if (dispatchNeeded) { dispatch(); } } }; }
/** * Called to turn an object into a scalar value according to the {@link GraphQLScalarType} by asking that scalar type to coerce the object * into a valid value * * @param executionContext contains the top level execution parameters * @param parameters contains the parameters holding the fields to be executed and source object * @param scalarType the type of the scalar * @param result the result to be coerced * * @return a promise to an {@link ExecutionResult} */ protected CompletableFuture<ExecutionResult> completeValueForScalar(ExecutionContext executionContext, ExecutionStrategyParameters parameters, GraphQLScalarType scalarType, Object result) { Object serialized; try { serialized = scalarType.getCoercing().serialize(result); } catch (CoercingSerializeException e) { serialized = handleCoercionProblem(executionContext, parameters, e); } // TODO: fix that: this should not be handled here //6.6.1 http://facebook.github.io/graphql/#sec-Field-entries if (serialized instanceof Double && ((Double) serialized).isNaN()) { serialized = null; } try { serialized = parameters.getNonNullFieldValidator().validate(parameters.getPath(), serialized); } catch (NonNullableFieldWasNullException e) { return exceptionallyCompletedFuture(e); } return completedFuture(new ExecutionResultImpl(serialized, null)); }
private ExecutionStrategyParameters firstFieldOfSubscriptionSelection(ExecutionStrategyParameters parameters) { MergedSelectionSet fields = parameters.getFields(); MergedField firstField = fields.getSubField(fields.getKeys().get(0)); ExecutionPath fieldPath = parameters.getPath().segment(mkNameForPath(firstField.getSingleField())); return parameters.transform(builder -> builder.field(firstField).path(fieldPath)); }
/** * Called to turn an object into a enum value according to the {@link GraphQLEnumType} by asking that enum type to coerce the object into a valid value * * @param executionContext contains the top level execution parameters * @param parameters contains the parameters holding the fields to be executed and source object * @param enumType the type of the enum * @param result the result to be coerced * * @return a promise to an {@link ExecutionResult} */ protected CompletableFuture<ExecutionResult> completeValueForEnum(ExecutionContext executionContext, ExecutionStrategyParameters parameters, GraphQLEnumType enumType, Object result) { Object serialized; try { serialized = enumType.getCoercing().serialize(result); } catch (CoercingSerializeException e) { serialized = handleCoercionProblem(executionContext, parameters, e); } try { serialized = parameters.getNonNullFieldValidator().validate(parameters.getPath(), serialized); } catch (NonNullableFieldWasNullException e) { return exceptionallyCompletedFuture(e); } return completedFuture(new ExecutionResultImpl(serialized, null)); }
final MergedField currentField = fields.getSubField(fieldName); ExecutionPath fieldPath = parameters.getPath().segment(mkNameForPath(currentField)); ExecutionStrategyParameters newParameters = parameters .transform(builder -> builder.field(currentField).path(fieldPath));
@Override @SuppressWarnings({"TypeParameterUnusedInFormals","FutureReturnValueIgnored"}) public CompletableFuture<ExecutionResult> execute(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException { Instrumentation instrumentation = executionContext.getInstrumentation(); InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext, parameters); InstrumentationContext<ExecutionResult> executionStrategyCtx = instrumentation.beginExecutionStrategy(instrumentationParameters); MergedSelectionSet fields = parameters.getFields(); List<String> fieldNames = new ArrayList<>(fields.keySet()); CompletableFuture<List<ExecutionResult>> resultsFuture = Async.eachSequentially(fieldNames, (fieldName, index, prevResults) -> { MergedField currentField = fields.getSubField(fieldName); ExecutionPath fieldPath = parameters.getPath().segment(mkNameForPath(currentField)); ExecutionStrategyParameters newParameters = parameters .transform(builder -> builder.field(currentField).path(fieldPath)); return resolveField(executionContext, newParameters); }); CompletableFuture<ExecutionResult> overallResult = new CompletableFuture<>(); executionStrategyCtx.onDispatched(overallResult); resultsFuture.whenComplete(handleResults(executionContext, fieldNames, overallResult)); overallResult.whenComplete(executionStrategyCtx::onCompleted); return overallResult; }
private FetchedValue fetchField(ExecutionContext executionContext, ExecutionStrategyParameters parameters, MergedSelectionSet fields, String fieldName) { MergedField currentField = fields.getSubField(fieldName); ExecutionPath fieldPath = parameters.getPath().segment(fieldName); ExecutionStrategyParameters newParameters = parameters .transform(builder -> builder.field(currentField).path(fieldPath)); return fetchField(executionContext, newParameters).join(); }
private ExecutionStrategyParameters newParameters(ExecutionStrategyParameters parameters, MergedSelectionSet fields, String fieldName) { MergedField currentField = fields.getSubField(fieldName); ExecutionPath fieldPath = parameters.getPath().segment(fieldName); return parameters .transform(builder -> builder.field(currentField).path(fieldPath)); }
@Override public CompletableFuture<ExecutionResult> execute(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException { MergedSelectionSet fields = parameters.getFields(); Map<String, FetchedValue> fetchedValues = new LinkedHashMap<>(); // first fetch every value for (String fieldName : fields.keySet()) { FetchedValue fetchedValue = fetchField(executionContext, parameters, fields, fieldName); fetchedValues.put(fieldName, fetchedValue); } // then for every fetched value, complete it Map<String, Object> results = new LinkedHashMap<>(); for (String fieldName : fetchedValues.keySet()) { MergedField currentField = fields.getSubField(fieldName); FetchedValue fetchedValue = fetchedValues.get(fieldName); ExecutionPath fieldPath = parameters.getPath().segment(fieldName); ExecutionStrategyParameters newParameters = parameters .transform(builder -> builder.field(currentField).path(fieldPath)); try { completeValue(executionContext, results, fieldName, fetchedValue, newParameters); } catch (NonNullableFieldWasNullException e) { assertNonNullFieldPrecondition(e); results = null; break; } } return CompletableFuture.completedFuture(new ExecutionResultImpl(results, executionContext.getErrors())); }
/** * Called to complete a list of value for a field based on a list type. This iterates the values and calls * {@link #completeValue(ExecutionContext, ExecutionStrategyParameters)} for each value. * * @param executionContext contains the top level execution parameters * @param parameters contains the parameters holding the fields to be executed and source object * @param result the result to complete, raw result * * @return a {@link FieldValueInfo} */ protected FieldValueInfo completeValueForList(ExecutionContext executionContext, ExecutionStrategyParameters parameters, Object result) { Iterable<Object> resultIterable = toIterable(executionContext, parameters, result); try { resultIterable = parameters.getNonNullFieldValidator().validate(parameters.getPath(), resultIterable); } catch (NonNullableFieldWasNullException e) { return FieldValueInfo.newFieldValueInfo(LIST).fieldValue(exceptionallyCompletedFuture(e)).build(); } if (resultIterable == null) { return FieldValueInfo.newFieldValueInfo(LIST).fieldValue(completedFuture(new ExecutionResultImpl(null, null))).build(); } return completeValueForList(executionContext, parameters, resultIterable); }
ExecutionStrategyInstrumentationContext beginExecutionStrategy(InstrumentationExecutionStrategyParameters parameters) { CallStack callStack = parameters.getInstrumentationState(); ExecutionPath path = parameters.getExecutionStrategyParameters().getPath(); int parentLevel = path.getLevel(); int curLevel = parentLevel + 1;
/** * Builds the type info hierarchy for the current field * * @param executionContext the execution context in play * @param parameters contains the parameters holding the fields to be executed and source object * @param fieldDefinition the field definition to build type info for * * @return a new type info */ protected ExecutionStepInfo createExecutionStepInfo(ExecutionContext executionContext, ExecutionStrategyParameters parameters, GraphQLFieldDefinition fieldDefinition, GraphQLObjectType fieldContainer) { GraphQLOutputType fieldType = fieldDefinition.getType(); List<Argument> fieldArgs = parameters.getField().getArguments(); GraphQLCodeRegistry codeRegistry = executionContext.getGraphQLSchema().getCodeRegistry(); Map<String, Object> argumentValues = valuesResolver.getArgumentValues(codeRegistry, fieldDefinition.getArguments(), fieldArgs, executionContext.getVariables()); return newExecutionStepInfo() .type(fieldType) .fieldDefinition(fieldDefinition) .fieldContainer(fieldContainer) .field(parameters.getField()) .path(parameters.getPath()) .parentInfo(parameters.getExecutionStepInfo()) .arguments(argumentValues) .build(); }