Reader small image

You're reading from  Modern API Development with Spring 6 and Spring Boot 3 - Second Edition

Product typeBook
Published inSep 2023
Reading LevelIntermediate
PublisherPackt
ISBN-139781804613276
Edition2nd Edition
Languages
Concepts
Right arrow
Author (1)
Sourabh Sharma
Sourabh Sharma
author image
Sourabh Sharma

Sourabh Sharma is a Senior Development Manager at Oracle with over 20 years of experience in the industry. He is a manager and architect who has been designing on-premise and cloud-based applications using Java, Javascript, and Oracle DB. Sourabh has worked with leading companies and delivered enterprise products and applications. His expertise lies in conceptualizing, modeling, designing, and developing N-tier and cloud-based web applications while leading teams. Sourabh's experience also includes developing microservice-based solutions and implementing various types of workflow and orchestration engines. He believes in continuous learning and sharing knowledge through his books and training.
Read more about Sourabh Sharma

Right arrow

GraphQL API Development and Testing

In the previous chapter, we learned about the fundamental concepts of GraphQL. You are going to use that knowledge to develop and test GraphQL-based APIs in this chapter. You will implement GraphQL-based APIs for a sample application in this chapter. The GraphQL server implementation will be developed based on a design-first approach, the way you defined the OpenAPI specification in Chapter 3, API Specifications and Implementation, and designed the schema in Chapter 11, gRPC API Development and Testing.

After completing this chapter, you will have learned how to practically implement the GraphQL concepts learned about in the previous chapter and about the implementation of the GraphQL server using Java and Spring and its testing.

This chapter will cover the following main topics:

  • Workflow and tooling for GraphQL
  • Implementing the GraphQL server
  • Documenting APIs
  • Test automation

Workflow and tooling for GraphQL

As per the data graph (data structure) way of thinking in GraphQL, data is exposed using an API consisting of graphs of objects. These objects are connected using relations. GraphQL only exposes a single API endpoint. Clients query this endpoint, which uses a single data graph. On top of that, the data graph may resolve data from a single source, or multiple sources, by following the OneGraph principle of GraphQL. These sources could be a database, legacy system, or services that expose data using REST/gRPC/SOAP.

The GraphQL server can be implemented in the following two ways:

  • Standalone GraphQL service: A standalone GraphQL service contains a single data graph. It could be a monolithic app or based on a microservice architecture that fetches the data from single or multiple sources (having no GraphQL API).
  • Federated GraphQL services: It’s very easy to query a single data graph for comprehensive data fetching. However, enterprise...

Implementing the GraphQL server

You are going to develop a standalone GraphQL server in this chapter. The knowledge you acquire while developing the standalone GraphQL server can be used to implement federated GraphQL services.

Let’s create the Gradle project first in the next subsection.

Creating the gRPC server project

