dgs-framework
dgs-framework copied to clipboard
bug: Complex InputArgument serialized as Optional List of Complex Type
Context
Given the following GraphQL Schema...
type Query {
hello(person:[Person]): String
}
input Person {
name:String
}
And a Data Fetcher that serializes to a Optional<List<Person>>
, as below
@DgsData(parentType = "Query", field = "hello")
fun someFetcher(@InputArgument person: Optional<List<Person>>): String {
return "Hello, ${person.get().joinToString(", ")}"
}
Expectation
I should see that the optional arguments have a list of Person
references, assuming we have a simple Person
pojo.
Actual behavior
The following error ensues
java.util.LinkedHashMap cannot be cast to com.netflix.graphql.dgs.internal.kotlin.test.Person
Steps to reproduce
Test case.
@Test
fun `@InputArgument on an optional list of input types, with no input argument name`() {
val schema = """
type Query {
hello(person:[Person]): String
}
input Person {
name:String
}
""".trimIndent()
val fetcher = object {
@DgsData(parentType = "Query", field = "hello")
fun someFetcher(@InputArgument person: Optional<List<Person>>): String {
assertThat(person)
.isNotEmpty
.get()
.extracting { ls -> ls.map { it.name } }.asList()
.containsOnly("tester 1", "tester 2")
return "Hello, ${person.get().joinToString(", ")}"
}
}
withComponents("helloFetcher" to fetcher)
val build = GraphQL.newGraphQL(provider.schema(schema)).build()
val executionResult = build.execute("""{hello(person: [{name: "tester 1"}, {name: "tester 2"}])}""")!!
assertThat(executionResult).isNotNull
assertThat(executionResult.errors).isEmpty()
assertThat(executionResult.isDataPresent).isTrue
val data = executionResult.getData<Map<String, *>>()
assertThat(data["hello"]).isEqualTo("Hello, tester 1, tester 2")
}
Hi @berngp i was tracking this bug for more then a month. Is it going to be fixed in next releases. when we can expect for a new release
Hi @berngp can you help me how to resolve this issue, or by pass with any other thing. I have using this optional field for a pojo.
if we don't have solutions is we are going to resolve in subsequent releases
regards, kiran kumar
Hi @k2k1422, we haven't been able to address this yet. As a workaround you can have a List as an argument and expect it to be null or empty. If you need to know if it was set, you can define a DataFetchingEnvironment
as input to your data fetcher, and through it understand if the field was set or not in the request. e.g.
@DgsData(parentType = "Query", field = "hello")
fun someFetcher(@InputArgument persons: List<String>, dfe: DataFetchingEnvironment): String {
val optList =
if (dfe.containsArgument("persons"))
Optional.ofNullable(persons)
else
Optional.empty()
// ....
}
Hi @berngp,
I ran into another issue that may be the same as the above issue, but may be a different issue and just related to this. I thought I'd post here first and get your thoughts.
Essentially it appears that the DefaultInputObjectMapper
class has issues with correctly mapping parameterized types with either an upper bound on a ?
operator or a List<T>
field. With the upper bounded wildcard it is unable to find the implementing class, and further when trying to use a concrete wrapper implementation to work around the above issue, it ignores the List
type and attempts to map the list to a single instance of the parameterized type.
For more details I have put together a sample project that demonstrates the problem (which appears to be a bug in the getFieldType
method of the DefaultInputObjectMapper
class). I have included a ReadMe and java docs with more details.
https://github.com/lbusch25/lawson-busch-input-demo
This is fixed with #1254 @lbusch25
@antholeole - thank you!
Curious if you know when that will be released? Looks like its not included in 5.3.0
and testing my example with that version verifies the issue persists. I'm excited to verify so that we can improve the schema workaround we implemented as a result.
You can use latest master or wait until the next release. It’s currently on master but it has not been made into a release yet. For now if you’d like you can point to the repo using git
I plan on release later this week or early next.