Introduction to GraphQL

Introduction to GraphQL

 

Preamble

From the original definition on https://graphql.org/learn/ :

“GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. GraphQL isn't tied to any specific database or storage engine and is instead backed by your existing code and data.”

Actually many people find that definition a bit confusing, because when they think of a query, they immediately think of something that looks like an SQL query. GraphQL, despite its name, is not built for passing conditions and operators in the same way that you would use them in an SQL query. Instead, think of a graph of objects, and think of the different ways you can navigate through the graph. This is in essence what the basis of GraphQL is.

GraphQL may also be thought as an alternative to REST API to build queries through HTTP. Instead of concentrating on URL-mapping of resources like REST does, it focuses on the structure of the data that is flowing through the API. Whereas REST is mostly considered as an architecture style, GraphQL is actually described by a formal specification. This guarantees that any GraphQL APIs will be in general much more compatible with GraphQL clients than what happens in the REST world, where each service interprets the implementation of REST differently, making it very difficult to reuse client logic.

A few examples

Consider the following object graph

GraphQL-and-Jahia-3.png

As you can see we have four different objects, with attributes such as title, first name, height or url. Objects also have relationships to other objects, such as the Book object that has an “authors” relationship to multiple Person objects, or the reverse relation that indicates that a Person has authored one or more books.

GraphQL provides a simple way of accessing these objects with their attributes (called fields in GraphQL) as well as their relationships (also called fields!). So let’s look at how to request some of these object fields in a first GraphQL query:

{

 books {

   title

 }

}

You might notice the absence of any URL for the request. This is because GraphQL actually doesn’t really enforce any specific URL (although you can find some guidelines). It is a specification that specifies what passes through the HTTP request and response bodies, but the actual URL host, path, parameters and queries are not that important.

If you execute this query, the result will be a JSON object that looks like this:

[

 { “title” : “First book” },

 { “title” : “Second book” },

 ...

 { “title” : “Nth book” },

]

As you can see in a single GraphQL query we can retrieve a collection of objects, while only requesting certain attributes. We are not retrieve for example the “abstract” attribute that we do not need in this example. Please also note that the GraphQL query format, although it borrows some syntax elements from JSON, it is actually not expressed in JSON. The response however is always returned as a JSON object or array.

Now let’s retrieve all the books including the authors of the books. In order to do this let’s modify the query to look like this instead:

{ 
  books {
    title
    authors {
       lastName
    }
  }
}

This query will retrieve all the book’s titles alongside with all the authors last names. Let’s look at the result of the execution of this query:

[ 
  { 
    “title” : “First book”, 
    “authors” : [
      { “lastName” : “Huber” },
      { “lastName” : “Gauthier” },
    ] 
  },
  ...
  { 
    “title” : “Nth book”,
    “authors” : [
      { “lastName” : “AuthorX” },
      { “lastName” : “AuthorY” },
    ] 
  },
]

 

In the same way we could build a more complex GraphQL query that would navigate through all 4 object’s graph:

{ 
  books {
    title
    authors {
       lastName
       headshot {
         file {
           url
         }
       }
    }
  }
}

 

This would produce a result looking something like this:

