Skip to content

Known Issues

Oryan edited this page Jun 18, 2021 · 3 revisions

Upload scalars within input objects cannot be parsed

Scalars work fine by themselves (or in an array) but not if they are defined as a field on an input object. This is because input objects can be arbitrarily complex and so they are parsed using a Jackson object mapper. If for some reason the default mapper doesn't know how to parse that scalar it will fail. For most scalars, this can be worked around by providing an StdDeserializer with the mapper via the objectMapperProvider option. However, for the Upload scalar, which is often mapped to a Spring Part or MultipartFile this is becomes tricky because there is no standard way to instantiate these objects manually. And so, mocks are the best option available in this case. A full working example is provided here.


A second way to overcome this is by replacing Part or MultipartFile with String in our resolvers while holding a reference to the actual files in a custom context object.
In the controller method, before calling the GraphQL executor, we need to update the query with file references.
For example, if the HTTP request would look something like this:

operations: {"operationName":"uploadFile","variables":{"input": [{"file": null},{"file": null}]},"query":"mutation uploadFile($input: [FileInput]) { uploadFile(input: $input) { id }"}

map: { "file0": ["variables.input.0.file"] , "file1":["variables.input.1.file"]}

We will update the input to look like this:

..."input": [{"file": "file0"}, {"file": "file1"}]...

This requires parsing the query's JSON to get to the specific nodes that represent files and modify them.
Finally we need to create a mapping from these references (file0, file1...) to the actual file parts in the context object (Map<String, Part/MultipartFile> files)
And we should be able to retrieve the file parts from the context:

    public void uploadFile(
        List<FileInput> input,
        GraphQLContext context
    ) {
        context.getFile(input.get(0).getFile());
        ...
    }

    class FileInput {
        String file;
        String path;
    }
Clone this wiki locally