GRAPH QL BASICS

GRAPHQL
----------------




Official website: - https://graphql.org/


Important Links:-
---------------------

1) http://adhithiravichandran.com/

2) https://altair.sirmuel.design/


Official Defination:-
---------------------------

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API and gives clients the power to ask for exactly what they need and nothing more.


1) GraphQL is a Query Language for API, not a tool or a framework for designing APIs.

2) Provides clients the power to ask for exactly what they need and nothing more.

3) GraphQL APIs get all the data your app needs in a single request.

4) Language agnostic - Plenty of client and server libraries are available.


GraphQL is a collection of three things:-

i) Schema Defination Language or SDL

ii) Runtime environment

iii) Query language


i) Schema Defination Language(SDL):-
   ----------------------------------------------

1) Schema defination language is used to define a GraphQL schema.

2) A GraphQL schema is used to expose the functionalities that are available in an application to its users. For ex: adding a new book to a virtual library or getting a list of all books from that library.

3) A GraphQL schema contains:-

     a) Types which are similar to classes in Java.

     b) Operations that can be performed on these Types. Similar to methods in Java.

e.g.- 

         type Query {

getBook(id: Int) :Book

getBooks: [Book]

         }

        

         type Mutation {

createBook(name: String, pages: Int): Int

         }


        type Book {

id: Int

name: String :- Object type

pages: Int

        }


ii) Runtime Environment:-
   -----------------------------

   Runtime environment performs two major operations:-

   a) Parsing the GraphQL schema file and creating an 'In memory schema' from it.

   b) Executing the operation specified in the client's request.


   Parsing the GraphQL schema file:
   --------------------------------------------

   Reading information from the schema file again & again will be inefficient so the runtime environment creates an In-memory representation of the schema file that contains all the information defined in that schema file.


   Executing the operation:
   -----------------------------

   A user can use any of the operations that were defined in the schema file. Runtime is responsible for handling the user's request it looks for the operation specified in the request then it uses the in-memory schema

   to check if that operation exists in the schema or not. If it exists then the runtime will execute it and will perform the specified action like reading or manipulating the data at the server.


iii) Query Language(QL):
     ---------------------------

     a) Query language is used by clients to use operations that are defined in the GraphQL schema.

     b) QL enables a client to select only the required fields from a set of fields.


{

getBooks {

       name  ---------------------------> GraphQL-------------------------------> {

     "data": {

}             "getBooks": [

}       "name": "My latest book"

},

{

      "name": "My oldest book"

}

           ]

    }

              }

GraphQL Query Runtime environment Result



Data Fetcher:
-------------------

1) A data fetcher is a call-back function.

2) It is linked to every query, mutation, and field.

3) When a client uses an operation defined in the schema file then the runtime environment invokes the data fetcher linked to that operation in order to perform the specified action.

e.g.- 

//getBook(id: Int): Book

public DataFetcher<Book> getBook() {

       return environment-> bookRepository.findById(environment.getArgument("id")).map(Function.identity()).orElse(null);

}

// getBooks: [Book]

public DataFetcher<List><Book>> getBooks() {

      return environment -> bookRepository.findAll();

}

// createBook(name: String, pages:Int): Int

public DataFetcher<Integer> createBook() {

      return environment -> bookRepository.save(new Book(environment.getArgument("name"), environment.getArgument("pages"))).getId();

}


Advantages:-
------------------

1) Increase multi-team productivity

2) Rapid product development

3) Improved performance of web and mobile apps

4) Reduced cost in Testing and Deployment

5) Apps using GraphQL are fast and stable as they control the data they get.


Histroy:-

1) In 2012, Facebook started the GraphQL project to overcome data fetching issues in their native mobile platform.

2) Moved the focus of development to the client apps.

3) GraphQL was open-sourced in 2015. Ever since then, there have been huge community involvement.

4) GraphQL came into existence due to the need for better flexibility and efficiency in client-server communication.


GraphQL users:-
---------------------

1) Facebook

2) Paypal

3) Twitter

4) Yelp

5) Shopify

6) GitHub, etc.


Single Request

    {Query}

Client ------------------------------------------------------------------> GraphQL 

         JSON

         <------------------------------------------------------------------  Service



