leangen / graphql-spqr

Build a GraphQL service in seconds
Apache License 2.0
1.09k stars 179 forks source link

Replace batching strategy with DataLoader #432

Closed kaqqao closed 1 year ago

kaqqao commented 1 year ago

graphql-java removed BatchedExecutionStrategy and @Batched annotation. In order to build with newer versions of graphql-java, yet still support batching and preserve backwards-compatibility as much as possible, SPQR must reimplement batching via DataLoader (the only currently supported batching strategy in graphql-java).

To make use of the new implementation:

  1. Replace graphql.execution.batched.Batched with io.leangen.graphql.annotations.Batched (same @Batched, different package)
  2. Configure DataLoaderRegistry either: a. usingGraphQLRuntime.newGraphQL instead of GraphQL.newGraphQL b. manually, using the generated BatchLoaderWithContext instances

Examples:

a)

//No changes in the business logic, apart from the new annotation package
public class UserService {
    @Batched
    @GraphQLQuery
    //Can also return List<Education>, but async fetching is preferred
    public CompletionStage<List<Education>> education(@GraphQLContext List<User> users) {
        ... //Batch-resolve the educations for all users
    }
}

//ExecutableSchema contains the schema and the batch loaders
ExecutableSchema executableSchema = new GraphQLSchemaGenerator()
          .withOperationsFromSingleton(new UserService());
          .generateExecutable();

GraphQL graphQL = GraphQLRuntime.newGraphQL(executableSchema).build();

//Execute queries as normal, no DataLoader setup needed
ExecutionResult result = graphQL.execute("{users {education {startYear}}}");

b)

ExecutableSchema executableSchema = new GraphQLSchemaGenerator()
          .withOperationsFromSingleton(new UserService());
          .generateExecutable();

GraphQL graphQL = GraphQL.newGraphQL(executableSchema.getSchema()).build();

//Get the generated BatchLoaderWithContext instances and setup DataLoader manually
DataLoaderRegistry registry = new DataLoaderRegistry();
executableSchema.getBatchLoaders().forEach((loaderName, batchLoader) -> {
    //Configure DataLoaderOptions etc as needed
    registry.register(loaderName, DataLoader.newDataLoader(batchLoader));
});

ExecutionResult result = graphQL.execute(ExecutionInput.newExecutionInput()
                .query("{users {education {startYear}}}")
                .dataLoaderRegistry(registry) //Make sure to use the registry
                .build());
fedor-bobin-db commented 1 year ago

@kaqqao Hi, could you please build new release version.