LIGHT

  • News
  • Docs
  • Community
  • Reddit
  • GitHub

Mutation Tutorial with IDL

In the mutation tutorial, we have created a new project by copying and modifying the hello world tutorial. In this tutorial, we are going to generate the project from IDL and change it accordingly. Users can compare between these two implementations and see the difference. It helps users to understand that in which case to copy an existing project and create the schema or create the schema first and generate the project from it.

Prepare environment

First, we need to clone light-codegen, model-config, and light-example-4j into your workspace. I am using networknt as workspace in my home directory.

cd ~/networknt
git clone https://github.com/networknt/light-codegen.git
git clone https://github.com/networknt/light-example-4j.git
git clone https://github.com/networknt/model-config.git

Let’s build light-codegen so that we can use the command line to generate the code.

cd ~/networknt/light-codegen
mvn clean install -DskipTests

Config and Schema

Here is the config.json file to control the light-codegen.

{
  "name": "mutation-example",
  "version": "1.0.1",
  "groupId": "com.networknt",
  "artifactId": "mutation-example",
  "schemaPackage": "com.networknt.example.mutation",
  "schemaClass": "MutationSchema",
  "overwriteSchemaClass": true,
  "httpPort": 8080,
  "enableHttp": false,
  "httpsPort": 8443,
  "enableHttps": true,
  "enableHttp2": true,
  "enableRegistry": false,
  "supportDb": true,
  "dbInfo": {
    "name": "mysql",
    "driverClassName": "com.mysql.jdbc.Driver",
    "jdbcUrl": "jdbc:mysql://mysqldb:3306/oauth2?useSSL=false",
    "username": "root",
    "password": "my-secret-pw"
  },
  "supportH2ForTest": false,
  "supportClient": false
}

The schema file mutation-schema.graphqls can be found at model-config/graphql/mutation-idl folder.

schema {
  query: Query
  mutation: Mutation
}

type Query {
  numberHolder: NumberHolder
}

type NumberHolder {
  theNumber: Int
}

type Mutation {
  changeTheNumber(newNumber: Int!): NumberHolder
  failToChangeTheNumber(newNumber: Int): NumberHolder
}

Generate

Given the light-codegen is built, let’s generate the project from the config file and IDL. For more detail about the light-codegen please refer to light-codegen graphql.

We are going to generate the code to the same folder on light-example-4j/graphql/mutation-idl, let’s rename the existing folder so that you can compare after you follow the tutorial.

cd ~/networknt/light-example-4j/graphql
mv mutation-idl mutation-idl.bak

Now let’s run the command line in ~/networknt folder.

cd ~/networknt
java -jar light-codegen/codegen-cli/target/codegen-cli.jar -f light-graphql-4j -o light-example-4j/graphql/mutation-idl -m model-config/graphql/mutation-idl/mutation-schema.graphqls -c model-config/graphql/mutation-idl/config.json

Modify

After the light-codegen, we have the following StarWarsSchema generated.

package com.networknt.example.mutation;

import com.networknt.graphql.router.SchemaProvider;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * Created by steve on 25/03/17.
 */
public class MutationSchema implements SchemaProvider {
    private static Logger logger = LoggerFactory.getLogger(SchemaProvider.class);
    private static String schemaName = "schema.graphqls";
    @Override
    public GraphQLSchema getSchema() {
        SchemaParser schemaParser = new SchemaParser();
        TypeDefinitionRegistry typeRegistry = null;

        try(InputStream is = getClass().getClassLoader().getResourceAsStream(schemaName)) {
            typeRegistry = schemaParser.parse(new InputStreamReader(is));
        } catch (IOException e) {
            logger.error("IOException:", e);
        }

        RuntimeWiring wiring = RuntimeWiring.newRuntimeWiring()
            // put other wiring logic here.
            .build();

        return new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring);
    }
}

Let’s create a model and wire in the logic to make the generated code works. First, let’s create a model class for NumberHolder.

package com.networknt.example.mutation;

/**
 * Created by Nicholas Azar on October 16, 2017.
 */
public class NumberHolder {
    private int theNumber;

    public NumberHolder(int theNumber) {
        this.theNumber = theNumber;
    }

    public int getTheNumber() {
        return theNumber;
    }

    public void setTheNumber(int theNumber) {
        this.theNumber = theNumber;
    }
}

Next, let’s create a class that wires the business logic.

package com.networknt.example.mutation;

import graphql.schema.DataFetcher;

/**
 * Created by Nicholas Azar on October 16, 2017.
 */
public class MutationWiring {

    public static class Context {
        final NumberHolder numberHolder;

        public Context(int theNumber) {
            this.numberHolder = new NumberHolder(theNumber);
        }

        public NumberHolder getNumberHolder() {
            return this.numberHolder;
        }
    }

    private static Context context = new Context(5);

    static DataFetcher numberHolderFetcher = dataFetchingEnvironment -> context.getNumberHolder();

    static DataFetcher theNumberFetcher = dataFetchingEnvironment -> context.getNumberHolder().getTheNumber();

    static DataFetcher changeTheNumberFetcher = dataFetchingEnvironment -> {
        context.getNumberHolder().setTheNumber(dataFetchingEnvironment.getArgument("newNumber"));
        return context.getNumberHolder();
    };

    static DataFetcher failToChangeTheNumberFetcher = dataFetchingEnvironment -> {
        throw new RuntimeException("Simulate failing to change the number.");
    };

}

With the above two classes, let’s modify the generated code to wire the logic in.


package com.networknt.example.mutation;

import com.networknt.graphql.router.SchemaProvider;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * Created by Nicholas Azar on October 16, 2017.
 */
public class MutationSchema implements SchemaProvider {
    private static Logger logger = LoggerFactory.getLogger(SchemaProvider.class);
    private static String schemaName = "schema.graphqls";
    @Override
    public GraphQLSchema getSchema() {
        SchemaParser schemaParser = new SchemaParser();
        TypeDefinitionRegistry typeRegistry = null;

        try(InputStream is = getClass().getClassLoader().getResourceAsStream(schemaName)) {
            typeRegistry = schemaParser.parse(new InputStreamReader(is));
        } catch (IOException e) {
            logger.error("IOException:", e);
        }

        RuntimeWiring wiring = buildRuntimeWiring();
        return new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring);
    }

    private RuntimeWiring buildRuntimeWiring() {
        return RuntimeWiring.newRuntimeWiring()
                .type(TypeRuntimeWiring.newTypeWiring("Query")
                        .dataFetcher("numberHolder", MutationWiring.numberHolderFetcher))
                .type(TypeRuntimeWiring.newTypeWiring("theNumber")
                        .dataFetcher("theNumber", MutationWiring.theNumberFetcher))
                .type(TypeRuntimeWiring.newTypeWiring("Mutation")
                        .dataFetcher("changeTheNumber", MutationWiring.changeTheNumberFetcher)
                        .dataFetcher("failToChangeTheNumber", MutationWiring.failToChangeTheNumberFetcher)
                )
                .build();
    }

}

Build

With all the changes done, we can build the server and start it.

cd ~/networknt/light-example-4j/graphql/mutation-idl
mvn clean install exec:exec

Test

Now we can test it with GraphiQL web interface.

Open your browser and point to

https://localhost:8443/graphql

Now you can explore the schema on Documentation Explorer. There should be a query and a mutation.

  • Test query with GraphiQL
query {
  numberHolder {
    theNumber
  }
}

The result should be something like:

{
  "data": {
    "numberHolder": {
      "theNumber": 6
    }
  }
}
  • Test mutation with GraphiQL
mutation {
  changeTheNumber(newNumber:4) {
    theNumber
  }
}

The result should be:

{
  "data": {
    "changeTheNumber": {
      "theNumber": 4
    }
  }
}
  • Test the query again

With the same query in the beginning, we should have the updated value 4 returned.

query {
  numberHolder {
    theNumber
  }
}

The result should be:

{
  "data": {
    "numberHolder": {
      "theNumber": 4
    }
  }
}
  • Test mutation with variables

Query:

mutation ($n: Int!) {
  changeTheNumber(newNumber: $n) {
    theNumber
  }
}

Variables

{"n": 5}

And the result should be:

{
  "data": {
    "changeTheNumber": {
      "theNumber": 5
    }
  }
}
  • About Light
    • Overview
    • Testimonials
    • What is Light
    • Features
    • Principles
    • Benefits
    • Roadmap
    • Community
    • Articles
    • Videos
    • License
    • Why Light Platform
  • Getting Started
    • Get Started Overview
    • Environment
    • Light Codegen Tool
    • Light Rest 4j
    • Light Tram 4j
    • Light Graphql 4j
    • Light Hybrid 4j
    • Light Eventuate 4j
    • Light Oauth2
    • Light Portal Service
    • Light Proxy Server
    • Light Router Server
    • Light Config Server
    • Light Saga 4j
    • Light Session 4j
    • Webserver
    • Websocket
    • Spring Boot Servlet
  • Architecture
    • Architecture Overview
    • API Category
    • API Gateway
    • Architecture Patterns
    • CQRS
    • Eco System
    • Event Sourcing
    • Fail Fast vs Fail Slow
    • Integration Patterns
    • JavaEE declining
    • Key Distribution
    • Microservices Architecture
    • Microservices Monitoring
    • Microservices Security
    • Microservices Traceability
    • Modular Monolith
    • Platform Ecosystem
    • Plugin Architecture
    • Scalability and Performance
    • Serverless
    • Service Collaboration
    • Service Mesh
    • SOA
    • Spring is bloated
    • Stages of API Adoption
    • Transaction Management
    • Microservices Cross-cutting Concerns Options
    • Service Mesh Plus
    • Service Discovery
  • Design
    • Design Overview
    • Design First vs Code First
    • Desgin Pattern
    • Service Evolution
    • Consumer Contract and Consumer Driven Contract
    • Handling Partial Failure
    • Idempotency
    • Server Life Cycle
    • Environment Segregation
    • Database
    • Decomposition Patterns
    • Http2
    • Test Driven
    • Multi-Tenancy
    • Why check token expiration
    • WebServices to Microservices
  • Cross-Cutting Concerns
    • Concerns Overview
  • API Styles
    • Light-4j for absolute performance
    • Style Overview
    • Distributed session on IMDG
    • Hybrid Serverless Modularized Monolithic
    • Kafka - Event Sourcing and CQRS
    • REST - Representational state transfer
    • Web Server with Light
    • Websocket with Light
    • Spring Boot Integration
    • Single Page Application
    • GraphQL - A query language for your API
    • Light IBM MQ
    • Light AWS Lambda
    • Chaos Monkey
  • Infrastructure Services
    • Service Overview
    • Light Proxy
    • Light Mesh
    • Light Router
    • Light Portal
    • Messaging Infrastructure
    • Centralized Logging
    • COVID-19
    • Light OAuth2
    • Metrics and Alerts
    • Config Server
    • Tokenization
    • Light Controller
  • Tool Chain
    • Tool Chain Overview
  • Utility Library
  • Service Consumer
    • Service Consumer
  • Development
    • Development Overview
  • Deployment
    • Deployment Overview
    • Frontend Backend
    • Linux Service
    • Windows Service
    • Install Eventuate on Windows
    • Secure API
    • Client vs light-router
    • Memory Limit
    • Deploy to Kubernetes
  • Benchmark
    • Benchmark Overview
  • Tutorial
    • Tutorial Overview
  • Troubleshooting
    • Troubleshoot
  • FAQ
    • FAQ Overview
  • Milestones
  • Contribute
    • Contribute to Light
    • Development
    • Documentation
    • Example
    • Tutorial
“Mutation Tutorial with IDL” was last updated: July 5, 2021: fixes #275 checked and corrected grammar/spelling for majority of pages (#276) (b3bbb7b)
Improve this page
  • News
  • Docs
  • Community
  • Reddit
  • GitHub
  • About Light
  • Getting Started
  • Architecture
  • Design
  • Cross-Cutting Concerns
  • API Styles
  • Infrastructure Services
  • Tool Chain
  • Utility Library
  • Service Consumer
  • Development
  • Deployment
  • Benchmark
  • Tutorial
  • Troubleshooting
  • FAQ
  • Milestones
  • Contribute