=> GraphQL gives us the ability to ask for specific data. This gives the client systems a greater amount of control over what information to request and receive.


REST vs. GraphQL
-----------------------------

REST GraphQL
--------- -------------

1) Multiple round trips to collect the information from multiple resources. 1) One single request to collect the information by aggregation of data.

2) Over Fetching and Under Fetching data resources 2) You only get what you ask for. Tailor-made queries to your exact needs.

3) Frontend teams rely heavily on backend teams to deliver the APIs. 3) Frontend and backend teams can work independently.

4) Caching is built into HTTP spec. 4) Doesn't use HTTP spec for caching (Libraries like Apollo, Relay come with caching options)


Is GraphQL Right for My Business?
------------------------------------------

1) Increases multi-team productivity

2) Rapid product development

3) Improved performance Web and Mobile App.

4) Reduced cost in Testing and Deployment

5) Integration with existing APIs


Legacy

{Query} System

         --------------------- GraphQL ------------------------->

Client {JSON}       Server Microservice

         <----------------------   <---------------------------

   API

<--------

       ---------->


Types:-
-----------

Different types supported by GraphQL schema:-
--------------------------------------------------------

This Schema acts as a contract between the client and the server.


1) GraphQL Scalar Types:-  These are the primitive types in GraphQL.

    i) Int A signed 32-bit integer

   ii) Float A signed double-precision floating-point value

  iii) String A UTF-8 character sequence

  iv) Boolean true or false values

   v) ID Unique identifier. Used to re-fetch an object or as the key for a cache.


e.g.- type Author {

            id: ID

            firstName: String

            lastName: String

            rating: Float

            numOfCourses: Int

       }


2) Enumeration Types:-  Enums are special scalar types that are restricted to a particular set of allowed values. It allows us to validate any arguments of this type are one of the allowed values.

    -------------------------

   e.g.- enum language {

ENGLISH

FRENCH

SPANISH

           }


3) Query and Mutation Types:- Every GraphQL service has a query type. It may or may not have a mutation type. They act as an entry point into the schema. Query and Mutation types are the same as any other

   ---------------------------------  GraphQL object type.

   e.g.- schema {

query: Query

mutation: Mutation

          }

          

           type Query {

author_details: [Author]

           }

           type Mutation {

addAuthor(firstName: String, lastName: String): Author

           }


3) Non-Nullable Type:- 
    -----------------------

   1) By default each of the core scalar types can be set to null.

   2) T override this default behaviour and ensure that a field cannot be null, this ! is used.

   3) You can also have a list of Non-Null items. (List of non-null courses)


   e.g.- type Author {

id: ID!

firstName: String

lastName: String

rating: Float

numOfCourses: Int

courses: [String]

          }

Here the Author object will always have an id. Since it is declared as non-nullable field.


GraphiQL:- 
-------------

GraphiQL is an in-browser IDE for writing, validating, and testing GraphQL queries.


GitHub's GraphQL Explorer:- 
----------------------------------

GitHub's GraphQL Explorer makes use of your real, live, production data on GitHub.

https://developer.github.com/v4/explorer/


Fields:- 
---------

A GraphQL query is all about asking for specific fields on objects

e.g.- 

{

  viewer {

    login

    bio

    id

    name

  }

}


Arguments:-
----------------

In GraphQL you can pass arguments to fields. Every field and nested object can get its own set of arguments. This gets rid of multiple API fetches.

e.g.-

{

  viewer {

    login

    bio

    id

    name

    followers (last: 3) {

      nodes {

        id

        bio

      }

    }

  }

}


Alias:
-------

You can't query for the same field with different arguments. Hence you need aliases. They let you rename the result of a field with anything you want.

e.g. - 

{

  viewer {

    login

    bio

    id

    name

    FirstFollowers:followers (first: 3) {

      nodes {

        id

        bio

      }

    }

    LastFollowers: followers (last: 3) {

      nodes {

        id

        bio

      }

    }

  }

}


Fragments:-
--------------

Fragments are GraphQL's reusable units. They let you build sets of fields and then include them in multiple queries.

e.g. - 

{

  viewer {

    login

    bio

    id

    name

    FirstFollowers:followers (first: 3) {

      nodes {

        ...userInfo

      }

    }

    LastFollowers: followers (last: 3) {

      nodes {

        ...userInfo

      }

    }

  }

}


