3

I have a GraphQL operation which returns a type containing a field. This field takes an argument I'd like to read in the data fetcher.

If the argument is hard-coded (as myArg1 is below), I can directly read its value. If the argument is passed via a variable (as myArg2 is below), I can only read the variable's name, and not its value.

I could manually check each argument's type (e.g., VariableReference, StringValue), and accordingly find the variable's value on the DataFetchingEnvironment, but this is cumbersome. Since GraphQL Java has this info, is it possible for me to directly read the argument's value?

Here's a demo:

val registry = SchemaParser().parse(
    """
    type Query {
        myOperation: MyType!
    }

    type MyType {
        myField(myArg1: String!, myArg2: String!): Boolean!
    }
    """
)
val wiring = newRuntimeWiring()
    .type("Query") { builder ->
        builder.dataFetcher("myOperation") { env ->
            val myField = env.mergedField.singleField.selectionSet.selections[0] as Field
            val args = myField.arguments.map { it.value }
            println(args[0])
            println(args[1])
            true
        }
    }
    .build()
val schema = SchemaGenerator().makeExecutableSchema(registry, wiring)
val graphQl = newGraphQL(schema).build()
val query = """
    query MyOperation(${"$"}myArg2: String!) { 
        myOperation { 
            myField(myArg1: "myVar1", myArg2: ${"$"}myArg2) 
        } 
    }
"""
val builder = ExecutionInput.Builder().query(query).variables(mapOf("myArg2" to "myVar2"))
graphQl.execute(builder) // Trigger data fetcher.

Output:

StringValue{value='myVar1'}
VariableReference{name='myArg2'}
Neel Kamath
  • 1,188
  • 16
  • 34

3 Answers3

0

No need to be so complicated. If you are inside 'myField' 's data fetcher , you can simply get the value of the argument using env.getArgument() :

String myArgumentValue = env.getArgument("myArgument");

For the input type argument, it will return a Map. (See this). For the scalar argument , what java object type will be returned depends on the Coercing of the underlying Scalar implementation.

Ken Chan
  • 84,777
  • 26
  • 143
  • 172
  • The issue is that I'm unable to read the argument's value. I have updated my question to try to make it clearer. – Neel Kamath Jun 17 '20 at 05:10
0

You can get there with something like the following. You'll need to trim ! modifiers from the type names.

One thing I haven't figured out with this method of traversing the schema within a DataFetcher is sometimes the field definition arguments resolve to GraphQLInputObjectTypes in which case you need to cast them and call getName().

environment.getFieldDefinition().getArguments().forEach((arg) -> {
        System.out.println("Env field def arg: " + arg.getName() + ", type: " + arg.getType().toString());
});
-2

There's no way to do this. GraphQL Java doesn't do it because it claims that it doesn't have enough information to give the variable's value when the data fetcher is invoked. This is false because the data fetcher has both the variable's name, and its value. They probably don't want to implement this because they expect you to use DTOs instead. GraphQL Java provides DTOs with the required information.

Create a DTO:

class MyTypeDto {
    fun getMyField(env: DataFetchingEnvironment): Boolean {
        env.arguments // has the values for both arguments
        return false
    }
}

and a data fetcher:

dataFetcher("myOperation") { env -> MyTypeDto() }
Neel Kamath
  • 1,188
  • 16
  • 34