Techdozo
  • Microservices
    • All
    • GraphQL
    • gRPC
    • Spring Boot
    GraphQL Error Handling

    GraphQL Error Handling

    Pages

    Spring for GraphQL: Pagination with Code Example

    Spring for GraphQL: Interfaces and Unions

    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    Distributed transaction in microservices using Saga

    Distributed Transactions in Microservices: implementing Saga with Temporal

  • Spring Boot
    Pages

    Spring for GraphQL: Pagination with Code Example

    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful API Gateway with gRPC

    RESTful API Gateway with gRPC

  • gRPC
    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    gRPC Interceptor: unary interceptor with code example

    gRPC Interceptor: unary interceptor with code example

    gRPC: synchronous and asynchronous Server streaming RPC

    gRPC: synchronous and asynchronous Server streaming RPC

    Photo by Ramón Salinero on Unsplash

    gRPC: synchronous and asynchronous unary RPC in Java

    Microservices inter-process communication using gRPC

    gRPC for microservices communication

  • GraphQL
    GraphQL Error Handling

    GraphQL Error Handling

    Pages

    Spring for GraphQL: Pagination with Code Example

    Spring for GraphQL: Interfaces and Unions

    GraphQL Directive

    GraphQL Directive

    Spring for GraphQL mutation

    Spring for GraphQL: Mutation

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring GraphQL with @Controller, @SchemaMapping and @QueryMapping

    Spring for GraphQL : @SchemaMapping and @QueryMapping

    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

  • Kubernetes
    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Components of Kubernetes Architecture

    Components of Kubernetes Architecture

    Helm Chart: quick start your app deployment on Kubernetes

    Helm Chart: quick start your app deployment on Kubernetes

    gRPC load balancing on Kubernetes (using Headless Service)

    gRPC load balancing on Kubernetes (using Headless Service)

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

  • Java
    Java Streams: Stream Operation with Examples

    Java Streams: Stream Operation with Examples

    Java Streams: stream creation with examples

    Java Streams: stream creation with examples

    Garbage Collection

    Super Fast Garbage Collectors in Java

    Calculus

    Functional Programming in Java

No Result
View All Result
  • Login
  • Microservices
    • All
    • GraphQL
    • gRPC
    • Spring Boot
    GraphQL Error Handling

    GraphQL Error Handling

    Pages

    Spring for GraphQL: Pagination with Code Example

    Spring for GraphQL: Interfaces and Unions

    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    Distributed transaction in microservices using Saga

    Distributed Transactions in Microservices: implementing Saga with Temporal

  • Spring Boot
    Pages

    Spring for GraphQL: Pagination with Code Example

    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful API Gateway with gRPC

    RESTful API Gateway with gRPC

  • gRPC
    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    gRPC Interceptor: unary interceptor with code example

    gRPC Interceptor: unary interceptor with code example

    gRPC: synchronous and asynchronous Server streaming RPC

    gRPC: synchronous and asynchronous Server streaming RPC

    Photo by Ramón Salinero on Unsplash

    gRPC: synchronous and asynchronous unary RPC in Java

    Microservices inter-process communication using gRPC

    gRPC for microservices communication

  • GraphQL
    GraphQL Error Handling

    GraphQL Error Handling

    Pages

    Spring for GraphQL: Pagination with Code Example

    Spring for GraphQL: Interfaces and Unions

    GraphQL Directive

    GraphQL Directive

    Spring for GraphQL mutation

    Spring for GraphQL: Mutation

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring GraphQL with @Controller, @SchemaMapping and @QueryMapping

    Spring for GraphQL : @SchemaMapping and @QueryMapping

    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

  • Kubernetes
    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Components of Kubernetes Architecture

    Components of Kubernetes Architecture

    Helm Chart: quick start your app deployment on Kubernetes

    Helm Chart: quick start your app deployment on Kubernetes

    gRPC load balancing on Kubernetes (using Headless Service)

    gRPC load balancing on Kubernetes (using Headless Service)

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

  • Java
    Java Streams: Stream Operation with Examples

    Java Streams: Stream Operation with Examples

    Java Streams: stream creation with examples

    Java Streams: stream creation with examples

    Garbage Collection

    Super Fast Garbage Collectors in Java

    Calculus

    Functional Programming in Java

No Result
View All Result
Techdozo
No Result
View All Result
Home Microservices GraphQL

Getting started with Spring Boot GraphQL service

Pankaj by Pankaj
July 23, 2022
in GraphQL, Spring Boot
Reading Time: 20 mins read
0
A A
0
Spring Boot GraphQL service

Spring Boot GraphQL service

ADVERTISEMENT

Facebook developed GraphQL in 2012 to solve its problem of mobile communication. Since it was open-sourced in 2015, it has been adopted by companies like Twitter, Shopify, Lyft, Airbnb, Github, Yelp, and many more.

There is no doubt that GraphQL adoption is on the rise. The State of JavaScript 2020 report mentions that only 6% of developers surveyed had used it in 2016, however, 47% of developers used it in 2020.

ADVERTISEMENT

Spring for GraphQL, which recently released version 1.0, provides a higher level abstraction for building the Spring Boot GraphQL service.

If you want a quick overview of GraphQL and how to implement the Spring Boot GraphQL service then you have come to the right place.

Let’s get started!

In this article

  • What is GraphQL?
    • Features of GraphQL
      • Strongly Typed
      • Hierarchal Data
      • Client-specific Response
      • Introspection
  • Why GraphQL?
  • Why Not GraphQL?
  • GraphQL Schema
    • GraphQL Operation
    • Schemas and Types
    • Object Type and Fields
  • GraphiQL Editor
  • Spring Boot GraphQL support
    • Server Transport
  • GraphQL Service Implementation
    • GraphQL Dependency
    • RuntimeWiring
    • TypeRuntimeWiring
    • Data Fetchers
    • RuntimeWiringConfigurer
  • Running and Testing
  • Summary

What is GraphQL?

GraphQL is a query language and server runtime.

  1. Query language: GraphQL is a query language for API. In GraphQL, you design API based on its type system. A GraphQL API is expressed as a statically typed schema.
  2. Server runtime: On the service side, a GraphQL service provides a runtime layer that describes the structure of data exposed by API, and this runtime layer is responsible for parsing GraphQL requests and calling the appropriate data fetcher (also called resolver) for each field.

In short, GraphQL is a query language for API and a server-side runtime for executing queries. Also, it’s not tied to any specific programming language, database, or storage engine.

A GraphQL query to fetch book by an id

ADVERTISEMENT

{
  bookById(id: 4) {
    name
    author
  }
}

Response


{
  "data": {
    "bookById": {
      "name": "Atomic Habits",
      "author": "James Clear"
    }
  }
}

Spring Boot GraphQL Service

Spring Boot GraphQL

Features of GraphQL

Some important features of GraphQL are:

Strongly Typed

GraphQL APIs are strongly typed and expressed as a schema. This strongly typed nature makes GraphQL APIs more predictable and discoverable. Additionally, the type system provides other benefits, such as introspection.

Hierarchal Data

As the “Graph” in GraphQL suggests, GraphQL provides first-class support for hierarchical data. With GraphQL, you can create a request as a graph of related fields. The GraphQL response is shaped like the request, a natural way for a client to describe its data requirement.

Client-specific Response

REST APIs are often criticized for over-fetching. Generally, a REST API returns all data under a resource even though you need only a fraction of the data. This is not a problem in GraphQL as a GraphQL client can choose to request data on the field level granularity.

Introspection

Because of the statically typed nature of GraphQL, any client can ‘introspect’ the server and ask for the schema. One popular GraphQL tool that relies on this concept is GraphiQL, a feature-rich browser-based editor to explore and test GraphQL requests.

You can explore some popular GraphiQL interfaces

  • Star Wars GraphQL API: az.dev/swapi-graphql
  • GitHub GraphQL API: az.dev/github-api

Why GraphQL?

