Skip to content

feat: Add extension, public method for coercing DataFetchingEnvironment arguments with Kotlin reflection#2169

Closed
JordanJLopez wants to merge 4 commits intomasterfrom
jordlopez-argument-coercing
Closed

feat: Add extension, public method for coercing DataFetchingEnvironment arguments with Kotlin reflection#2169
JordanJLopez wants to merge 4 commits intomasterfrom
jordlopez-argument-coercing

Conversation

@JordanJLopez
Copy link
Copy Markdown
Collaborator

@JordanJLopez JordanJLopez commented Apr 24, 2026

📝 Description

Jackson 3's jackson-module-kotlin fails to construct Kotlin classes that lack proper creator
metadata when using ObjectMapper.convertValue. The failure path is in
ReflectionCache.valueCreatorFromJava:
when Constructor.kotlinFunction returns null for a class (which occurs for classes compiled
with older Kotlin metadata under a newer kotlin-reflect runtime),
valueClassAwareKotlinFunction
propagates null up through valueCreatorFromJava, causing KotlinValueInstantiator to fall
back to a Java creator path that finds nothing — resulting in "no Creators... cannot deserialize
from Object value".

FunctionDataFetcher has never had this problem because it uses KClass.primaryConstructor
(Kotlin-side reflection) directly. This PR exposes that same coercion path as a public API.

Changes:

  • Adds DataFetchingEnvironment.getArgumentsAs<T>() / getArgumentsAs(KClass) extension in
    graphql-kotlin-schema-generator's extensions package — coerces the full arguments map
  • Makes convertInputMap(map, KClass) public — coerces a single extracted argument value,
    for use in instrumentation or library code that inspects fields dynamically
  • Both paths resolve field names via @GraphQLName or Kotlin parameter names and correctly
    pass through values already coerced by graphql-java's scalar pipeline
  • Documents both utilities on the Data Fetching Environment page

Migration:

  • To coerce all arguments on a field: replace objectMapper.convertValue<MyArgs>(environment.arguments)
    with environment.getArgumentsAs<MyArgs>()
  • To coerce a single extracted argument value: replace objectMapper.convertValue<MyInput>(rawMap)
    with convertInputMap(rawMap, MyInput::class)

🔗 Related Issues

…ng arguments into typed objects using Kotlin reflection
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a public DataFetchingEnvironment extension to coerce environment.arguments into typed Kotlin input objects using the same Kotlin-reflection constructor path as FunctionDataFetcher, avoiding Jackson Kotlin metadata/constructor discovery issues (notably with Jackson 3 + older Kotlin metadata).

Changes:

  • Introduces DataFetchingEnvironment.getArgumentsAs(KClass) / getArgumentsAs<T>() extension in the schema generator.
  • Extracts/introduces an internal convertInputMap helper and extends tests around map-to-Kotlin-object coercion, including pre-coerced custom scalar values.
  • Documents the recommended migration away from ObjectMapper.convertValue(environment.arguments).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
website/docs/schema-generator/execution/data-fetching-environment.md Documents the new getArgumentsAs extension and why it’s preferred over ObjectMapper.convertValue.
generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/extensions/DataFetchingEnvironmentExtensions.kt Adds getArgumentsAs extensions that coerce environment.arguments via Kotlin reflection.
generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/execution/convertArgumentValue.kt Adds convertInputMap helper and (currently) changes convertArgumentValue visibility.
generator/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/extensions/DataFetchingEnvironmentExtensionsTest.kt Unit tests for getArgumentsAs behavior (defaults, @GraphQLName, pass-through of pre-coerced values).
generator/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/execution/ConvertArgumentValueTest.kt Adds direct tests for convertInputMap conversion behavior.
generator/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/test/integration/PlainKotlinInputWithCustomScalarTest.kt Integration-style tests validating end-to-end custom scalar coercion and map conversion behavior.
Comments suppressed due to low confidence (1)

generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/execution/convertArgumentValue.kt:56

  • convertArgumentValue was changed from internal to a public top-level function. This unexpectedly expands the library's public API surface (and effectively commits to supporting this signature/behavior). If this wasn't intentional, revert it back to internal; if it is intended to be public API, it should be documented as such (including KDoc contract/expectations).
fun convertArgumentValue(
    argumentName: String,
    param: KParameter,
    argumentMap: Map<String, Any?>
): Any? {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread website/docs/schema-generator/execution/data-fetching-environment.md Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/execution/convertArgumentValue.kt:56

  • convertArgumentValue is now public (fun) instead of internal. Unless you intentionally want to add/maintain this as a supported public API, it should remain internal to avoid expanding the library surface area and committing to its behavior/signature for external consumers.
fun convertArgumentValue(
    argumentName: String,
    param: KParameter,
    argumentMap: Map<String, Any?>
): Any? {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread website/docs/schema-generator/execution/data-fetching-environment.md Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/execution/convertArgumentValue.kt:56

  • convertArgumentValue appears to have been unintentionally made public (it was previously internal). This expands the library’s public API surface and makes it harder to change this helper without breaking consumers. If external use isn’t intended, restore internal visibility; if it is intended to be public, please add KDoc/README docs and treat it as a supported API (incl. semantic versioning implications).
fun convertArgumentValue(
    argumentName: String,
    param: KParameter,
    argumentMap: Map<String, Any?>
): Any? {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@JordanJLopez JordanJLopez marked this pull request as ready for review April 24, 2026 15:34
@JordanJLopez JordanJLopez changed the title feat: Add DataFetchingEnvironment extension for coercing arguments using Kotlin reflection feat: Add extension, public method for coercing DataFetchingEnvironment arguments into Kotlin objects Apr 24, 2026
@JordanJLopez JordanJLopez changed the title feat: Add extension, public method for coercing DataFetchingEnvironment arguments into Kotlin objects feat: Add extension, public method for coercing DataFetchingEnvironment arguments with Kotlin reflection Apr 24, 2026
@JordanJLopez JordanJLopez marked this pull request as draft April 24, 2026 16:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants