Skip to content

Cannot inject DataLoader<> directly from auto configured @BatchMapping #1023

Closed as not planned
@xcq1

Description

@xcq1

I'm in the process of porting an existing project to spring-graphql 1.3.1 and want to use all of its convenience features for more readable code. From the docs about annotated controllers I gathered that defining and reusing DataLoaders should be quite easy. I have a setup similar to this:

@Controller
class EntityConnectionsBatchController {

    @BatchMapping
    fun entityConnections(keys: Set<EntityFilter>): Mono<Map<EntityBatchFilter, EntityConnectionGraphQL>> {
        return Mono.just(
            // complex filtering logic...
            .toMap()
        )
    }
}

@Controller
class EntityQueryController {

    @QueryMapping
    fun entities(
        @Argument first: Int,
        @Argument after: CursorGraphQL?,
        @Argument offset: Int?,
        @Argument filter: EntityFilterInputGraphQL?,
        dataLoader: DataLoader<EntityBatchFilter, EntityConnectionGraphQL>
    ): CompletableFuture<EntityConnectionGraphQL> =
        dataLoader.load(
            EntityFilter(
                // add all the arguments into the filter
            )
        )
}

But when I try to query this, I run into an exception:

Cannot resolve DataLoader for parameter 'dataLoader' in method public java.util.concurrent.CompletableFuture<org.example.controller.graphql.model.EntityConnectionGraphQL> org.example.controller.graphql.resolvers.queries.EntityQueryController.entities(int,java.lang.String,java.lang.Integer,org.example.controller.graphql.model.EntityFilterInputGraphQL,org.dataloader.DataLoader<org.example.controller.graphql.resolvers.queries.EntityBatchFilter, org.example.controller.graphql.model.EntityConnectionGraphQL>). Neither the name of the declared value type 'class org.example.controller.graphql.model.EntityConnectionGraphQL' nor the method parameter name 'dataLoader' match to any DataLoader. The DataLoaderRegistry contains: [EntityGroupBatchFilter.entityGroupConnections, EntityBatchFilter.entityConnections, /* ... */]

I was trying to change some internal names to get it to work out of the box, but upon debugging a bit I am confused how this is supposed to work:

Not only will the class names never match by default, because one is simpleName and one is package-qualified, but it is impossible to select an existing data loader since a.) I cannot configure the @BatchMapping annotation to not include a dot and b.) I cannot request injection of a data loader with dot in the name since dots are (thankfully) illegal in parameter names.

Am I missing something and there is a reason for this? To me it sounds as if the DataLoaderMethodArgumentResolver should actually request the same kind of pattern of <simpleClassName>.<parameterName> by default.

So to get this to work currently I have to inject the environment and find it by knowing the naming convention of AnnotatedControllerConfigurer:

 fun entities(
        // ...
        env: DataFetchingEnvironment
    ): CompletableFuture<EntityConnectionGraphQL> {
        val dataLoader = env.getDataLoader<EntityBatchFilter, EntityConnectionGraphQL>("${EntityBatchFilter::class.simpleName}.entityConnections")
        return dataLoader.load(/* ... */)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions