DEV Community

Anisha Mohanty
Anisha Mohanty

Posted on

How to create GraphQL schema dynamically?

Hey everyone. 🀩 I am writing this article to guide you through to a create a dynamic GraphQL schema programmatically as java code. We would be primarily using the graphql-java library for this.

GraphQL Schema

GraphQL has its type system that’s used to define the schema of an API. The syntax for writing schemas is called Schema Definition Language (SDL). We can either define the schema using SDL or define it programmatically as java code. But both of them are static ways of representation. In case you are building schema during runtime, it becomes difficult to recursively add new fields to your predefined definition.

SDL Schema Definition

type Customer {
   name : String
   address : String
   contact : Int 
}

Programmatic Schema Definition

GraphQLObjectType.Builder graphQLObjectType = GraphQLObjectType.newObject();
graphQLObjectType.name("Customer")
                 .field(newFieldDefinition()
                       .name("name")
                       .type(Scalars.GraphQLString))
                 .field(newFieldDefinition()
                       .name("address")
                       .type(Scalars.GraphQLString))
                 .field(newFieldDefinition()
                       .name("conatct")
                       .type(Scalars.GraphQLInt)
                 .build();

We will be focusing on how to extract the metadata of the data source to which you are connecting. Metadata characterizes your data and makes easier for anyone to understand and consume it. To put it simply, metadata is the data describing the data that is being stored in your data source. It generally includes the name, size and number of rows of each table present in a database, along with the columns in each table, their data types, precisions, etc.

Let's get started! πŸš€

To read and store database meta data we will be using two interfaces DatabaseMetaData and ResultSet.The DatabaseMetaData interface is huge, containing hundreds of methods for reading capabilities of a DBMS. You can refer to Javadoc for the complete list of methods.

Obtaining DatabaseMetaData Instance

Here I am using jdbc-url for Teiid, you can choose others too. We obtain the DatabaseMetaData object from a Connection object, like this:

String URL = "jdbc:teiid:customer@mm://localhost:31000";
String USERNAME = "sa";
String PASSWORD = "sa";
Connection connection = DriverManager.getConnection(URL, USERNAME ,PASSWORD );
DatabaseMetaData databaseMetaData = connection.getMetaData();

Listing Database Tables

We can obtain a list of the defined tables in your database or data source with the help of DatabaseMetaData. Here is how that is done:

String table[] = {"TABLE"};

ResultSet resultSet = databaseMetaData.getTables(null,null,null,table);
ArrayList<String> tables = new ArrayList();

    while(resultSet.next()) {
        tables.add(resultSet.getString("TABLE_NAME"));
    }

Listing Database Columns

We can obtain the columns of a table via the DatabaseMetaData object in this manner :

ResultSet columns = databaseMetaData.getColumns(null,null, tableName, null);
     while(columns.next()) {
         String columnName = columns.getString("COLUMN_NAME");
         String datatype = columns.getString("DATA_TYPE");
         String columnsize = columns.getString("COLUMN_SIZE");

         System.out.println(columnName + "---" + datatype + "---" + columnsize);
      }

Creating Schema

Next step would be to create a schema using GraphQLObjectType object, store it's corresponding metadata in HashMap and read it's type from ReturnType class defined in the next section.

ResultSet resultSet = databaseMetaData.getColumns(null, null, (String) tableName, null);

     GraphQLObjectType objectType = null;
     GraphQLObjectType.Builder graphQLObjectType = GraphQLObjectType.newObject();

     System.out.println("-------Schema for Table " + tableName + "-------");
     HashMap <String,String> data  = new HashMap<>();

      while (resultSet.next()) {
           data.put(resultSet.getString("COLUMN_NAME"), resultSet.getString("TYPE_NAME"));

           for (Map.Entry<String, String> hm : data.entrySet()) {

                graphQLObjectType
                        .name(tableName)
                        .field(GraphQLFieldDefinition.newFieldDefinition()
                                .name(hm.getKey())
                                .type(ReturnType(hm.getValue())));
                objectType = graphQLObjectType.build();

            }
        }

Defining the Field Type in Schema

This class returns the type of field in each case, here I have defined only two types GraphQLLong and GraphQLString. You can define accordingly for other types.

public static GraphQLScalarType ReturnType(String type) {
      if(type.equals("long"))
           return Scalars.GraphQLLong;
      else if (type.equals("string"))
           return Scalars.GraphQLString;
      return null;
    }
}

Building and Printing Schema

To print schema is a defined manner we are using SchemaPrinter object which takes an object of GraphQLSchema type.

GraphQLSchema graphQLSchema = GraphQLSchema.newSchema()
                    .query(objectType)
                    .build();

SchemaPrinter schemaPrinter = new SchemaPrinter();
String printer = schemaPrinter.print(graphQLSchema);
System.out.println(printer);

Conclusion

There you have it! You have successfully connected to your data source to fetch database metadata and using the data you constructed your graphQL schema.

You can visit the Github Repo Schema Builder to view the source code. Also check GraphQL Java website to learn more.

You're learning. I'm learning. We're all learning. Let's continue to learn and get better together. Thank you. Happy Reading! πŸŽ‰

You can connect with me on Twitter and LinkedIn ❀️

Top comments (1)

Collapse
 
renu944 profile image
renu944

Hi ,
I have a requirement to generate dynamic query of GraphQL from schema. I need to create dynamic schema and its query by passing table name from the database. I am able to create schema dynamically. Can anyone help me to create dynamic queries on it?

Thanks