Configure additional GraphQL schema files

Prior to this commit, the GraphQL auto-configuration would provide
configuration properties for specifying the locations and file
extensions of schema files to be scanned during startup.

This commit adds a new "spring.graphql.schema.additional-files" that
applications can use to point at particular files, like
"classpath:mylocation/schema.graphqls". These files will be parsed and
considered for the schema in addition to the scanned ones.

Closes gh-42792
This commit is contained in:
Brian Clozel
2025-01-16 18:15:51 +01:00
parent af499705e4
commit 6957557fd7
3 changed files with 39 additions and 8 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
@@ -96,11 +96,15 @@ public class GraphQlAutoConfiguration {
ObjectProvider<SubscriptionExceptionResolver> subscriptionExceptionResolvers,
ObjectProvider<Instrumentation> instrumentations, ObjectProvider<RuntimeWiringConfigurer> wiringConfigurers,
ObjectProvider<GraphQlSourceBuilderCustomizer> sourceCustomizers) {
String[] schemaLocations = properties.getSchema().getLocations();
Resource[] schemaResources = resolveSchemaResources(resourcePatternResolver, schemaLocations,
properties.getSchema().getFileExtensions());
List<Resource> schemaResources = new ArrayList<>();
schemaResources.addAll(resolveSchemaResources(resourcePatternResolver, schemaLocations,
properties.getSchema().getFileExtensions()));
schemaResources.addAll(Arrays.asList(properties.getSchema().getAdditionalFiles()));
GraphQlSource.SchemaResourceBuilder builder = GraphQlSource.schemaResourceBuilder()
.schemaResources(schemaResources)
.schemaResources(schemaResources.toArray(new Resource[0]))
.exceptionResolvers(exceptionResolvers.orderedStream().toList())
.subscriptionExceptionResolvers(subscriptionExceptionResolvers.orderedStream().toList())
.instrumentation(instrumentations.orderedStream().toList());
@@ -116,7 +120,7 @@ public class GraphQlAutoConfiguration {
return builder.build();
}
private Resource[] resolveSchemaResources(ResourcePatternResolver resolver, String[] locations,
private List<Resource> resolveSchemaResources(ResourcePatternResolver resolver, String[] locations,
String[] extensions) {
List<Resource> resources = new ArrayList<>();
for (String location : locations) {
@@ -124,7 +128,7 @@ public class GraphQlAutoConfiguration {
resources.addAll(resolveSchemaResources(resolver, location + "*" + extension));
}
}
return resources.toArray(new Resource[0]);
return resources;
}
private List<Resource> resolveSchemaResources(ResourcePatternResolver resolver, String pattern) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
@@ -20,6 +20,7 @@ import java.time.Duration;
import java.util.Arrays;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.Resource;
/**
* {@link ConfigurationProperties Properties} for Spring GraphQL.
@@ -85,6 +86,11 @@ public class GraphQlProperties {
*/
private String[] fileExtensions = new String[] { ".graphqls", ".gqls" };
/**
* Locations of additional, individual schema files to parse.
*/
private Resource[] additionalFiles = new Resource[0];
private final Inspection inspection = new Inspection();
private final Introspection introspection = new Introspection();
@@ -107,6 +113,14 @@ public class GraphQlProperties {
this.fileExtensions = fileExtensions;
}
public Resource[] getAdditionalFiles() {
return this.additionalFiles;
}
public void setAdditionalFiles(Resource[] additionalFiles) {
this.additionalFiles = additionalFiles;
}
private String[] appendSlashIfNecessary(String[] locations) {
return Arrays.stream(locations)
.map((location) -> location.endsWith("/") ? location : location + "/")

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
@@ -110,6 +110,19 @@ class GraphQlAutoConfigurationTests {
});
}
@Test
void shouldConfigureAdditionalSchemaFiles() {
this.contextRunner
.withPropertyValues("spring.graphql.schema.additional-files=classpath:graphql/types/person.custom")
.run((context) -> {
assertThat(context).hasSingleBean(GraphQlSource.class);
GraphQlSource graphQlSource = context.getBean(GraphQlSource.class);
GraphQLSchema schema = graphQlSource.schema();
assertThat(schema.getObjectType("Book")).isNotNull();
assertThat(schema.getObjectType("Person")).isNotNull();
});
}
@Test
void shouldBackOffWithCustomGraphQlSource() {
this.contextRunner.withUserConfiguration(CustomGraphQlSourceConfiguration.class).run((context) -> {