Starter for building GraphQL applications with Spring GraphQL
—
The Spring Boot GraphQL Starter provides fundamental GraphQL infrastructure through auto-configured Spring beans. These components form the foundation for GraphQL schema loading, execution, and request processing.
The central component that holds the GraphQL schema and execution configuration.
@Bean
@ConditionalOnMissingBean
public GraphQlSource graphQlSource(
ResourcePatternResolver resourcePatternResolver,
GraphQlProperties properties,
ObjectProvider<DataFetcherExceptionResolver> exceptionResolvers,
ObjectProvider<SubscriptionExceptionResolver> subscriptionExceptionResolvers,
ObjectProvider<Instrumentation> instrumentations,
ObjectProvider<RuntimeWiringConfigurer> wiringConfigurers,
ObjectProvider<GraphQlSourceBuilderCustomizer> sourceCustomizers
) {
// Auto-configured with schema loading and customization
}Service responsible for executing GraphQL requests against the schema.
@Bean
@ConditionalOnMissingBean
public ExecutionGraphQlService executionGraphQlService(
GraphQlSource graphQlSource,
BatchLoaderRegistry batchLoaderRegistry
) {
DefaultExecutionGraphQlService service = new DefaultExecutionGraphQlService(graphQlSource);
service.addDataLoaderRegistrar(batchLoaderRegistry);
return service;
}Registry for DataLoader instances to solve the N+1 query problem.
@Bean
@ConditionalOnMissingBean
public BatchLoaderRegistry batchLoaderRegistry() {
return new DefaultBatchLoaderRegistry();
}Configures support for @Controller classes with GraphQL mapping annotations.
@Bean
@ConditionalOnMissingBean
public AnnotatedControllerConfigurer annotatedControllerConfigurer(
@Qualifier(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME) ObjectProvider<Executor> executorProvider,
ObjectProvider<HandlerMethodArgumentResolver> argumentResolvers
) {
AnnotatedControllerConfigurer configurer = new AnnotatedControllerConfigurer();
// Configured with executors and custom argument resolvers
return configurer;
}The starter automatically discovers GraphQL schema files from default locations:
// Default schema configuration
public class Schema {
private String[] locations = {"classpath:graphql/**/"};
private String[] fileExtensions = {".graphqls", ".gqls"};
private Resource[] additionalFiles = {};
}Schema files are loaded recursively from:
src/main/resources/graphql/ (all subdirectories).graphqls, .gqlsBuilt-in schema validation and inspection capabilities:
public class Inspection {
private boolean enabled = true; // Schema-to-application mapping validation
}
public class Introspection {
private boolean enabled = true; // Runtime schema introspection
}Usage example:
// Enable detailed schema inspection logging
spring.graphql.schema.inspection.enabled=true
// Disable introspection in production
spring.graphql.schema.introspection.enabled=falseHandle exceptions during GraphQL field resolution:
public interface DataFetcherExceptionResolver {
Mono<List<GraphQLError>> resolveException(DataFetcherExceptionResolverEnvironment environment);
}Implementation example:
@Component
public class CustomExceptionResolver implements DataFetcherExceptionResolver {
@Override
public Mono<List<GraphQLError>> resolveException(DataFetcherExceptionResolverEnvironment env) {
Throwable exception = env.getException();
if (exception instanceof ValidationException) {
GraphQLError error = GraphqlErrorBuilder.newError()
.message("Validation failed: " + exception.getMessage())
.location(env.getField().getSourceLocation())
.errorType(ErrorType.ValidationError)
.build();
return Mono.just(List.of(error));
}
return Mono.empty(); // Let other resolvers handle
}
}Handle exceptions during GraphQL subscription streams:
public interface SubscriptionExceptionResolver {
Mono<List<GraphQLError>> resolveException(SubscriptionExceptionResolverEnvironment environment);
}Add cross-cutting concerns to GraphQL execution:
public interface Instrumentation {
InstrumentationState createState(InstrumentationCreateStateParameters parameters);
InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters);
// Additional instrumentation hooks...
}Usage example:
@Component
public class TimingInstrumentation implements Instrumentation {
@Override
public InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters) {
long startTime = System.currentTimeMillis();
return new SimpleInstrumentationContext<ExecutionResult>() {
@Override
public void onCompleted(ExecutionResult result, Throwable t) {
long duration = System.currentTimeMillis() - startTime;
log.info("GraphQL execution took {}ms", duration);
}
};
}
}Customize the GraphQL runtime wiring to add custom DataFetchers, type resolvers, and scalar types:
public interface RuntimeWiringConfigurer {
void configure(RuntimeWiring.Builder builder);
}Usage example:
@Component
public class CustomWiringConfigurer implements RuntimeWiringConfigurer {
@Override
public void configure(RuntimeWiring.Builder builder) {
builder
.scalar(ExtendedScalars.DateTime)
.type("Query", typeWiring -> typeWiring
.dataFetcher("customField", customDataFetcher))
.type("Book", typeWiring -> typeWiring
.dataFetcher("author", authorDataFetcher));
}
}Customize the GraphQL source building process:
public interface GraphQlSourceBuilderCustomizer {
void customize(GraphQlSource.SchemaResourceBuilder builder);
}Usage example:
@Component
public class SchemaCustomizer implements GraphQlSourceBuilderCustomizer {
@Override
public void customize(GraphQlSource.SchemaResourceBuilder builder) {
builder
.configureTypeDefinitions(registry -> {
// Modify type definitions
})
.configureRuntimeWiring(wiringBuilder -> {
// Configure runtime wiring
});
}
}The core infrastructure is conditionally configured based on:
@ConditionalOnClass({GraphQL.class, GraphQlSource.class})
@ConditionalOnGraphQlSchema // Custom condition checking for schema filesThe @ConditionalOnGraphQlSchema annotation ensures GraphQL infrastructure is only configured when:
GraphQlSource bean is providedAutomatic cursor strategy configuration for pagination:
@ConditionalOnClass(ScrollPosition.class)
@Configuration(proxyBeanMethods = false)
static class GraphQlDataAutoConfiguration {
@Bean
@ConditionalOnMissingBean
EncodingCursorStrategy<ScrollPosition> cursorStrategy() {
return CursorStrategy.withEncoder(
new ScrollPositionCursorStrategy(),
CursorEncoder.base64()
);
}
}Native compilation support through runtime hints:
static class GraphQlResourcesRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
hints.resources()
.registerPattern("graphql/*.graphqls")
.registerPattern("graphql/*.gqls");
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-graphql