[ 
  { 
    “title” : “First book”, 
    “authors” : [
      { “lastName” : “Huber”, “headshot” : { “file”: { “url”: “http://localhost/headshots/huber.jpg” } } },
      { “lastName” : “Gauthier”, “headshot” : { “file” : { “url” : “http://localhost/headshots/gauthier.jpg” } } },
    ] 
  },
  ...
]

 

As we have just illustrated, GraphQL makes it easy to retrieve data from object graphs, in powerful ways. Now what is important to remember is that the objects might exist or they might be dynamic representations of server-side services. For example the Image object in our example could actually just be an image service that has an API that can be mapped with the fields we have defined here. This type of mapping is what makes GraphQL so powerful.

Schemas

GraphQL defines access to the objects using a schema, with object types being clearly defined. For example for the Book object, the type could look like this:

type Book {
  id : identifier,
  title : string,
  abstract : string,
  authors : [Author]
}

As you can see the relationship between a Book and an Author is defined as an array of authors. GraphQL schemas are defined using simple basic types, although it is possible to extend the basic (aka scalar) types, but in most scenarios the scalar types should be enough.

The schema makes it easy to “learn” and publish GraphQL APIs. It also greatly helps tools make it easy for developers to integrate and test GraphQL APIs. One great example of this is the GraphiQL tool, that uses the schema to help developers navigate the schema using a builtin API documentation view, as well as help them write queries by using auto-completion.


GraphQL-and-Jahia-4.png

It is also possible to directly attach documentation to the GraphQL schema, making it easy to add comments to a GraphQL type or field.

Field arguments

As you may have noticed in the examples we have presented until now, we were always retrieving all the objects that were returned by the queries. However in some cases you would probably like to retrieve a smaller set or even a single object.

Field arguments may be used to pass arguments to be used when building the result for a field. For example in the following query :

{ 
  books(id : “12345”) {
    title
  }
}

 

We use an argument called “id” to limit the result to a single book that has the corresponding identifier. Of course the interpretation and usage of arguments is entirely left to the GraphQL API implementation.

Let’s look at another fun example of a possible GraphQL query:

{
  myDatabaseType(where : “firstName = ‘Serge’ AND lastName = ‘Huber’) {
    id
  }
}

This example shows how we could build GraphQL APIs on top of an SQL database, and then pass as an arguments parts of the SQL WHERE clause. In this case we would just be interested in retrieving the ID column of the table. If you think this idea is far-fetched, it has already been implemented by the Prisma.io project.

As an intermediate layer

GraphQL is also a great way to regroup multiple services under a common frontend API, as illustrated in the example below:


GraphQL-and-Jahia-2.png

In this example we can see that using REST APIs we would need to use three HTTP calls to retrieve all the data that is needed. Using GraphQL (actually you could even put it in front of those REST APIs), you can retrieve all the data in a single HTTP call. Of course the magic happens on the server side, where the GraphQL server will perform the aggregation and the different calls to the services or the data. The additional benefit of this GraphQL layer is that the implementation may be changed while the API to the external world stays the same. GraphQL may be a front-end to other GraphQL services too, as illustrated below:

GraphQL-and-jahia-1.png

Jahia DX GraphQL API

As we have seen in this introduction, GraphQL provides a great way to access structured objects, and makes it easy to request only the data that is needed in a very efficient way. Because of these strengths, Jahia has decided to provide a GraphQL API for accessing DX content.

We present below an example architecture diagram for a Javascript client application that could be built on top of Jahia’s DX GraphQL API. In this example we choose to illustrate the use of the Apollo Client GraphQL library, that is a very powerful and fast GraphQL client library. It even includes features such as client-side object caching, making sure that objects will not be requested multiple times.

GraphQL-and-Jahia.png

As you can also see in the above diagram, the GraphQL API sits on top of the DX server, exposing it’s functionality through GraphQL, but also through other APIs such as its REST API, or even custom-built Jahia DX actions.

If you want to learn more about DX’s GraphQL API, you may visit the corresponding section in the Jahia Academy site.

 

Author : Serge Huber

Serge Huber is the Chief Technology Officer (CTO) at Jahia, and Co-Founder of Jahia Solutions Group SA as well as the Jahia project before the creation of the group. With more than 15 years’ experience in developing web content management (WCM) and content management system (CMS) solutions in various technologies, his history includes building high-visibility, mission-critical applications for organizations such as the French government, the Swiss Federal Institute of Technology of Lausanne and Garmin. He now oversees the future development and evolution of Jahia’s software and manages the interaction with open source communities such as the Apache Foundation, where he is a committer for the Apache Jackrabbit Project. In his spare time, he enjoys experimenting with innovative technology - the kind that is mind-blowing and future-changing.