rocketraman
07/21/2021, 1:49 PMClosedRange<LocalDate>
. I have defined and registered a Coercing<ClosedRange<LocalDate>, String>
(and via debugger confirmed the coercer is being called at runtime), but I get a Jackson exception when parsing an Input:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `kotlin.ranges.ClosedRange` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: my.MyInput["range"])
Any idea why that would be happening?Dariusz Kuc
07/21/2021, 1:58 PMClosedRange<LocalDate>
? Jackson requires default (empty) constructor or you will have to annotate your data classrocketraman
07/21/2021, 1:58 PMClosedRange
is a Kotlin stdlib type.ClosedRange
is an interface type? The underlying type is ComparableRange
(private to stdlib).Dariusz Kuc
07/21/2021, 2:10 PMrocketraman
07/21/2021, 2:10 PMat com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4236) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:4167) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.expediagroup.graphql.generator.execution.FunctionDataFetcher.convertValue(FunctionDataFetcher.kt:161) ~[graphql-kotlin-schema-generator-4.1.1.jar:4.1.1]
at com.expediagroup.graphql.generator.execution.FunctionDataFetcher.convertArgumentToObject(FunctionDataFetcher.kt:142) ~[graphql-kotlin-schema-generator-4.1.1.jar:4.1.1]
at com.expediagroup.graphql.generator.execution.FunctionDataFetcher.mapParameterToValue(FunctionDataFetcher.kt:114) ~[graphql-kotlin-schema-generator-4.1.1.jar:4.1.1]
at com.expediagroup.graphql.generator.execution.FunctionDataFetcher.getParameters(FunctionDataFetcher.kt:90) ~[graphql-kotlin-schema-generator-4.1.1.jar:4.1.1]
at com.expediagroup.graphql.generator.execution.FunctionDataFetcher.get(FunctionDataFetcher.kt:69) ~[graphql-kotlin-schema-generator-4.1.1.jar:4.1.1]
at graphql.execution.ExecutionStrategy.fetchField(ExecutionStrategy.java:270) ~[graphql-java-16.2.jar:?]
at graphql.execution.ExecutionStrategy.resolveFieldWithInfo(ExecutionStrategy.java:203) ~[graphql-java-16.2.jar:?]
at graphql.execution.AsyncExecutionStrategy.execute(AsyncExecutionStrategy.java:60) ~[graphql-java-16.2.jar:?]
at graphql.execution.ExecutionStrategy.completeValueForObject(ExecutionStrategy.java:646) ~[graphql-java-16.2.jar:?]
at graphql.execution.ExecutionStrategy.completeValue(ExecutionStrategy.java:438) ~[graphql-java-16.2.jar:?]
at graphql.execution.ExecutionStrategy.completeField(ExecutionStrategy.java:390) ~[graphql-java-16.2.jar:?]
at graphql.execution.ExecutionStrategy.lambda$resolveFieldWithInfo$1(ExecutionStrategy.java:205) ~[graphql-java-16.2.jar:?]
at java.util.concurrent.CompletableFuture.uniApplyNow(CompletableFuture.java:680) ~[?:?]
at java.util.concurrent.CompletableFuture.uniApplyStage(CompletableFuture.java:658) ~[?:?]
at java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:2094) ~[?:?]
at graphql.execution.ExecutionStrategy.resolveFieldWithInfo(ExecutionStrategy.java:204) ~[graphql-java-16.2.jar:?]
at graphql.execution.AsyncExecutionStrategy.execute(AsyncExecutionStrategy.java:60) ~[graphql-java-16.2.jar:?]
at graphql.execution.Execution.executeOperation(Execution.java:165) ~[graphql-java-16.2.jar:?]
at graphql.execution.Execution.execute(Execution.java:104) ~[graphql-java-16.2.jar:?]
at graphql.GraphQL.execute(GraphQL.java:557) ~[graphql-java-16.2.jar:?]
at graphql.GraphQL.parseValidateAndExecute(GraphQL.java:482) ~[graphql-java-16.2.jar:?]
at graphql.GraphQL.executeAsync(GraphQL.java:446) ~[graphql-java-16.2.jar:?]
at com.expediagroup.graphql.server.execution.GraphQLRequestHandler.executeRequest$suspendImpl(GraphQLRequestHandler.kt:45) ~[graphql-kotlin-server-4.1.1.jar:4.1.1]
at com.expediagroup.graphql.server.execution.GraphQLRequestHandler.executeRequest(GraphQLRequestHandler.kt) ~[graphql-kotlin-server-4.1.1.jar:4.1.1]
at com.expediagroup.graphql.server.execution.GraphQLServer.execute$suspendImpl(GraphQLServer.kt:48) ~[graphql-kotlin-server-4.1.1.jar:4.1.1]
at com.expediagroup.graphql.server.execution.GraphQLServer.execute(GraphQLServer.kt) ~[graphql-kotlin-server-4.1.1.jar:4.1.1]
<my call handler here>
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
<jackson databind classes here>
Dariusz Kuc
07/21/2021, 2:14 PMrocketraman
07/21/2021, 2:15 PMDariusz Kuc
07/21/2021, 2:17 PMrocketraman
07/21/2021, 2:19 PMDariusz Kuc
07/21/2021, 2:28 PMmapParameterToValue
with custom logic to handle closed rangerocketraman
07/21/2021, 2:30 PMClosedRange
field. So do I need to add special logic for every type where I use ClosedRange
(yuck)?Dariusz Kuc
07/21/2021, 2:43 PMrocketraman
07/21/2021, 2:47 PMClosedRange
is a property of my input data class type, and when mapParameterToValue
is called, the param
value is the input data class type. Just tried it with the debugger.Dariusz Kuc
07/21/2021, 2:48 PMrocketraman
07/21/2021, 5:27 PMStdDeserializer
but this is what seems to be happening:
serialized input on the wire
-> coercer deserializes into ClosedRange<LocalDate>
-> something serializes ClosedRange<LocalDate>
into crazy JSON as the java.time objects have lots of internal state
-> custom deserializer runs with crazy JSONShane Myrick
07/21/2021, 6:47 PMFunctionDataFetcher
https://github.com/ExpediaGroup/graphql-kotlin/blob/a6b957c999398c741cdfbc955fb862[…]expediagroup/graphql/generator/execution/FunctionDataFetcher.kt
As mentioned above, you can customize the how FunctionDataFetcher
gets created with KotlinDataFetcherFactoryProvider
rocketraman
07/21/2021, 6:48 PMClosedRange<LocalDate>
property. I'm not going to create custom fetchers for every object that happens to have a property of that type.