Dynamic generate GraphQL schema supports

Dynamic generate GraphQL schema supports


11

Is it possible to dynamically create a GraphQL schema ?

We store the data in mongoDB and there is a possibility of new fields getting added. We do not want any code change to happen for this newly added field in the mongoDB document.

Is there any way we can generate the schema dynamically ?

Schema is defined in code, but for java(schema as pojo), when new
attribute is added, you have to update and recompile code, then
archive and deploy the jar again. Any way to generate schema by the
data instead of pre-define it?

Currently we are using java related projects (graphql-java, graphql-java-annotations) for GraphQL development.

2 Answers
2


10

You could use graphql-spqr (or the related Spring Boot starter, if applicable), it allows you auto-generate a schema based on your service classes. In your case, it would look like this:

public class Pojo {

    private Long id;
    private String name;

    // whatever Ext is, any (complex) object would work fine
   private List<Ext> exts;
}

public class Ext {
    public String something;
    public String somethingElse;
}

Presumably, you have a service class containing your business logic:

public class PojoService {

    //this could also return List<Pojo> or whatever is applicable
    @GraphQLQuery(name = "pojo")
    public Pojo getPojo() {...}
}

To expose this service, you’d just do the following:

GraphQLSchema schema = new GraphQLSchemaGenerator()
                .withOperationsFromSingleton(new PojoService())
                .generate();

You could then fire a query such as:

query test {
    pojo {
        id
        name 
        exts {
            something
            somethingElse
        } } }

No need for strange wrappers or custom code of any kind, nor sacrificing type safety. Works with generics, dependency injection, or any other jazz you may have in your project.

Full disclosure: I’m the author of graphql-spqr.

3

  • please, can you help with this? stackoverflow.com/questions/56802809/…

    – DaviesTobi alex

    Jun 28, 2019 at 7:49

  • Is there support for parsing spring-graphql annotations and not use leangen annotations?

    – AlikElzin-kilaka

    Aug 24, 2022 at 12:29

  • @AlikElzin-kilaka The problem is that Spring's GraphQL annotations simply don't fit. They're meant to map methods to an existing schema, and as such don't let you provide enough info to generate the schema. But I'll look into what's possible. SPQR has some support for Microprofile annotations, which are intended to works exactly like the leagnen ones, but are standardized. Unfortunately the support is incomplete at this moment, but it is on my radar.

    – kaqqao

    1 hour ago


0

After some days’ investigation. I found it is hard to generate schema dynamically in Java (or cost is so high).

Well, from another way. I think we can use Map as a compromised way to accomplish that.

  • POJO/Entity

    public class POJO{
        @GraphQLField
        private Long id;
    
        @GraphQLField
        private String name;
    
        // ...
    
        @GraphQLField
        private GMap exts;   
    }
    

    GMap is a customized Map (Because Map/HashMap is a JDK inner class which could not make as GraphQL Schema but only extend).

  • GMap

    public class GMap extends HashMap<String, String> {
    
        @GraphQLField
        public String get(@GraphQLName("key") String key) {
            return super.get(key);
        }
    }
    
  • Retrieve data from Client

    // query script
    query test
    {
        your_method
        {
            id
            name
            exts {
                get(key: "ext") // Add a extended attribute someday
            }
        }
    }
    
    // result 
    {
        "errors":[],
        "data":
        {
            "list":
            [
                {"id":1, name: "name1", exts: {"get": "ext1"}},
                {"id":2, name: "name2", exts: {"get": "ext2"}}
            ]
        }
    }
    



Leave a Reply

Your email address will not be published. Required fields are marked *