Introduction to GraphQL with Spring Boot

This article is an introduction to GraphQL with spring boot. We will discuss basic concepts of GraphQL and setup a spring boot app for schema-driven development.

What is GraphQL ?

GraphQL is a data query language. It was created by Facebook. GraphQL provides a new API standard similar to REST.

In REST API, the fundamental concept is a resource. Resources are managed by the server. Problem arises when the client requests data from multiple resources at the same time. To solve this, either the client makes multiple requests or the server responds with extra data, that are not needed.

GraphQL solves this problem by providing declarative data fetching, thereby enabling the client to fetch only the data it requires and avoids over-fetching or under-fetching of data.

What are the benefits of using GraphQL over e.g., REST ?

Let’s consider an example to understand the concept better. Consider the earlier example where we created a web-service that provides a REST API to manage a collection of films. The client can retrieve the list of films in the collection along with their year of release and other details. The details behind the implementation of this API as well as a demo are here.

A client using the REST API to get data about the films could either use the /films end-point to get the entire database of films or the /films/<id> to get individual film info. Suppose the client is trying to build a UI that lists, say, only the IDs and names, it still will end-up getting all the fields for all the films. Thus it ends up overfetching data from the server.

An alternate approach could be to design the REST API to return only the IDs from the /films endpoint or to create a new end-point, say, /filmids to return just the IDs. Still, if the client wanted to get all the IDs and names it would have to first visit this end-point, get all the IDs and then visit each end-point to get the names. In this case, the first API call results in underfetching which is why the client makes N additional calls to get the remaining pieces of data. This is the so-called “N+1” problem that is commonly encountered while using REST APIs.

Of course, we can design multiple endpoints providing multiple views of the data. But, we are transferring the concerns of the client into the API implementation, which is not good design. Also, the number of such views could multiply over time and make the service unmaintainable.

GraphQL simplifies this process by getting all the data your app needs in a single request. In GraphQL, the consumers can choose the data that is needed, by having all data in a single endpoint. Thus, the GraphQL server exposes a single endpoint and enables the client to request precisely the data it requires. Requests normally use POST method and use a JSON syntax to describe the data queried for.

GraphQL with Spring Boot

In this article we will discuss the basics of graphql and understand queries and mutations. We will illustrate GraphQL by creating a schema for a GraphQL endpoint. We will be developing the schema for jerseyfilm REST example using GraphQL.

Any other web app can be used as a starting point for this tutorial. You can create your own web-app by visit https://start.spring.io or by opening STS and choosing File → New → Spring Starter project and walking through the steps in the wizard. Ensure in either case to use Maven as the build system since the rest of the article assumes your application is structured as a Maven project.

Adding GraphQL capabilities to your SpringBoot Application

To add GraphQL capabilities to a spring boot app, we need the following dependencies:

  • graphql-spring-boot-starter dependency (includes graphql-java)

  • The Spring Boot GraphQL Starter(graphql-spring-boot-starter) allows us to setup a GraphQL server running in a very short time. graphql-java is the GraphQL server implementation itself.

  • Graphql-java-tools: This dependency makes dynamic resolver wiring easy. Hence, we need to include graphql-java-tools dependency.

Schema-first approach vs Code-first approach

The GraphQL Tools library processes the GraphQL Schema files to build the correct structure and then wires special beans to this structure. The Spring Boot GraphQL starter automatically finds these schema files and develops a graphQL API using the schema-driven approach, i.e., the library automatically parses the GraphQL API schemas in the project, locates and loads any implementation classes for the schema and exposes them over the graphql server. The schema files need to be saved with the extension “.graphqls” and it can be present anywhere on the classpath.

By using schema driven approach, GraphQL can speed up your application by making strong contract between the frontend and backend upfront.

An alternate approach to developing a GraphQL API is called Code-first approach, in which Java classes implementing the API are developed and schema is dynamically generated.

In this article, we will be following the schema-driven approach to creating a graphQL API.

First, add these dependencies to your pom.xml

Adding these dependencies will expose the GraphQL Service to be available on the /graphql endpoint of our app, by default.. This endpoint can be customized based on the application’s needs.

GraphQL has a handy tool called GraphiQL. GaphiQL provides a user Interface which communicates with any GraphQL Server and can parse and execute queries.

Add the GraphiQL Spring Boot Starter dependency in the pom.xml to enable GraphiQL in our app:

GraphQL API needs to be hosted on the default endpoint of /graphql, for this to work.

Schema Definition Language(SDL)

There are basic GraphQL constructs which can be used to define the GraphQL schema of an API. This syntax for defining the schema is called Schema Definition Language.

Let’s take the FilmService example used in REST API.

Below is an example of using SDL to define a simple type called Film.

The type Film has four fields, namely id, name, year, genre and are respectively of type Int, String, Int and Enum. In SDL, a ‘!’ following the type indicates the type is required.

Queries:

While using REST API’s, each endpoint has a clear structure along with the information it returns. The requirements of the client are encoded in the URL from which data is loaded.

Conversely, in GraphQL, GraphQl API exposes a single endpoint rather than having multiple endpoints returning fixed data structures. This approach provides flexibility to the client to exactly fetch the data it needs. This process of requesting the data needs of the client to the server is called a Query. Let’s take an example query from a client to a server:

The allFilms field is called as root field of the query. The query will return list of all the films stored in the database. Example response of the query would be:

The server returns only the name of the film in the response, other fields like id, year, genre are not displayed. This is because the query has only the name field specified.

Each field can have 0 or more arguments. This can be configured in the schema. For example, allFilms field can have a parameter ‘first’ to return first n films. A sample query for this would be:

Mutations

We discussed the method to request data from a server using Queries. Next, we may require to change the information stored in the backend. For this, ‘mutations’ are provided by the GraphQL Schema to create new data, update existing data or delete existing data.

Syntax of mutations is similar to queries, but it always needs to start with the keyword ‘mutation’. In GraphQL, operations can be of 2 types namely Query or Mutation. This is similar to resources in a RESTful API.

Below is the schema for defining the mutation:

Below is an example API call for creating a new Film:

Note how the call selects the fields to be returned in the Film object. The server response for above mutation could be:

There can be relationships between different types and it can also be expressed using the SDL. In a movie app, a Director object or a Review object could be associated with a Film:

Similarly, the relationship at the other end should be placed on the Film type.

Subscriptions

An application may require a realtime connection with the server, which enables it to get immediate information about important events, instantly. To provide this use case, GraphQL offers “subscriptions”. An example to subscribe on events happening of Films type is as follows:

By sending a subscription to a sever, a connection is setup between the client an the server. Whenever a new mutation is done that creates a new Film, the server sends the data about the new film to the client:

The one requirement in SDL is that there must be only one root query, and one root mutation. It cannot be split across files.

Schema:

A schema is a collection of GraphQL types. The schema specifies the client requirements of the API and establishes a contract between the client and server by defining how client can request the data.

You can write the schema by using queries, mutation and subscriptions.

A sample schema created by using the concepts we just discussed in the article”

Summary

In this article, we reviewed the basic concepts of GraphQL and its advantages over REST. We also understood the fundamental constructs of defining GraphQL Schema and built a basic GraphQL Schema.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.