fragment userInfo on User {

  id

  bio

  bioHTML

  avatarUrl

}


OperationName:-
----------------------

A meaningful and explicit name for your operation. Think of it like a function name in a programming language.


Variables:-
--------------

Arguments to Fields can be dynamic. GraphQL uses variables to factor dynamic values out of the query, and pass them as a separate dictionary.

query viewerInfo 

{

i)  viewer {

    id

    name

    starredRepositories(ownedByViewer: true, last: 5) {

      nodes {

        id

        name

      }

    }

  }

}


ii) query viewerInfo($isOwner: Boolean) {

  viewer {

    id

    name

    starredRepositories(ownedByViewer: $isOwner, last: 5) {

      nodes {

        id

        name

      }

    }

  }

}


Mutations:-
-------------

1) Mutations are used to make changes to the data(Create, update, delete data).

2) GraphQL assumes side-effects after mutations and changes the dataset after a mutation.

3) While query fields are executed in parallel, mutation fields run in series, one after the other.


e.g. - 

i) query viewerInfo {

  viewer {

    login

    name

    status {

      id

      message

    }

  }

}


mutation NewStatus($input: ChangeUserStatusInput) {

  changeUserStatus(input:$$input) {

    clientMutationId

  }

}


query viewerInfo {

  viewer {

    login

    name

    status {

      id

      message

    }

  }

}

Query Variables - 

{

  "input": {

    "clientMutationId": "10101103",

    "Demo for GraphQL"

  }

}


Benefits of Declarative Data Fetching:
-----------------------------------------------

1) Avoids round trips to fetch data

2) No more over-fetching or under-fetching of data

3) Strongly-Typed Schema:- GraphQL is strongly typed.

    i) GraphQL is a strongly typed language, and its schema should have types for all objects that it uses.

   ii) The schema serves as a contrast between client and server.

   iii) Relies on a query language with a type system.


Benefits of Strongly-Typed GraphQL Schema:-
----------------------------------------------------------

1) Code is predictable.

2) Frontend and backend teams work independently

3) Earlier detection of errors and speeds development

4) Facilitates building high quality client tools


Superior Developer Experience:-
-----------------------------------------

1) Flexibility - GraphQL offers a lot of flexibility.

2) No versioning

3) Non-breaking changes

4) With GraphQL teams can work independently in parallel.

5) Frontend can continue work with mocked version of API and also test it.


Evolve your API without Versioning:
----------------------------------------------

1) Add new fields and types to GraphQL API without breaking changes.

2) Provides apps continuous access to new features

3) Developers don't have to maintain multiple versions of the API.


Modern Ecosystem and Tooling:
----------------------------------------

1) Tools like GraphiQL IDE provide excellent developer experience.

2) Hours of documentation time saved with in-built self-documentation in the schema.

3) Plenty of GraphQL clients for every UI framework (Apollo, Relay)

4) Lots of server-side libraries and client libraries and services across several languages


Cost Effective:
--------------------

1) Rapid product development cycle

2) Multiple teams work in parallel

3) Self-documentation of API - Tons of hours saved from writing elaborate API documentation

4) Save money with minimal training

5) Easy to onboard developers on GraphQL


GraphQL Ecosystem and Tooling:
---------------------------------------

GraphQL is a specification that is language-agnostic.


GraphQL Architecture:
-----------------------------

GraphQL Client:
-------------------

What Can a GraphQL Client Do?
--------------------------------------

1) Handles sending requests(queries) to the server and receiving the response(JSON) from the server.

2) Integrates with your view components and updates the UI.

3) Caching Query Results

4) Error Handling and schema validation

5) Local State Management and Caching

6) Pagination


Popular GraphQL Clients:
----------------------------------

1) Apollo client - https://www.apollographql.com/docs/react/

2) Relay - https://relay.dev - developed by Facebook


GraphQL Server:
---------------------

In simple terms, a GraphQL server receives the query from the client and responds back.

The GraphQL server layer is where backend developer will create and design the schema and the API.


1) Resolvers:
   ----------------

Resolver function is a function that resolves a value for a type/field in the GraphQL Schema. It can return objects or scalars like strings, numbers, booleans, etc.

They can also resolve values from another REST API, database cache or any other source.


2) Network Layer:- The queries from the client need to be transported to the server through the network over HTTPS.

    -------------------


3) GraphQL Execution Engine:- 
    ---------------------------------

i) Parses query from the client

ii) Validate schema

iii) Returns JSON response

iv) Executes resolvers for each field


4) Batch Resolving:- By making Batch requests we ensure that we only do one fetch to the backend. This way we don't actually make multiple requests for the same item over and over again.

    ----------------------


Popular GraphQL Server Libraries:
-----------------------------------------

1) Apollo Server

2) Express GraphQL

3) GraphQL Yoga


Database to GraphQL Server:
---------------------------------

i) Prisma is a popular GraphQL database Server.

ii) Prisma sits between the GraphQL Server and the database.


Client-------------------------------> Server-------------------------------->Prism---------------------------------->Database



Prisma:-
----------

1) Replaces traditional ORMs and simplifies database workflows

2) Data access layer that makes it easy for the API server to talk to DB through Prisma.

3) Type-safe database access

4) GraphQL subscriptions

5) Powerful visual data management available with Prisma admin


GraphQL Tools:
--------------------

1) GraphiQL:
     ------------

    An in-browser IDE for writing, validating, and testing GraphQL queries.

   -> Write queries to retrieve data

   -> Perform mutations

   -> Live syntax and validation errors highlighted


2) GraphQL Voyager:- https://apis.guru/graphql-voyager/
     ----------------------

   i) Represents any GraphQL API as an interactive graph.

  ii) Perfect to explore complex GraphQL APIs

 iii) Great tool during design of data model.


3) GraphQL Faker:- https://github.com/APIs-guru/graphql-fake

    i) Mock your API with realistic data from faker.js

   ii) No additional coding required

  iii) Useful for testing and coding against future APIs


4) GraphQL Visual Editor:-
     ----------------------------

    i) Create schemas by joining visual blocks

   ii) GraphQL editor transforms them into code

  iii) Don't need to write any code

   iv) Perfect to understand any GraphQL Schema


Preparing In memory Schema:
-------------------------------------

GraphQL schema file--------

         |

         |-------------> Runtime environment -------------------------> In memory schema

fx          |

Data fetchers-----------------




Building a GraphQL API with Apollo Server
---------------------------------------------------

Important Links:-
-----------------------

1) https://studio.apollographql.com/


APOLLO:
--------------

Apollo is a node.js implementation of GraphQL that does a lot of heavy lifting for us so we can just get to the business needs.


Building the Environment:
-------------------------------

1) npm init

2) npm install apollo-server

3) npm install nodemon

4) npm install apollo-datasource

5) npm install lodash

6) npm install apollo-datasource-rest


Schema:-
-----------

A schema allows the client to understand what properties are available on your api and enables them to select the fields they want.


Apollo Playground:-
-------------------------

Apollo comes with a graphical, interactive, in-browser GraphQL IDE.


Introspection:-
------------------

The ability to query which resources are available in the current API schema. Given the API, via introspection, we can see the queries , types, fields, and directives it supports.


Resolver:
-----------

A function that is responsible for populating the data for a single field in your schema. A resolver has a query type and Session fields.


Resolver Map:
-----------------

A big object that holds all of those Type ---> Field ----> Resolver functions.



Field Level Directives:
----------------------------

1) @include(if: Boolean!) - Calls for the resolver for the annotated field if the boolean is true.

2) @skip(if: Boolean!) - The opposite of include. This will skip the field if the boolean is true.

3) @deprecated(reason: String) - Mark the field as deprecated with a reason for its future removal.


How GraphQL works in Java?
--------------------------------------

Client-----------------------> Controller------------->GraphQL------------->Data Fetcher------------------->DB/API

        <-----------------------                <-------------        <--------------              <-------------------


1) In Controller there is always a method that uses GraphQL object to manage the request body. This method is usually mapped to the URI path "/graphql" for example "http://localhost:8080/graphql".


2) whenever a client sends a request to this URI path then Controller passes the request body to GraphQL object. The GraphQL object performs the following steps:-

* Fetch the query

* Fetch the variables(if provided)

* Fetch the operation name(if provided)

* Execute the Data Fetcher associated with the query and return the result




0 Comments