REST is the most popular way of building APIs, but it has many shortcomings. Let’s understand the problem with REST APIs that GraphQL promises to solve.

  • Standard: The GraphQL specification is maintained by the GraphQL community, providing a comprehensive standard for developing maintainable APIs. In contrast, REST APIs lack an industry-wide standard despite being around for many years.
  • API Documentation: With REST API, API documentation is maintained in OpenAPI spec. However, documentation and implementation can drift apart over time, which is a common issue. In GraphQL, there is no need to maintain separate API documentation.
  • Overfetching: Overfetching is a significant issue with REST APIs, particularly for mobile applications. Pure REST APIs are built around resources and lack the concept of partial response. For instance, a mobile e-commerce app displaying order history must show the name, purchase date, and price of a product. However, the /orders API of a REST API may return many other fields, such as payment details, discounts, shipment details, etc., making it inefficient for mobile use.
  • Under fetching: REST APIs are usually fine-grained and built around resources. Thus, a client application may call multiple APIs to construct a view. This is typically not an issue in GraphQL due to its hierarchal nature.

Why Not GraphQL?

However, this doesn’t mean GraphQL is perfect in every sense; it has its own shortcomings. For example:

  • As REST API has been around for many years, it has a very well-defined security measure, but the same is not true for GraphQL.
  • Compared to REST APIs, implementing client-side caching is very hard in GraphQL.
  • Things like rate limiting are harder to implement in GraphQL. This can easily lead to a denial of service attack, as it’s possible to bring down the whole service by requesting deeply nested data.

As with everything in life, choosing between REST and GraphQL involves making trade-offs.

GraphQL Schema

The GraphQL Schema defines how data is requested and returned from the server and is governed by GraphQL Schema Definition Language (SDL). A GraphQL schema may contain operations, variables, and directives.

GraphQL Operation

A GraphQL service can support the following operations

  1. Queries: Queries represent READ operations.
  2. Mutation: Mutation involves WRITE then READ operation.
  3. Subscription: A subscription is used for continuous READ (for example, over WebSocket).

Schemas and Types

Every GraphQL API defines a set of types that describe the data you can query on that API. A GraphQL request is validated and executed against that schema.

Object Type and Fields

The most fundamental components of a GraphQL schema are object types, which represent an object you can fetch from a service and its corresponding fields. In the GraphQL schema language, you can represent an object type for a Book as follows:


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

In the above example,

  • Type: Book is GraphQL object type.
  • Fields: id, name, author, price, and ratings are fields of Book type.
  • Scalar types: String, Float, and Int are some of the built-in scalar types.
  • ID: the ID scalar type represents a unique identifier, often used to refetch an object. Additionally, the ID type is serialized in the same way as a String.

Example of a GraphQL book-catalog API


type Query {
    books: [Book]
    bookById(id : ID) : Book
}

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

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

GraphiQL Editor

One of the reasons GraphQL is very popular is GraphiQL (pronounced “graphical”), an open-source web application (written with React.js and GraphQL) that runs in a browser. The best thing about GraphiQL is that it provides intelligent type-ahead and auto-completion features, which is possible because of GraphQL’s statically typed schema.

Star Wars GraphiQL editor (az.dev/swapi-graphql)

Spring Boot GraphQL support

Spring Boot GraphQL provides support for Spring applications built on GraphQL Java. It supports the handling of GraphQL requests over HTTP, WebSocket, and RSocket.

Spring for GraphQL is the successor of the GraphQL Java Spring project from the GraphQL Java team. It aims to be the foundation for all Spring, GraphQL applications.

Server Transport

GraphQL specification itself doesn’t talk anything about transport layer protocol. GraphQL over HTTP specification extends GraphQL specification to cover the topic of serving GraphQL services over HTTP.

As per GraphQL over HTTP specification, requests must use HTTP POST with request details included as JSON in the request body. Once the JSON body has been successfully decoded, the HTTP response status is always 200 (OK), and any errors from GraphQL request execution appear in the “errors” section of the GraphQL response.

The default and preferred choice of the media type is "application/graphql+json" , but "application/json" is also supported.

GraphQL Service Implementation

In Spring Boot, you can implement the GaphQL service using low-level GraphQL Java API or a higher-level abstraction as Controller annotation (similar to REST API). However, if you are starting out then, I think it’s better to start with the low-level GraphQL Java implementation as it covers some important concepts. In this article, we’ll use GraphQL Java APIs rather than Controller annotation.

The working code example of this article is listed on GitHub  . To run the example, clone the repository and import graphql-spring as a project in your favorite IDE as a Gradle project.

In this code example, we’ll implement the following GraphQL API.


type Query {
    books: [Book]
    bookById(id : ID) : Book
}

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

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

GraphQL Dependency

To implement GraphQL in Spring Boot, the main dependency you need to define is spring-boot-starter-graphql. For the transport layer, I have added dependency on spring-boot-starter-webflux. Additionally, you can use Spring MVC, Instead of WebFlux, as Spring provides support for both.


dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-graphql'
	implementation 'org.springframework.boot:spring-boot-starter-webflux'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'io.projectreactor:reactor-test'
	testImplementation 'org.springframework.graphql:spring-graphql-test'
}

RuntimeWiring

GraphQL Java RuntimeWiring.Builder is used to register DataFetchers, type resolvers, custom scalar types, and more. You can declare RuntimeWiringConfigurer beans in your Spring config to get access to the RuntimeWiring.Builder.

You first create type wiring for Query type by registering Query type with RuntimeWiring.Builder as


return new RuntimeWiringConfigurer() {
  @Override
  public void configure(RuntimeWiring.Builder builder) {

    builder.type(
        "Query",
        new UnaryOperator<TypeRuntimeWiring.Builder>() {
          @Override
          public TypeRuntimeWiring.Builder apply(TypeRuntimeWiring.Builder builder) {
            .....
          }
        });    
  }
};


TypeRuntimeWiring

As the type Query has two fields books and bookById, the next step is to define DataFetcher for fields books and bookById and register data fetchers with TypeRuntimeWiring.Builder as


return new RuntimeWiringConfigurer() {
  @Override
  public void configure(RuntimeWiring.Builder builder) {
    builder.type(
        "Query",
        new UnaryOperator<TypeRuntimeWiring.Builder>() {
          @Override
          public TypeRuntimeWiring.Builder apply(TypeRuntimeWiring.Builder builder) {
            return builder
                .dataFetcher(
                    "books",
                    new DataFetcher<>() {
                      @Override
                      public Collection<Book> get(DataFetchingEnvironment environment)
                          throws Exception {
                        return bookCatalogService.getBooks();
                      }
                    })
                .dataFetcher(
                    "bookById",
                    new DataFetcher<>() {
                      @Override
                      public Book get(DataFetchingEnvironment environment) throws Exception {
                        return bookCatalogService.bookById(
                            Integer.parseInt(environment.getArgument("id")));
                      }
                    });
          }
        });
  }
};

In the above code,

  1. Data Fetcher for field books fetches all books by calling the service method bookCatalogService.getBooks().
  2. Data Fetcher for field bookById fetches a book by calling the service method bookCatalogService.bookById. You can get arguments from the DataFetchingEnvironment as environment.getArgument("id").

Similarly, for type Book and the field ratings , you can define DataFetcher as:


builder.type(
    "Book",
    new UnaryOperator<TypeRuntimeWiring.Builder>() {
      @Override
      public TypeRuntimeWiring.Builder apply(TypeRuntimeWiring.Builder builder) {
        return builder.dataFetcher(
            "ratings",
            new DataFetcher<>() {
              @Override
              public List<Rating> get(DataFetchingEnvironment environment)
                  throws Exception {
                return bookCatalogService.ratings(environment.getSource());
              }
            });
      }
    });

Data Fetchers

Probably the most important concept for a GraphQL Java server is a DataFetcher. While GraphQL Java is executing a query, it calls the appropriate DataFetcher for each field it encounters in the query.

Every field from the schema has a DataFetcher  associated with it. If you don’t specify any DataFetcher  for a specific field, then the default PropertyDataFetcher  is used.

In above example Query.books, Query.bookById has a data fetcher, as does each field in type Book. we typically don’t need specialized data fetchers on each field. As Graphql Java ships with a smart graphql.schema.PropertyDataFetcher that knows how to follow POJO patterns based on the field name. In the example above there is a name  field and hence it will try to look for a public String getName() POJO method to get the data.

RuntimeWiringConfigurer

You can change UnaryOperator<TypeRuntimeWiring.Builder> as a lambda expression. Then, the last step left is to tell Spring about GraphQL wiring by defining RuntimeWiringConfigurer as bean as:


