Spring GraphQL SPQR集成Apollo Federation-JVM遇问题求助
问题背景
基于Spring Boot的GraphQL SPQR服务作为子图,需通过Apollo Server整合为超图。为让子图Schema兼容联邦规范,使用Apollo的federation-jvm项目,借助其SchemaTransformer添加联邦通用类型(如_Any标量、_Entity联合类型、联邦指令等)。
问题1:添加FederationSchemaFactory Bean后启动报错
按照项目示例添加以下两个Bean后,启动时抛出No GraphQL schema definition was configured错误:
@Bean public GraphQlSourceBuilderCustomizer customizer(FederationSchemaFactory factory) { return builder -> builder.schemaFactory(factory::createGraphQLSchema); } @Bean FederationSchemaFactory federationSchemaFactory() { return new FederationSchemaFactory(); }
完整堆栈追踪:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'routerFunctionMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Error creating bean with name 'graphQlRouterFunction' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQlRouterFunction' parameter 0: Error creating bean with name 'graphQlHttpHandler' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQlHttpHandler' parameter 0: Error creating bean with name 'webGraphQlHandler' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'webGraphQlHandler' parameter 0: Error creating bean with name 'executionGraphQlService' defined in class path resource [org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.class]: Unsatisfied dependency expressed through method 'executionGraphQlService' parameter 0: Error creating bean with name 'graphQlSource' defined in class path resource [org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.class]: Failed to instantiate [org.springframework.graphql.execution.GraphQlSource]: Factory method 'graphQlSource' threw exception with message: No GraphQL schema definition was configured.
问题2:自定义GraphQLSchema Bean后GUI不显示联邦指令
尝试自定义GraphQLSchema Bean,代码如下:
@Bean public GraphQLSchema federatedSchema() { GraphQLSchema schema = new GraphQLSchemaGenerator() .withBasePackages("com.madhi.graphql_demo2.service", "com.madhi.graphql_demo2") .withOperationsFromSingletons(payrollService, employeeService) .generate(); schema = Federation.transform(schema).build(); String printedSchema = new SchemaPrinter( // Tweak the options accordingly SchemaPrinter.Options.defaultOptions(). includeDirectives(true) ).print(schema); System.out.println(printedSchema); return schema; }
打印的Schema显示已添加federation-jvm的_service字段,但GraphQL GUI(如GraphiQL)中未显示新增的联邦指令,怀疑该修改对GUI暴露的最终Schema无效。
解决方案
修复No GraphQL schema definition was configured错误
报错核心原因是FederationSchemaFactory无法自动获取SPQR生成的原始Schema,不能直接替换schemaFactory,需在SPQR生成原始Schema后再执行联邦转换:
@Bean public GraphQlSourceBuilderCustomizer federationCustomizer() { return builder -> builder.configureSchema(schema -> { // 先触发SPQR生成原始Schema,再执行联邦转换 return Federation.transform(schema).build(); }); }
同时确保SPQR的Schema生成逻辑正常:检查项目中@GraphQLApi、@GraphQLQuery等注解类被正确扫描,SPQR依赖配置完整。
让GUI显示联邦指令
GraphQL GUI默认不会展示所有指令,需做以下配置:
- 确认联邦转换后的Schema包含
@key、@extends等指令,可通过打印的SDL验证。 - 配置Spring GraphQL的SchemaPrinter选项,确保暴露的Schema包含指令:
@Bean public GraphQlSource graphQlSource(GraphQlSourceBuilder builder) { return builder.configureSchema(schema -> Federation.transform(schema).build()) .schemaPrinterOptions(options -> options.includeDirectives(true)) .build(); }
- 重启服务或清空GUI工具缓存,部分工具会缓存旧Schema导致不更新。
完整集成步骤
- 确认依赖:引入
com.apollographql.federation:federation-jvm和SPQR的Spring Boot Starter(如io.leangen.graphql:spqr-spring-boot-starter)。 - 配置SPQR:确保
@GraphQLApi标注的服务类被Spring扫描到,能生成原始Schema。 - 添加联邦转换的
GraphQlSourceBuilderCustomizerBean,实现Schema的联邦增强。 - 配置SchemaPrinter选项,确保指令被包含在对外暴露的Schema中。
验证方式
- 启动服务后,访问GraphQL GUI,查看Schema文档是否包含
_Entity、_Any类型及@key等联邦指令。 - 执行查询
{ _service { sdl } },返回的SDL应包含完整的联邦Schema定义。
内容的提问来源于stack exchange,提问作者Venkatesh Madhipatla

