springgraphql-javaspring-graphql

HttpGraphQlTester doesn't work with ArgumentValue


I'm having a mutation defined to update an image object:

mutation updateImage($input: UpdateImageInput!) {
    updateImage(input: $input) {
        ...Image
    }
}

The UpdateImageInput looks like this:

input UpdateImageInput {
    id: ID!
    version: Int!
    title: String
}

When I send a request using the HttpGraphQlTester I get an error: {message=Variable 'input' has an invalid value: Expected a String input, but it was a 'LinkedHashMap', locations=[{line=1, column=22}

This is how my request looks like

        val input = new MyInput(testImage.getId(), testImage.getVersion(), 
                        ArgumentValue.ofNullable("foo"));
        
        val actual = this.gql
            .documentName("updateImage")
            .fragmentName("fragments/Image")
            .fragmentName("fragments/Address")
            .fragmentName("fragments/LinkedPlanningObject")
            .variable("input", input)
            .execute()
            .errors()
            .verify()
            .path("updateImage")
            .entity(Image.class)
            .get();

When I remove the ArgumentValue and just use a String in my input object, then there is no error. The application works well with another client like graphiql.

Am I missing something or is there any way to configure the client to use the ArgumentValue?


Solution

  • In Spring for GraphQL, ArgumentValue is a reference type designed to know whether a value is absent/null/present. It's mostly designed with the server-side in mind. But I agree that the client side has been overlooked.

    To simply answer your question, this is currently not possible and you would need to write a custom Jackson Serializer to deal with this case right now.

    We (the Spring GraphQL team) could improve the situation. We would need to plug in a customization mechanism in the JSON serialization library to omit that property when ArgumentValue.ommitted(). I have looked into this and the best I came up with was a Jackson PropertyFilter. Unfortunately, this needs to be manually associated with your type, so it's not 100% transparent.

    Assuming we automatically register an "argumentValue" filter for you, this still means your MyInput type needs to be annotated like this:

    @JsonFilter("argumentValue")
    record MyInput(String id, int version, ArgumentValue<String> title) {
      
    }
    

    Would this be an acceptable solution to you?

    Edit: I have created an issue to track this feature request: https://github.com/spring-projects/spring-graphql/issues/1166