
org.springframework.graphql.execution.AbstractGraphQlSourceBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spring-graphql Show documentation
Show all versions of spring-graphql Show documentation
GraphQL Support for Spring Applications
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.graphql.execution;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import graphql.GraphQL;
import graphql.execution.instrumentation.ChainedInstrumentation;
import graphql.execution.instrumentation.Instrumentation;
import graphql.schema.GraphQLCodeRegistry;
import graphql.schema.GraphQLSchema;
import graphql.schema.GraphQLTypeVisitor;
import graphql.schema.SchemaTransformer;
import graphql.schema.SchemaTraverser;
import org.springframework.lang.Nullable;
/**
* Implementation of {@link GraphQlSource.Builder} that leaves it to subclasses
* to initialize {@link GraphQLSchema}.
*
* @param the builder type
* @author Rossen Stoyanchev
* @author Brian Clozel
* @since 1.0.0
*/
public abstract class AbstractGraphQlSourceBuilder> implements GraphQlSource.Builder {
private final List exceptionResolvers = new ArrayList<>();
private final List subscriptionExceptionResolvers = new ArrayList<>();
private final List typeVisitors = new ArrayList<>();
private final List typeVisitorsToTransformSchema = new ArrayList<>();
private final List instrumentations = new ArrayList<>();
@Nullable
private Consumer graphQlConfigurer;
@Override
public B exceptionResolvers(List resolvers) {
this.exceptionResolvers.addAll(resolvers);
return self();
}
@Override
public B subscriptionExceptionResolvers(List resolvers) {
this.subscriptionExceptionResolvers.addAll(resolvers);
return self();
}
@Override
public B typeVisitors(List typeVisitors) {
this.typeVisitors.addAll(typeVisitors);
return self();
}
@Override
public B typeVisitorsToTransformSchema(List typeVisitorsToTransformSchema) {
this.typeVisitorsToTransformSchema.addAll(typeVisitorsToTransformSchema);
return self();
}
@Override
public B instrumentation(List instrumentations) {
this.instrumentations.addAll(instrumentations);
return self();
}
@Override
public B configureGraphQl(Consumer configurer) {
this.graphQlConfigurer = (this.graphQlConfigurer != null) ?
this.graphQlConfigurer.andThen(configurer) : configurer;
return self();
}
@SuppressWarnings("unchecked")
private T self() {
return (T) this;
}
@Override
public GraphQlSource build() {
GraphQLSchema schema = initGraphQlSchema();
schema = applyTypeVisitorsToTransformSchema(schema);
schema = applyTypeVisitors(schema);
GraphQL.Builder builder = GraphQL.newGraphQL(schema);
builder.defaultDataFetcherExceptionHandler(
DataFetcherExceptionResolver.createExceptionHandler(this.exceptionResolvers));
if (!this.instrumentations.isEmpty()) {
builder = builder.instrumentation(new ChainedInstrumentation(this.instrumentations));
}
applyGraphQlConfigurers(builder);
return new FixedGraphQlSource(builder.build(), schema);
}
/**
* Subclasses must implement this method to provide the
* {@link GraphQLSchema} instance.
*/
protected abstract GraphQLSchema initGraphQlSchema();
private GraphQLSchema applyTypeVisitorsToTransformSchema(GraphQLSchema schema) {
SchemaTransformer transformer = new SchemaTransformer();
for (GraphQLTypeVisitor visitor : this.typeVisitorsToTransformSchema) {
schema = transformer.transform(schema, visitor);
}
return schema;
}
private GraphQLSchema applyTypeVisitors(GraphQLSchema schema) {
GraphQLCodeRegistry.Builder outputCodeRegistry =
GraphQLCodeRegistry.newCodeRegistry(schema.getCodeRegistry());
Map, Object> vars = new HashMap<>(2);
vars.put(GraphQLCodeRegistry.Builder.class, outputCodeRegistry);
vars.put(TypeVisitorHelper.class, TypeVisitorHelper.create(schema));
List visitorsToUse = new ArrayList<>(this.typeVisitors);
visitorsToUse.add(ContextDataFetcherDecorator.createVisitor(this.subscriptionExceptionResolvers));
new SchemaTraverser().depthFirstFullSchema(visitorsToUse, schema, vars);
return schema.transformWithoutTypes((builder) -> builder.codeRegistry(outputCodeRegistry));
}
/**
* Protected method to apply the
* {@link #configureGraphQl(Consumer) configured graphQlConfigurer}'s.
* Subclasses can use this to customize {@link GraphQL.Builder} further.
* @param builder the builder to be customized
* @since 1.2.5
*/
protected void applyGraphQlConfigurers(GraphQL.Builder builder) {
if (this.graphQlConfigurer != null) {
this.graphQlConfigurer.accept(builder);
}
}
/**
* {@link GraphQlSource} with fixed {@link GraphQL} and {@link GraphQLSchema} instances.
*/
private record FixedGraphQlSource(GraphQL graphQl, GraphQLSchema schema) implements GraphQlSource {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy