graphql-spring-boot
graphql-spring-boot copied to clipboard
Using Upload scalar doesn't work with input object
File upload works great if Upload is a direct input parameter of a query or nested in an array, but fails if it is nested.
Here are the examples to demonstrate:
with this in schema:
type Query {
test1(input: Upload): ID!
test2(input: [Upload]): ID!
test3(input: FileInput): ID!
test4(input: [FileInput]): ID!
}
scalar Upload
input FileInput {
name: String!
file: Upload
}
FileInput is mapped to this java class:
@lombok.Data
@lombok.NoArgsConstructor
public class FileInputDTO {
String name;
Part file;
}
The first two queries work great when called like this:
curl --location --request POST 'http://localhost:8080/graphql' \
--form 'operations={ "query": "query test1query($input: Upload) {test1 (input: $input) }", "variables": {"input": null } } }' \
--form 'map={ "file0": ["variables.input"] }' \
--form 'file0=@/home/ivan/Downloads/2020-02-13-raspbian-buster-full.zip'
curl --location --request POST 'http://localhost:8080/graphql' \
--form 'operations={ "query": "query test2query($input: [Upload]) {test2 (input: $input) }", "variables": {"input": [null, null] } } }' \
--form 'map={ "file0": ["variables.input.0"], "file1": ["variables.input.1"] }' \
--form 'file0=@/home/ivan/Slike/GOPR6667.MP4' \
--form 'file1=@/home/ivan/Slike/GOPR6665.MP4'
But the last two (with Upload contained in another input type fail:
# called this way:
curl --location --request POST 'http://localhost:8080/graphql' \
--form 'operations={ "query": "query test3query($input: FileInput) {test3 (input: $input) }", "variables": {"input": {"name": "file0.txt", "file": null } } }' \
--form 'map={ "file0": ["variables.input.file"] }' \
--form 'file0=@/home/ivan/Slike/s gopro/GOPR6667.MP4'
The exception that is thrown:
java.lang.IllegalArgumentException: Cannot construct instance of `javax.servlet.http.Part` (no Creators, like default construct, 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: hr.verox.engeon.model.dto.FileInputDTO["file"])
at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3922) ~[jackson-databind-2.10.1.jar:2.10.1]
at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:3863) ~[jackson-databind-2.10.1.jar:2.10.1]
at graphql.kickstart.tools.MethodFieldResolver$createDataFetcher$$inlined$forEachIndexed$lambda$1.invoke(MethodFieldResolver.kt:100) ~[graphql-java-tools-6.0.2.jar:na]
at graphql.kickstart.tools.MethodFieldResolver$createDataFetcher$$inlined$forEachIndexed$lambda$1.invoke(MethodFieldResolver.kt:25) ~[graphql-java-tools-6.0.2.jar:na]
at graphql.kickstart.tools.MethodFieldResolverDataFetcher.get(MethodFieldResolver.kt:201) ~[graphql-java-tools-6.0.2.jar:na]
at graphql.execution.ExecutionStrategy.fetchField(ExecutionStrategy.java:272) ~[graphql-java-14.0.jar:na]
at graphql.execution.ExecutionStrategy.resolveFieldWithInfo(ExecutionStrategy.java:200) ~[graphql-java-14.0.jar:na]
at graphql.execution.AsyncExecutionStrategy.execute(AsyncExecutionStrategy.java:74) ~[graphql-java-14.0.jar:na]
at graphql.execution.Execution.executeOperation(Execution.java:165) ~[graphql-java-14.0.jar:na]
at graphql.execution.Execution.execute(Execution.java:106) ~[graphql-java-14.0.jar:na]
at graphql.GraphQL.execute(GraphQL.java:623) ~[graphql-java-14.0.jar:na]
at graphql.GraphQL.parseValidateAndExecute(GraphQL.java:556) ~[graphql-java-14.0.jar:na]
at graphql.GraphQL.executeAsync(GraphQL.java:520) ~[graphql-java-14.0.jar:na]
at graphql.kickstart.execution.GraphQLInvoker.executeAsync(GraphQLInvoker.java:26) ~[graphql-java-kickstart-9.1.0.jar:na]
at graphql.kickstart.execution.GraphQLInvoker.query(GraphQLInvoker.java:38) ~[graphql-java-kickstart-9.1.0.jar:na]
at graphql.kickstart.execution.GraphQLInvoker.query(GraphQLInvoker.java:31) ~[graphql-java-kickstart-9.1.0.jar:na]
at graphql.kickstart.servlet.HttpRequestHandlerImpl.invoke(HttpRequestHandlerImpl.java:67) ~[graphql-java-servlet-9.1.0.jar:na]
at graphql.kickstart.servlet.HttpRequestHandlerImpl.execute(HttpRequestHandlerImpl.java:52) ~[graphql-java-servlet-9.1.0.jar:na]
at graphql.kickstart.servlet.HttpRequestHandlerImpl.handle(HttpRequestHandlerImpl.java:37) ~[graphql-java-servlet-9.1.0.jar:na]
at graphql.kickstart.servlet.AbstractGraphQLHttpServlet.doRequest(AbstractGraphQLHttpServlet.java:147) ~[graphql-java-servlet-9.1.0.jar:na]
at graphql.kickstart.servlet.AbstractGraphQLHttpServlet.doRequestAsync(AbstractGraphQLHttpServlet.java:137) ~[graphql-java-servlet-9.1.0.jar:na]
at graphql.kickstart.servlet.AbstractGraphQLHttpServlet.doPost(AbstractGraphQLHttpServlet.java:169) ~[graphql-java-servlet-9.1.0.jar:na]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) ~[tomcat-embed-core-9.0.29.jar:9.0.29]