Either you can use the Chapter 14 code by cloning the Git repository (https://github.com/PacktPublishing/Modern-API-Development-with-Spring-6-and-Spring-Boot-3/tree/dev/Chapter14) or you can start by creating a new Spring project from scratch using Spring Initializr for the server and client with the following options:

  • Project: Gradle - Groovy
  • Language: Java
  • Spring Boot: 3.0.8

The preferred version is 3.0+; if not available, you can modify it later manually in the build.gradle file

  • Project Metadata:
    • Group: com.packt.modern.api
    • Artifact: chapter14
    • Name: chapter14
    • Description: Chapter 14 code of book Modern API Development...

Implementing GraphQL queries

Both the queries we introduced in the schema in the previous section are straightforward. You pass a product ID to find a product identified by that ID – that’s the product query for you. Next, you pass the optional product criteria to find the products based on the given criteria; otherwise, products are returned based on the default values of the fields of product criteria.

In REST, you implemented the controller class in the Implementing the OAS code interfaces section of Chapter 3, API Specifications and Implementation. You created a controller, passed the call to the service, and the service called the repository to fetch the data from the database. You are going to use the same design. However, you are going to use ConcurrentHashMap in place of the database to simplify the code. This can also be used in your automated tests.

Let’s create a repository class for that, as shown in the next code block:

public interface Repository...

Writing fetchers for GraphQL queries

You are going to write data fetchers in this section. Data fetchers, as the name suggests, retrieve the information from the source that is from a persistent store such as a database or a third-party API/document store. You will learn how to write data fetchers to retrieve a single field of data, a single object, and a collection of objects.

Writing the data fetcher for product

The data fetcher is a critical DSG component for serving GraphQL requests that fetches the data and the DSG internally resolves each of the fields. You mark them with the special @DgsComponent DGS annotation. These are types of Spring components that the DGS framework scans and uses for serving requests.

Let’s create a new file called ProductDatafetcher.java in the datafetchers package to represent a DGS data fetcher component. It will have a data fetcher method for serving the product query. You can add the following code to it:

@DgsComponentpublic class...

Implementing GraphQL mutations

As per the GraphQL schema, you are going to implement two mutations – addTag and addQuantity.

The addTag mutation takes productId and a collection of tags as arguments and returns the Product object. The addQuantity mutation takes productId and the quantity to add and returns Product.

Let’s add this implementation to the existing ProductDatafetcher class as shown in the following code block:

// rest of the ProductDatafetcher class code@DgsMutation(field = MUTATION.AddTag)
public Product addTags(
    @InputArgument("productId") String productId,
    @InputArgument(value = "tags", collectionType =
         TagInput.class) List<TagInput> tags) {
  return tagService.addTags(productId, tags);
}
@DgsMutation(field = MUTATION.AddQuantity)
public Product addQuantity(
      @InputArgument...

Implementing and testing GraphQL subscriptions

Subscription is another GraphQL root type that sends the object to the subscriber (client) when a particular event occurs.

Let’s assume an online shop offers a discount on products when the product’s inventory reaches a certain level. You cannot track each product’s quantity manually and then perform the computation and trigger the discount. To do things faster (or reduce manual intervention), this is where you can make use of a subscription.

Each change in the product’s inventory (quantity) through the addQuantity() mutation should trigger the event and the subscriber should receive the updated product and hence the quantity. Then, the subscriber can place the logic and automate this process.

Let’s write the subscription that will send the updated product object to the subscriber. You are going to use Reactive Streams and WebSocket to implement this functionality.

You need to enable CORS...

Instrumenting the GraphQL APIs

The GraphQL Java library supports the instrumentation of the GraphQL APIs. This can be used to support metrics, tracing, and logging. The DGS framework also uses it. You just must mark the instrumentation class with the Spring @Component annotation.

The instrumentation bean can be implemented using the graphql.execution. instrumentation.Instumentation interface. Here, you have to write boilerplate code, which may increase the unit test automation code for you. Another way that is much easier is to extend the SimpleInstrumentation class, which does the simple implementation for you. However, you can override the methods for custom implementation.

Let’s add instrumentation that will record the time taken by the data fetcher and complete GraphQL request processing. This metric may help you to fine-tune the performance and identify the fields that take more time to resolve.

Before adding the tracing, let’s add the custom header in the...

Test automation

The DGS framework provides classes and utilities that facilitate the automation of GraphQL API tests.

Create a new file called ProductDatafetcherTest.java inside the datafetchers package in the test directory and add the following code:

@SpringBootTest(classes = { DgsAutoConfiguration.class,     ProductDatafetcher.class,BigDecimalScalar.class })
public class ProductDatafetcherTest {
  private final InMemRepository repo = new InMemRepository();
  private final int TEN = 10;
  @Autowired
  private DgsQueryExecutor dgsQueryExecutor;
  @MockBean
  private ProductService productService;
  @MockBean
  private TagService tagService;
  // continue …

https://github.com/PacktPublishing/Modern-API-Development-with-Spring-6-and-Spring-Boot-3/tree/dev/Chapter14/src/test/java/com/packt/modern/api/datafetchers/ProductDatafetcherTest.java

Here, you are using the @SpringBootTest...

Summary

In this chapter, you learned about the different ways of implementing the GraphQL server, including federated GraphQL services. You have also explored the complete standalone GraphQL server implementation, which performs the following operations:

  • Writing the GraphQL schema
  • Implementing the GraphQL query APIs
  • Implementing the GraphQL mutation APIs
  • Implementing the GraphQL subscription APIs
  • Writing the data loaders to solve the N+1 problem
  • Adding custom scalar types
  • Adding the GraphQL API’s instrumentation
  • Writing the GraphQL API’s test automation using Netflix’s DGS framework

You learned about GraphQL API implementation using Spring and Spring Boot skills that will help you implement GraphQL APIs for your work assignments and personal projects.

Questions

  1. Why should you prefer frameworks such as Netflix’s DGS in place of the graphql-java library to implement GraphQL APIs?
  2. What are federated GraphQL services?

Answers

  1. You should prefer a framework such as Netflix DGS in place of the graphql-java library to implement GraphQL APIs because it bootstraps the development and avoids writing boilerplate code.

Apart from the ease of development, the framework uses graphql-java internally; therefore, it keeps itself in sync with the GraphQL specification’s Java implementation. It also supports developing federated GraphQL services.

It also provides plugins, the Java client, and testing utilities that help you to automate the development. The Netflix DGS framework is well tested and has been used by Netflix in production for quite some time.

  1. A federated GraphQL service contains a single distributed graph exposed using a gateway. Clients call the gateway, which is an entry point to the system. A data graph will be distributed among multiple services and each service can maintain its own development and release cycle independently. Having said that, federated GraphQL services...
lock icon
The rest of the chapter is locked
You have been reading a chapter from
Modern API Development with Spring 6 and Spring Boot 3 - Second Edition
Published in: Sep 2023Publisher: PacktISBN-13: 9781804613276
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
Sourabh Sharma

Sourabh Sharma is a Senior Development Manager at Oracle with over 20 years of experience in the industry. He is a manager and architect who has been designing on-premise and cloud-based applications using Java, Javascript, and Oracle DB. Sourabh has worked with leading companies and delivered enterprise products and applications. His expertise lies in conceptualizing, modeling, designing, and developing N-tier and cloud-based web applications while leading teams. Sourabh's experience also includes developing microservice-based solutions and implementing various types of workflow and orchestration engines. He believes in continuous learning and sharing knowledge through his books and training.
Read more about Sourabh Sharma