Please make sure that a spring GraphQL GraphQlSourceBuilderCustomizer that registers a Resource for the schema doesn't cause an error if the same schema is discovered in scanning
Comment From: sdeleuze
I suspect we miss a if (AotDetector.useGeneratedArtifacts()) check to avoid double processing of GraphQlSourceBuilderCustomizer in AOT mode as done on https://github.com/spring-projects/spring-boot/blob/b78e7b5ac72a2a8351e954f7b07e7ee02d530355/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplateContextCustomizer.java#L56. May impact other customizers too.
Comment From: mhalbritter
This double-executing was the cause of https://github.com/spring-projects/spring-boot/issues/32859, too.
Comment From: philwebb
@joshlong Have you a sample the replicates the problem? Or a stacktrace? Is it AOT specific?
Comment From: sdeleuze
I think the repro is https://github.com/joshlong/spring-boot-3-aot-graphql.
Comment From: mhalbritter
This is not related to AOT.
In the repro project, there's a
@Bean
GraphQlSourceBuilderCustomizer graphQlSourceBuilderCustomizer() {
return builder -> builder.schemaResources(SCHEMA_RESOURCE);
}
which registers /graphql/schema.graphqls. The same schema is picked up by the automatic scanning in GraphQlAutoConfiguration#graphQlSource, essentially registering it twice. The startup then fails with:
Caused by: SchemaProblem{errors=['Customer' type [@1:1] tried to redefine existing 'Customer' type [@1:1], 'Query' type [@6:1] tried to redefine existing 'Query' type [@6:1]]}
at graphql.schema.idl.TypeDefinitionRegistry.merge(TypeDefinitionRegistry.java:106)
at java.base/java.util.stream.ReduceOps$2ReducingSink.accept(ReduceOps.java:123)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:662)
at org.springframework.graphql.execution.DefaultSchemaResourceGraphQlSourceBuilder.initGraphQlSchema(DefaultSchemaResourceGraphQlSourceBuilder.java:98)
at org.springframework.graphql.execution.AbstractGraphQlSourceBuilder.build(AbstractGraphQlSourceBuilder.java:93)
at org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration.graphQlSource(GraphQlAutoConfiguration.java:94)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:139)
... 159 more
The automatic scanning for resources can be disabled by setting spring.graphql.schema.locations=.
We have to decide if we want to deduplicate the resources registered on the SchemaResourceBuilder or if this is considered a user made error.
What's your take on this, @bclozel?
Comment From: mhalbritter
We discussed it today and we don't think we should deduplicate the resource files.