Skip to content

Remove missingResolverDataFetcher and the legacy context fallbacks - #915

Merged
oryan-block merged 5 commits into
masterfrom
feature/846-remove-missing-resolver-data-fetcher
Oct 24, 2026
Merged

oryan-block merged 5 commits into
masterfrom
feature/846-remove-missing-resolver-data-fetcher

Conversation

@oryan-block

@oryan-block oryan-block commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #846

Checklist

  • Pull requests follows the contribution guide
  • New or modified functionality is covered by tests

Description

The three breaking cleanups the issue lists for 15.0.0, one commit each, plus a fix commit for the context class.

missingResolverDataFetcher is gone from SchemaParserOptions and its builder, with the fallback to it in MissingFieldResolver, the null check in FieldResolverScanner.missingFieldResolver and the test for it. An app that calls it stops compiling, so nothing changes quietly. missingResolverDataFetcherProvider stays.

A custom context class (contextClass) is only read from the GraphQLContext now. #566 made it look there first and fall back to environment.getContext() (what ExecutionInput.context(...) was given), with a warning that said "This warning will become an error in the future". Without the fallback the parameter would have gotten null for a Java method or a nullable Kotlin parameter, which hides the mistake. So the field fails instead, with an error that names the resolver method and the context class and says to put it in the GraphQLContext under its class when building the ExecutionInput. On master the same mistake already failed with argument type mismatch, unless the app also passed the class as the context object. contextClass(GraphQLContext::class) keeps working: that parameter gets the GraphQLContext, as it did on master through the fallback.

A CoroutineScope is only read from the GraphQLContext under the CoroutineScope class key now. #350 added the context object route (the app's context implements CoroutineScope, so each request gets its own scope) and 14.2.0 deprecated it with a warning. Without it, suspend resolvers run in CoroutineScope(Dispatchers.Default) and nothing is logged or fails. That's the one that can go unnoticed: cancelling the app's scope no longer cancels its running resolvers, and the scope's job and context elements aren't there. I didn't add anything to catch it, so the release note has to.

Tests: data fetcher fails if custom context is missing from GraphQLContext, data fetcher fails if custom context is only passed as the legacy context object and data fetcher passes GraphQLContext if it is the custom context class are new, and the legacy CoroutineScope test now asserts the scope isn't used. The fallback tests fail on the unchanged code.

mvn clean verify passes on graphql-java 26.1 and 25.1 (412 tests each).

Also checked through the installed jar in a separate consumer project, with a context that is both the contextClass and a CoroutineScope, passed as the context object. On master nullableContext and strictContext both give context user: oryan, scopeJob gives ran in the request scope, and the log has the two context warnings and the scope one. On this branch (graphql-java 26.1 and 25.1) nullableContext and strictContext fail with the new error, scopeJob gives ran in the default scope, and the log is empty. The context-and-environment scenario, which passes the class through the GraphQLContext, still runs without errors.

Release note: three removals for 15.0.0.

  • SchemaParserOptions.Builder.missingResolverDataFetcher(...) is removed. Replace .missingResolverDataFetcher(fetcher) with .missingResolverDataFetcherProvider { _, _ -> fetcher }.
  • A custom context class that is only passed as the context object (ExecutionInput.context(...)) is no longer given to resolvers. A resolver with a parameter of that class fails the field with an error saying so. Put it in the GraphQLContext under its class instead, e.g. ExecutionInput.newExecutionInput().graphQLContext(mapOf(MyContext::class.java to myContext)).
  • A CoroutineScope that is only passed as the context object is no longer used by suspend resolvers, and nothing is logged or fails. They run in CoroutineScope(Dispatchers.Default), so cancelling your scope no longer cancels them. Put it in the GraphQLContext under the CoroutineScope class key instead, e.g. graphQLContext(mapOf(CoroutineScope::class.java to scope)).

@oryan-block oryan-block reopened this Oct 23, 2026
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
B Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@oryan-block
oryan-block merged commit 17c10c5 into master Oct 24, 2026
5 of 6 checks passed
@oryan-block
oryan-block deleted the feature/846-remove-missing-resolver-data-fetcher branch October 24, 2026 00:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove deprecated missingResolverDataFetcher option in 15.0.0

1 participant