@Configuration
public class GraphQLConfiguration {

  @Bean
  public RuntimeWiringConfigurer runtimeWiringConfigurer(BookCatalogService bookCatalogService) {

    return builder -> {
      builder.type(
          "Query",
          wiring ->
              wiring
                  .dataFetcher("books", environment -> bookCatalogService.getBooks())
                  .dataFetcher(
                      "bookById",
                      env -> bookCatalogService.bookById(Integer.parseInt(env.getArgument("id")))));
      builder.type(
          "Book",
          wiring ->
              wiring.dataFetcher("ratings", env -> bookCatalogService.ratings(env.getSource())));
    };
  }
}


Running and Testing

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

To test, open the GraphiQL editor in the browser using the link http://localhost:8080/graphiql?path=/graphql.

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

Summary

GraphQL, a query language for API and a server-side runtime for executing queries, is fast emerging as an alternative to REST API. Most significantly, it solves common problems associated with REST APIs such as over-fetching and under-fetching.

Spring Boot GraphQL provides support for Spring applications built on GraphQL Java. It supports the handling of GraphQL requests over HTTP, WebSocket, and RSocket.

If you like this article, then please follow me on LinkedIn  for more tips on #software architecture.

Tags: graphql
Previous Post

gRPC Interceptor: unary interceptor with code example

Next Post

Spring for GraphQL : @SchemaMapping and @QueryMapping

Pankaj

Pankaj

Software Architect @ Schlumberger ``` Cloud | Microservices | Programming | Kubernetes | Architecture | Machine Learning | Java | Python ```

Related Posts

GraphQL Error Handling
GraphQL

GraphQL Error Handling

August 9, 2023
Pages
GraphQL

Spring for GraphQL: Pagination with Code Example

July 26, 2023
GraphQL

Spring for GraphQL: Interfaces and Unions

May 17, 2023
GraphQL Directive
GraphQL

GraphQL Directive

September 29, 2022

Discussion about this post

Recent Articles

GraphQL Error Handling

GraphQL Error Handling

August 9, 2023
Pages

Spring for GraphQL: Pagination with Code Example

July 26, 2023

Spring for GraphQL: Interfaces and Unions

May 17, 2023
gRPC Bidirectional Streaming with Code Example

gRPC Bidirectional Streaming with Code Example

February 17, 2023
  • Trending
  • Comments
  • Latest
gRPC Bidirectional Streaming with Code Example

gRPC Bidirectional Streaming with Code Example

February 17, 2023
Deploying a RESTful Spring Boot Microservice on Kubernetes

Deploying a RESTful Spring Boot Microservice on Kubernetes

August 18, 2021
gRPC Interceptor: unary interceptor with code example

gRPC Interceptor: unary interceptor with code example

April 30, 2022
Temporal Workflow Orchestration

Workflow Orchestration with Temporal and Spring Boot

October 29, 2022
Calculus

Functional Programming in Java

0
Java Streams: stream creation with examples

Java Streams: stream creation with examples

0
Garbage Collection

Super Fast Garbage Collectors in Java

0
Java Streams: Stream Operation with Examples

Java Streams: Stream Operation with Examples

0
GraphQL Error Handling

GraphQL Error Handling

August 9, 2023
Pages

Spring for GraphQL: Pagination with Code Example

July 26, 2023

Spring for GraphQL: Interfaces and Unions

May 17, 2023
gRPC Bidirectional Streaming with Code Example

gRPC Bidirectional Streaming with Code Example

February 17, 2023
Facebook Twitter Pinterest

TECHDOZO

Simplifying modern tech stack!

Browse by Category

  • Bitesize
  • GraphQL
  • gRPC
  • Java
  • Kubernetes
  • Microservices
  • Spring Boot

Recent Articles

GraphQL Error Handling

GraphQL Error Handling

August 9, 2023
Pages

Spring for GraphQL: Pagination with Code Example

July 26, 2023

© 2023 Techdozo.

Welcome Back!

Sign In with Google
OR

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Home
  • gRPC
  • Kubernetes
  • Microservices
  • GraphQL

© 2023 Techdozo.