How to create a GraphQL API using Spring Boot – A Beginner's Guide
Tags: graphql, springboot, beginners, java
Published: 2023-10-11 22:20:38

## What is GraphQL?


According to its [official documentation](https://graphql.org/learn/), “GraphQL is a query language for your API and a server-side runtime for executing queries using a type system you define for your data.” It was developed and open-sourced by Meta and is now maintained by a large community of companies and individuals.

GraphQL consists of 2 main parts: -

1. **Schema Definition Language** - GraphQL schemas for a service specified using GraphQL SDL (schema definition language), also sometimes referred to as just GraphQL schema language.
2. **Query Language** - A query language consists of 3 parts, Query, Mutations and Subscription

We’ll discuss these points in detail later in this article.

GraphQL has a lot of good features, like:

1. It enables **declarative data fetching** and provides a **single endpoint** where a client can specify exactly what’s needed, no more over-fetching of information.
2. It provides **validation and type checking** out of the box, you can validate a query within the GraphQL strongly typed system before execution. 
3. It keeps **API documentation in sync** with API changes. This benefits developers, since they must spend less time documenting an API.
4. GraphQL removes the need for **versioning** by deprecating APIs on a field level. Old fields can be later removed from the schema without impacting the existing queries.

There are some disadvantages also: -

1. GraphQL requires **heavier tooling support**, both on the client and server sides. This requires a sizable upfront investment. It is not a suitable alternative for very simple use cases of API.
2. GrpahQL has a single point of entry and uses HTTP POST by default. This prevents the full use of client-side **HTTP caching** and makes it a non-trivial task to implement caching.

## GraphQL Schema

Schema is mandatory in GraphQL service. The GraphQL Schema defines how data is requested and returned from the server and is controlled by GraphQL SDL. Let’s try to understand some of the most important concepts with one sample schema: -

```
# root Query Type
type Query {
    fetchBooks: [Book]
}

# Book type
type Book {
    id : ID
    name : String
    author: String
    ratings: [Rating]
}

# Rating type
type Rating {
    id: ID
    rating: Int
    comment: String
    user: String
}
```
**Object Types** – Object types are specific to GraphQL service, and are defined with the type keyword. They define the type name and the fields under that type. Each field in an object type can be resolved to either scaler types or other object types, e.g., type Book has scaler fields of type String and another object field of type Rating.

**Built-In Scaler Types** - There are 5 built-in scalar types in GraphQL: Int, Float, String, Boolean, and ID. The ID type resolves to a string but expects a unique value.

**Type Modifiers** - Modifiers can be used on the type that a field resolves to by using characters like […], e.g. root Query has type modifier [Book], it represents a nullable list of non-nullable string values. The entire value can be null, or specific list elements can be null.

**Operations** - A GraphQL service can support the following operations: -

1. **Queries**: Queries represent READ operations.
2. **Mutation**: Mutation comprises WRITE then READ operation.
3. **Subscription**: A subscription is used for continuous READ (e.g. over WebSocket).

## Getting started

In this article, you’re going to build a book catalog service using Spring Boot GraphQL. This service will support a single query “fetchBooks” to return the top 5 books, authors, and ratings of all times.

We are using [Spring for GraphQL](https://spring.io/projects/spring-graphql) to build this service. It is built on [GraphQL Java](https://www.graphql-java.com/) and supports GraphQL request handling over HTTP and WebSocket. GraphQL specification is not tied to any transport layer protocol. I am using [GraphQL over HTTP](https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md) specification to build this API. 

Before diving into code, let’s spend some time understanding Spring GraphQL. It has 3 main components, transport, GraphQL Java engine and data fetchers.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w1vetx1j41vy21pjj0vk.png)

**Transport** - GraphQL Java doesn’t provide any transport by default. You can use any transport mechanism provided by the Spring framework e.g. Spring MVC, Spring WebFlux, and WebSocket etc. These handlers tunnel all requests GraphQL Java Engine.

**GraphQL Java Engine** – It has support to bootstrap service from scratch and context propagation from the web layer to the data layer. Exceptions are also handled at this layer.

**Data Fetchers** – It provides annotated controllers (@Controller), query Domain Specific Language (DSL) and repositories


## Service Implementation steps

**Step 1: Create a Spring Boot project with dependencies.**

You can use [spring initializer](https://start.spring.io/) to create an empty spring boot project with the below dependencies: -


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ahk7yr2eomu7joxcn3c9.png)

- spring-boot-starter-graphql – main dependency
- spring-boot-starter-web – add this dependency for building the transport layer


**Step 2: Create a schema file for our books catalog service.**

```
type Query {
    fetchBooks: [Book]
}

type Book {
    id : ID
    name : String
    author: String
    ratings: [Rating]
}

type Rating {
    id: ID
    rating: Int
    comment: String
    user: String
}
```


**Step 3: Create a data fetcher.**

[Data fetcher](https://www.graphql-java.com/documentation/data-fetching/) is a callback function, and it fetches data to include the result of a query. When an incoming GraphQL query is received, the library will call the registered DataFetcher for query. Every query must have an associated DataFetcher, e.g., we’ll create a data fetcher for the “fetchBooks” query in our schema defined in step 2.

**Step 4: Type Wiring and RunTime wiring**

GraphQL Java uses [RuntimeWiring](https://javadoc.io/static/com.graphql-java/graphql-java/9.5/graphql/schema/idl/RuntimeWiring.Builder.html) builder to register data fetchers, type resolvers, and more. We’ll create RuntimeWiringConfigurer beans in our Spring config to get access to the RuntimeWiring.Builder. Below code snippet shows data fetcher for “fetchBooks” query and it’s linking with RuntimeWiring builder.

```
@Configuration
public class GraphQLServiceConfiguration {

    @Bean
    public RuntimeWiringConfigurer runtimeWiringConfigurer(BooksCatalogService bookCatalogService) {
        return builder -> {
            builder.type(
                    "Query",
                    wiring ->
                            wiring
                                    .dataFetcher("fetchBooks", environment -> bookCatalogService.fetchBooks()));
            builder.type(
                    "Book",
                    wiring ->
                            wiring.dataFetcher("ratings", env -> bookCatalogService.fetchRatings(env.getSource())));
        };
    }
}
```

In the above code, Data Fetcher for field fetchBooks fetches all books and rating by calling books catalog service’s methods fetchBooks() and fetchRatings().

**Step 5: Running and Testing**

You can start the GraphQL service from IDE by running the main method of BooksCatalogServiceApplication class


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sn607p8p0hj7r8gs0xe4.png)

You can use Insomnia client to test your API. 
POST : http://localhost:8080/graphql 

 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kgwfqcgv5jcbrk3obwns.png)

You can also use GraphiQL editor in the browser using the link http://localhost:8080/graphiql?path=/graphql.
 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/223j2o660khoz6oyty16.png)

To enable GraphiQL editor, you must set **spring.graphql.graphiql.enabled=true** in application.properties.

The working code example of this article is listed on [GitHub](https://github.com/aparoha/books-catalog-service). To run the example, clone the repository and import books-catalog-service as a project in your favorite IDE as a Maven project.