Skip to content

ClassCastException when changing fields with visitor #2546

@pvgoddijn

Description

@pvgoddijn

When you have an interfaceType implementing an interface through a type Reference, tranformation fails because
GraphQLInterfaceType.Builder.replaceInterfaces() expects a list of GraphQLInterfaceType but that list can contain GraphQlTypeReference objects Too (to the interface)

i think replacing GraphQLInterfaceType with GraphQLNamedType would fix it

I reproduced it in a junitTest case

Stacktrace:

java.lang.ClassCastException: class graphql.schema.GraphQLTypeReference cannot be cast to class graphql.schema.GraphQLInterfaceType (graphql.schema.GraphQLTypeReference and graphql.schema.GraphQLInterfaceType are in unnamed module of loader 'app')

	at graphql.schema.GraphQLInterfaceType$Builder.replaceInterfaces(GraphQLInterfaceType.java:413)
	at graphql.schema.GraphQLInterfaceType.lambda$withNewChildren$2(GraphQLInterfaceType.java:203)
	at graphql.schema.GraphQLInterfaceType.transform(GraphQLInterfaceType.java:166)
	at graphql.schema.GraphQLInterfaceType.withNewChildren(GraphQLInterfaceType.java:200)
	at graphql.schema.GraphQLInterfaceType.withNewChildren(GraphQLInterfaceType.java:39)
	at graphql.schema.GraphQLSchemaElementAdapter.withNewChildren(GraphQLSchemaElementAdapter.java:27)
	at graphql.schema.SchemaTransformer.moveUp(SchemaTransformer.java:501)
	at graphql.schema.SchemaTransformer.zipUpToDummyRoot(SchemaTransformer.java:384)
	at graphql.schema.SchemaTransformer.traverseAndTransform(SchemaTransformer.java:279)
	at graphql.schema.SchemaTransformer.transformImpl(SchemaTransformer.java:147)
	at graphql.schema.SchemaTransformer.transform(SchemaTransformer.java:121)
	at graphql.schema.SchemaTransformer.transformSchema(SchemaTransformer.java:89)
	at nl.base.servlets.graphql.schema.TestJavaGraphQL.testTransForm(TestJavaGraphQL.java:98)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

ReproductionCode:

@Test
	public void testTransForm() {

		GraphQLInterfaceType iFace = GraphQLInterfaceType.newInterface().name("iFace")
				.field(builder -> builder.type(Scalars.GraphQLString).name("field"))
				.withInterface(GraphQLTypeReference.typeRef("iFace2"))
				.build();

		GraphQLInterfaceType iFace2 = GraphQLInterfaceType.newInterface().name("iFace2")
				.field(builder -> builder.type(Scalars.GraphQLString).name("field"))
				.build();
		GraphQLObjectType impl = GraphQLObjectType.newObject().name("impl")
				.field(builder -> builder.type(Scalars.GraphQLString).name("field"))
				.withInterfaces(GraphQLTypeReference.typeRef("iFace"))
				.withInterfaces(GraphQLTypeReference.typeRef("iFace2"))
				.build();

		Builder codeRegBuilder = GraphQLCodeRegistry.newCodeRegistry().typeResolver(iFace, env -> impl)
				.typeResolver(iFace2, env -> impl);

		GraphQLSche
ma schema = GraphQLSchema.newSchema()
				.codeRegistry(codeRegBuilder.build())
				.additionalType(iFace).additionalType(iFace2)
				.query(GraphQLObjectType
						.newObject()
						.name("test")
						.field(builder -> builder.name("iFaceField").type(impl))
				).build();
//		SchemaUtil.replaceTypeReferences(schema); // this is not wanted nor helps but i thought it might help
		SchemaTransformer.transformSchema(schema, new GraphQLTypeVisitorStub() {
			@Override
			public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition node,
					TraverserContext<GraphQLSchemaElement> context) {
				GraphQLFieldDefinition transform = node.transform(
						builder -> builder.argument(builder1 -> builder1.name("arg").type(Scalars.GraphQLString)));
				changeNode(context, transform);
				return super.visitGraphQLFieldDefinition(node, context);
			}
		});
	}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions