Search code examples
javaspringgraphqlspring-graphql

How to implement union in spring-graphql? I get error that I'm requesting object but its rather a 'graphql.schema.GraphQLUnionType'


I wanted to create a union named Tables, that holds all the other tables and the user can request the table accordingly. I get the error: You have asked for named object type 'Tables', but it's not an object type but rather a 'graphql.schema.GraphQLUnionType'

Here is my graphql schema:

type Query{ 
  getData: [Tables]
}
union Tables = address | identifier

My query is a simple one:

query allData{ 
 getData{ 
  __typename 
 } 
}

My Java method looks like this:

@QueryMapping 
public List getData() { 
 return List.of(new Address());
}

Here is the error I'm receiving:

ERROR 14724 - [nio-8880-exec-1] o.a.c.c.[. [. [/].[dispatcherServlet] : Servlet.service() for servlet
[dispatcherServlet] threw exception

java.util.concurrent.CompletionException Create breakpoint: graphql.AssertException: You have asked for named object type 'Tables' but its not an object type but rather a 'graphql.schema.GraphQLUnionType'

at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:331) ~[na:na]

at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:346) ~[na:na] at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete (CompletableFuture.java:870) ~[na:na]

java.base/java.util.concurrent.CompletableFuture.uniWhenCompleteStage(CompletableFuture.java:883) -[na:na]

at at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:2251) ~[na:na]

at graphql.execution.Execution.executeoperation(Execution.java:174) ~[graphql-java-18.5.jar:na]

at graphql.execution.Execution.execute(Execution.java:105) -[graphql-java-18.5.jar:na]

at graphql.GraphQL.execute(GraphQL.java:641) [graphql-java-18.5.jar:na]

at graphql.GraphQL.LambdasparseValidateAndExecute$11(GraphQL.java:561) -[graphql-java-18.5.jar:na] at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1106)-[na:na]

at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2235)-[na:na]

at graphql.GraphQL.parseValidateAndExecute(GraphQL.java:556) -[graphql-java-18.5.jar:na] at graphql.GraphQL.executeAsync(Graphq.java:524) [graphql-java-18.5.jar:na]

at org.springframework.graphql.execution.DefaultExecutionGraphql.Service.Lambda$execute$2(DefaultExecution@nave -[spring-graphql-1.0.6.jar:1.0.6]

at reactor.core.publisher.MonoDeferContextual.subscribe(MongDeferContextual.java:47) -[ reactor-core-3.4.33.jar:3.4.33]

I saw some implementations and this should work, but throws an error in my case.

My Classes Address and Identifier are Hibernate Entities.

I simply wanted to create a generic controller that can serve as an entry point for all the tables. I thought union would do the job, what can I do in this case?


Solution

  • TLDR: Match the name of your object in the GraphQL schema to your Java class (along with case sensitivity), and you'll have a working code.


    I solved the error I was getting. Apparently, for the normal GraphQL queries, it doesn't matter if the name of your entity in the GraphQL schema, as well as the Java class, is the same or not.

    However, when you create a union with the same entities, the names in the GraphQL schema and Java class must match with case sensitivity.

    Basically, if you have an object Address, and you make the GraphQL schema like this:

    type address{
    .....
    }
    

    and the Java Object like this:

    Class Address{
    ....
    }
    

    a simple GraphQL query like this would still work:

    type Query{
       getAddress: address
    }
    

    However, if you create a union of the Tables as I did, it'll throw an error.

    The following code won't work and will throw the error that I had been receiving.

    type Query{ 
       getData: [Tables]
    }
    
    type address{
       .....
    }
        
    union Tables = address | identifier
    

    You need the name of your object in the GraphQL schema and the Java class to be exactly the same (along with case sensitivity). I changed 'address' to 'Address' in the GraphQL schema, and voila!!

    The final code that worked is as follows:

    Java class:

    Class Address{
    ....
    }
    

    GraphQL schema:

    type Address{
        .....
    }
    
    type Query{ 
       getData: [Tables]
    }
        
    union Tables = Address | Identifier