Skip to content
This repository was archived by the owner on Oct 25, 2021. It is now read-only.
This repository was archived by the owner on Oct 25, 2021. It is now read-only.

Request-scoped DataLoaderRegistry blows up #21

Closed
@kijanowski

Description

@kijanowski

I have given a try the code introduced by #12
I used version 1.0 and created a CustomGraphQLInvocation class based on https://github.com/graphql-java/graphql-java-spring/pull/12/files#diff-cb93f026b7b911f1cdfa731e56caa39f

The comment in this PR says:
I think it's overkill to create a ExecutionInputCustomizer for this, simply defining a (request-scoped) @bean should be sufficient.

I've create that bean like this:

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public DataLoaderRegistry dataLoaderRegistry() {...}

And it fails with:

{
  "timestamp": "2019-09-29T11:07:42.456+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "Error creating bean with name 'scopedTarget.dataLoaderRegistry': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.",
  "path": "/graphql"
}

If I change the scope to WebApplicationContext.SCOPE_APPLICATION then it doesn't throw an error. How should this be approached to have a request scoped DataLoaderRegistry?

A working workaround is to change the DefaultGraphQLInvocation and remove:

    @Autowired(required = false)
    DataLoaderRegistry dataLoaderRegistry;

and replace:

        if (dataLoaderRegistry != null) {
            executionInputBuilder.dataLoaderRegistry(dataLoaderRegistry);
        }

with:

        DataLoaderRegistry dataLoaderRegistry = new DataLoaderRegistry();

        // Loader specific configuration
        DataLoader<String, CountryTO> countryLoader = DataLoader.newDataLoader(dataFetchers.countryBatchLoader());
        dataLoaderRegistry.register("countries", countryLoader);
        // Loader specific configuration end
        
        executionInputBuilder.dataLoaderRegistry(dataLoaderRegistry);
        executionInputBuilder.context(dataLoaderRegistry); // add it to the context to use it later in fetchers

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions