Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

Hi! We recently introduced dataloaders into our GraphQL API and they worked great for several days before they started throwing this exception:

Exception while fetching data (/getRecords/nestedRecords) : Cannot invoke "java.util.Map.get(Object)" because "map" is null:
java.lang.NullPointerException: Cannot invoke "java.util.Map.get(Object)" because "map" is null
    at org.dataloader.DataLoaderHelper.lambda$invokeMapBatchLoader$11(DataLoaderHelper.java:429)
    at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:642)
    at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
    at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1769)
    at org.springframework.cloud.sleuth.instrument.async.TraceRunnable.run(TraceRunnable.java:63)
    at org.springframework.security.concurrent.DelegatingSecurityContextRunnable.run(DelegatingSecurityContextRunnable.java:82)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at com.blah.graphql.async.DecoratedThread.run(DecoratedThread.java:51)

I see there's a nonNull assertion on the line directly above the call that throws that exception in DataLoaderHelper.java. Could it somehow be passing that assertion even though it shouldn't?

Here's the rough structure of one of the dataloader definitions:

private DataLoader<UUID, List<NestedRecord>> createNestedRecordDataLoader() {
    MappedBatchLoader<UUID, List<NestedRecord>> nestedRecordBatchLoader =
        (Set<UUID> parentIds) -> CompletableFuture.supplyAsync(
                () -> nestedRecordService.getNestedRecordsByParentIds(
                    parentIds), graphqlAsyncTaskExecutor)
            .orTimeout(threadTimeoutSeconds, TimeUnit.SECONDS)
            .exceptionally(e -> {
              log.error("Exception while fetching NestedRecords: {}", e);
              return null;
            });

    return DataLoaderFactory.newMappedDataLoader(
        nestedRecordBatchLoader );
  }

Any initial thoughts? We haven't been able to reproduce the issue locally to get a debugger on it yet, but will update if we do. Thanks in advance!

You must be logged in to vote

Great - I was just about to reply back that you MUST a non null map

I have this check in the code

        CompletableFuture<Map<K, V>> mapBatchLoad = nonNull(loadResult, () -> "Your batch loader function MUST return a non null CompletionStage").toCompletableFuture();

perhaps we could change the code to either require a non null map OR handle null as if its an empty map. I think reuiring a non null map is better - it would tell you straight away via an assert that your exceptionally -> return null was the problem

Replies: 1 comment · 1 reply

Comment options

This turned out to be an issue with code further down the chain in our service definition. It boiled down to us throwing an exception in the service code which eventually resulted in returning null from the batch loader function (as defined above). That null value then caused the exception to be thrown in DataLoaderHelper.java.

The solution we went with was returning a default non-null value in the exceptionally call of the batch loader function definition and then handling that unexpected default output in the resolvers themselves.

You must be logged in to vote
1 reply
@bbakerman
Comment options

Great - I was just about to reply back that you MUST a non null map

I have this check in the code

        CompletableFuture<Map<K, V>> mapBatchLoad = nonNull(loadResult, () -> "Your batch loader function MUST return a non null CompletionStage").toCompletableFuture();

perhaps we could change the code to either require a non null map OR handle null as if its an empty map. I think reuiring a non null map is better - it would tell you straight away via an assert that your exceptionally -> return null was the problem

Answer selected by bbakerman
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
🙏
Q&A
Labels
None yet
2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.