Venkatesh Madhipatla
Venkatesh Madhipatla

Reputation: 21

federation-graphql-java-support for spring-graphql SPQR

I have a spring-boot graphQL SPQR service exposing a subgraph. We are using apollo server for federation of all subgraphs into a super graph. To make the subgraph schema federation compatible, apollo has a project called federation-jvm Their SchemaTransformer adds common Federation type definitions (e.g. _Any scalar, _Entity union, Federation directives, etc).

From their examples, I noticed I had to add the below two beans to spring application.

@Bean
public GraphQlSourceBuilderCustomizer customizer(FederationSchemaFactory factory) {
    return builder -> builder.schemaFactory(factory::createGraphQLSchema);
}

@Bean
FederationSchemaFactory federationSchemaFactory() {
    return new FederationSchemaFactory();
}

That fails with error "No GraphQL schema definition was configured" because a schema definition is expected.

Here's the full stack trace. Please give me some pointers how I can integrate their Schema transformer.

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.

I figured out I can do this to transform the schema. But gui still shows without the added directives. But printed schema does show the _service added by federation_jvm. Does this mean this change doesn't have any effect on the final schema exposed in the GUI?

@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;
}

Upvotes: 0

Views: 219

Answers (1)

Venkatesh Madhipatla
Venkatesh Madhipatla

Reputation: 21

Finally this worked. Changed schema shows up in the GUI.

@Bean
public ExecutableSchema graphQLExecutableSchema(GraphQLSchemaGenerator schemaGenerator) {
    ExecutableSchema schema = schemaGenerator.generateExecutable();
    GraphQLSchema fedSchema = Federation.transform(schema.getSchema()).build();
    String printedSchema = new SchemaPrinter(
            // Tweak the options accordingly
            SchemaPrinter.Options.defaultOptions().
                    includeDirectives(true)
    ).print(fedSchema);
    System.out.println(printedSchema);

    return new ExecutableSchema(fedSchema, schema.getTypeRegistry(), schema.getBatchLoaders(), null);
}

Upvotes: 1

Related Questions