Skip to content

Default values for enum fields on input types not set correctly #257

Closed
@skroll

Description

@skroll

It appears in the SchemaParser#createInputObject that the default value of input fields is not set to a proper value if it is an enum.

When the default value of a field on an input type is an enum, the parser is supplying an EnumValue, and it is being set, so when the schema metadata is retrieved, a CoercingSerializeException is thrown by graphql-java, since it can't do any comparison of `EnumValue.

private fun createInputObject(definition: InputObjectTypeDefinition): GraphQLInputObjectType {
val builder = GraphQLInputObjectType.newInputObject()
.name(definition.name)
.definition(definition)
.description(getDocumentation(definition))
builder.withDirectives(*buildDirectives(definition.directives, setOf(), Introspection.DirectiveLocation.INPUT_OBJECT))
definition.inputValueDefinitions.forEach { inputDefinition ->
val fieldBuilder = GraphQLInputObjectField.newInputObjectField()
.name(inputDefinition.name)
.definition(inputDefinition)
.description(getDocumentation(inputDefinition))
.defaultValue(inputDefinition.defaultValue)
.type(determineInputType(inputDefinition.type))
.withDirectives(*buildDirectives(definition.directives, setOf(), Introspection.DirectiveLocation.INPUT_FIELD_DEFINITION))
builder.field(directiveGenerator.onInputObjectField(fieldBuilder.build(), DirectiveBehavior.Params(runtimeWiring)))
}
return directiveGenerator.onInputObject(builder.build(), DirectiveBehavior.Params(runtimeWiring))
}

However, further down the SchemaParser, the createField method uses the buildDefaultValue function for the default value. By simply changing createInputObject to use buildDefaultValue, this seems to fix it.

private fun createField(field: GraphQLFieldDefinition.Builder, fieldDefinition: FieldDefinition): GraphQLFieldDefinition.Builder {
field.name(fieldDefinition.name)
field.description(getDocumentation(fieldDefinition))
field.definition(fieldDefinition)
getDeprecated(fieldDefinition.directives)?.let { field.deprecate(it) }
field.type(determineOutputType(fieldDefinition.type))
fieldDefinition.inputValueDefinitions.forEach { argumentDefinition ->
val argumentBuilder = GraphQLArgument.newArgument()
.name(argumentDefinition.name)
.definition(argumentDefinition)
.description(getDocumentation(argumentDefinition))
.defaultValue(buildDefaultValue(argumentDefinition.defaultValue))
.type(determineInputType(argumentDefinition.type))
.withDirectives(*buildDirectives(argumentDefinition.directives, setOf(), Introspection.DirectiveLocation.ARGUMENT_DEFINITION))
field.argument(directiveGenerator.onArgument(argumentBuilder.build(), DirectiveBehavior.Params(runtimeWiring)))
}
field.withDirectives(*buildDirectives(fieldDefinition.directives, setOf(), Introspection.DirectiveLocation.FIELD_DEFINITION))
return field
}

The issue tracks down to the GraphQLEnumType:

https://github.com/graphql-java/graphql-java/blob/8ba2d1da9a84d4490b59f59a43fb0d2f4d58a0f1/src/main/java/graphql/schema/GraphQLEnumType.java#L138-L162

The value being passed in ends up looking like EnumValue{name='FOO'}, which will never match, but by using buildDefaultValue, it turns it into the enum name, which the check will succeed.

All of this is may be moot point however, since it appears that graphql-java doesn't seem to support default values inside of input types (it gets coerced into a null value if is not present). However, I believe this is definitely a bug on the graphql-java-tools side.

What I'm not sure of is the possible complications of always using buildDefaultValue(inputDefinition.defaultValue), if any.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions