DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Providing Enum Consistency Between Application and Data
  • DDD and Spring Boot Multi-Module Maven Project
  • How to Build a New API Quickly Using Spring Boot and Maven
  • A Practical Guide to Creating a Spring Modulith Project

Trending

  • Why High-Performance AI/ML Is Essential in Modern Cybersecurity
  • Understanding and Mitigating IP Spoofing Attacks
  • Automating Data Pipelines: Generating PySpark and SQL Jobs With LLMs in Cloudera
  • The Role of Functional Programming in Modern Software Development
  1. DZone
  2. Data Engineering
  3. Databases
  4. DGS GraphQL and Spring Boot

DGS GraphQL and Spring Boot

This article explain how to use and implement DGS GraphQL using Spring Boot, and the GraphQL dashboard to make specific REST requests.

By 
Milan Karajovic user avatar
Milan Karajovic
·
May. 13, 25 · Tutorial
Likes (0)
Comment
Save
Tweet
Share
909 Views

Join the DZone community and get the full member experience.

Join For Free

Why GraphQL?

GraphQL provides a powerful layer to unify data from various backend sources, including databases, REST APIs, and microservices, into a single, consistent API. It enables the creation of flexible APIs that can evolve with changing client applications.

Introduction

This article will show you how to create an effective application that implements GraphQL using the Netflix DGS framework in the Spring Boot application.

Netflix DGS is an annotation-based GraphQL Java library built on top of Spring Boot. With Netflix DGS is allowed generating source code from GraphQL schemas. It simplifies writing unit tests and also supports websockets, file uploads, or GraphQL federation.

Tech Stack

  • Java 17
  • Spring Boot 3.4.3
  • Netflix DGS GraphQL 10.0.4
  • JPA
  • Maven
  • Lombok
  • JUnit
  • H2 Database

Application Development and Analysis

Create Spring Boot application using Spring Initializr. Setup is shown on the picture below: 

Create Spring Boot application


In this picture we can see all dependencies which we need to include in the graphql-spring-boot project. For the database we will use in-memory H2 database. Here’s a list of required dependencies in Maven pom.xml: 

XML
 
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>com.netflix.graphql.dgs</groupId>
    <artifactId>graphql-dgs-spring-graphql-starter</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
  </dependency>
  <dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
  </dependency>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>com.netflix.graphql.dgs</groupId>
    <artifactId>graphql-dgs-spring-graphql-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>


Grapql Schema

A schema may be defined in multiple graphqls files, but all of them have to be placed inside the /src/main/resources/schemas directory. The Netflix DGS library detects and loads them automatically. 

Python
 
"""
Sample user account container class.
"""
type User {
	"Sequential identifier"
	id: ID!
	"User's first & last name"
	name: String!
	"User's email"
	email: String
}

"""
User creation input
"""
input CreateUserInput {
	"User's first & last name"
	name: String
	"User's email"
	email: String
}

"""
User modification input
"""
input UpdateUserInput {
	"User's first & last name"
	name: String
	"User's email"
	email: String
}

"""
User object queries
"""
type Query {
	user(id: ID!): User
	users: [User]!
}

"""
User object modifications
"""
type Mutation {
	createUser(input: CreateUserInput!): User!
	updateUser(id: ID!, input: UpdateUserInput!): User!
	deleteUser(id: ID!): User!
}


The DGS framework is designed for schema first development. The framework picks up any schema files in the src/main/resources/schema folder. We created schema file schema.graphql. In this file are defined types, queries and mutations. Regarding this class we create classes in specific packages in the application.

It is possible using DGS plugin to generated Java source code using previously defined GraphQL schemas. However, I prefer to use Lombok annotations, so I did that manually.

Application Structure

This is application structure:

Application structure

Implementation

The most important classes are:

Domain 

(/graphql-spring-boot/src/main/java/rs/karajovic/milan/graphql_spring_boot/domain): 

  • Thera are defined domain object which exists in the above mentioned file src/main/resources/schema.

Repository 

(/graphql-spring-boot/src/main/java/rs/karajovic/milan/graphql_spring_boot/repository):

  • Thera are defined JPA repository which is used from the application to communicate with databse.

Service 

(/graphql-spring-boot/src/main/java/rs/karajovic/milan/graphql_spring_boot/service):

  • Service is layer which is between fatcher and repository.

Fetcher 

(/graphql-spring-boot/src/main/java/rs/karajovic/milan/graphql_spring_boot/fetcher):

(This is central part of the DGS GraphQL application. There are defined Queries and Mutations regarding to the declaration in the schema.graphql file).

  • Netflix DGS provides annotation-based support for Spring Boot.
  • The UserFetcher is responsible for defining queries related to the User object. We should annotate such a class with @DgsComponent. Then, we have to annotate every query method with @DgsData. The fields parentType and fields should match the names declared in GraphQL schemas for Queries. We can see that in the file schema.graphql are defined two queries, so we have two methods inside UserFetcher. To fetch data from the database are used methodes from the Service class. The last query method findUserById performs advanced filtering based on the user id field passed in the input. To pass an input parameter we should annotate the method argument with @InputArgument.
Java
 
package rs.karajovic.milan.graphql_spring_boot.fetcher;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import com.netflix.graphql.dgs.DgsComponent;
import com.netflix.graphql.dgs.DgsData;
import com.netflix.graphql.dgs.InputArgument;

import rs.karajovic.milan.graphql_spring_boot.domain.User;
import rs.karajovic.milan.graphql_spring_boot.service.UserService;

/**
 * 
 * @author Milan Karajovic <[email protected]>
 *
 */

@DgsComponent
public class UserFetcher {
	
	@Autowired
	UserService userService;
	
	
	@DgsData(parentType = "Query", field = "users")
    public List<User> findAllUsers() {
        return userService.findAll();
    }
	
	@DgsData(parentType = "Query", field = "user")
    public User findUserById(@InputArgument("id") Integer id) {
		return userService.findUserById(id);
    }
	
}


  • In comparison to the UserFetcher, UserMutation implementation is similar. The fields parentType and fields should match the names declared in GraphQL schemas for Mutations. To pass an input parameter we should annotate the method argument with @InputArgument. To execute Muttaion methodes are used methodes from the Service class.
Java
 
package rs.karajovic.milan.graphql_spring_boot.fetcher;

import org.springframework.beans.factory.annotation.Autowired;


import com.netflix.graphql.dgs.DgsComponent;
import com.netflix.graphql.dgs.DgsData;
import com.netflix.graphql.dgs.InputArgument;

import jakarta.validation.Valid;
import rs.karajovic.milan.graphql_spring_boot.domain.CreateUserInput;
import rs.karajovic.milan.graphql_spring_boot.domain.UpdateUserInput;
import rs.karajovic.milan.graphql_spring_boot.domain.User;
import rs.karajovic.milan.graphql_spring_boot.service.UserService;

/**
 * 
 * @author Milan Karajovic <[email protected]>
 *
 */

@DgsComponent
public class UserMutation {
	
	@Autowired
	UserService userService;
	
	@DgsData(parentType = "Mutation", field = "createUser")
    public User createUser(@InputArgument("input") CreateUserInput userInput) {
		return userService.save(new User(null, userInput.getName(), userInput.getEmail()));
	}
	
	@DgsData(parentType = "Mutation", field = "updateUser")
    public User updateUser(@InputArgument("id") Integer id, @Valid @InputArgument("input") UpdateUserInput userInput) {
		return userService.updateUser(id, userInput.getName(), userInput.getEmail());
	}
	
	@DgsData(parentType = "Mutation", field = "deleteUser")
    public User deleteUser(@InputArgument("id") Integer id) {
		return userService.deleteUserById(id);
	}
	
}


Database 

  • For this demo application is used inmemory H2 database. Configuration for the database is in the application.properties file. The data.sql script is used for initial filing database with data.

Tests

  • Tests are in the /graphql-spring-boot/src/test/java/rs/karajovic/milan/graphql_spring_boot/fetcher . There are tests for the Queries and Mutations.

Run Application in Your Development Environment

Run Spring Boot application in your development environment:  

  • Access to the H2 database: 
Textile
 
http://localhost:8080/h2-console


  • Access to the GraphiQL dashboard:
Textile
 
http://localhost:8080/graphiql


Build, and Run Application Using Docker

  • Prerequisite is to have installed Docker on your machine.
  • Download source code for this exaple from the GitHub.
  • Build the application using Maven (For building, I suggest to use STS or intelliJ IDEA development environment. However, you can do that also manually with maven command).

Textile
 
mvn clean install


  • The .jar file is created in the folder:
Textile
 
/graphql-spring-boot/target/graphql-spring-boot-0.0.1-SNAPSHOT.jar


  • Using Docker file, we create image graphql-spring-boot using next command in the console (It is necessary to open the console in the root folder of the project). The command is: 
Textile
 
docker image build -t graphql-spring-boot .


  • Now, we can start applicaton using docker-compose.yaml file. (It is necessary to open the console in the root folder of the project). The command is:
Textile
 
docker-compose up


  • Now we can access to the GraphiQL dashboard with: 
Textile
 
http://localhost/graphiql


  • After application is success started, let’s just use the GraphiQL tool to run test queries. It is automatically included in the application by the Netflix DGS library. We may display it by invoking the URL

GraphiQL Dashboard

  • GraphQL tool dashboard. There are all Queries and Mutations:GraphQL tool dashboard


  • Show all users in database using Query:

Show all users in database

  • Create user using Mutation:

Create user

  • Show all users after created new user in the previous step:

Show all users

  • Delete user by ID:

Delete user by ID

You can check all Queries and Mutation yourself using this dashboard. 

Contact and Support

  • Author: Milan Karajovic
  • GitHub:  https://github.com/Milan-Karajovic/GraphQL-SpringBoot
  • LinkedIn: https://www.linkedin.com/in/milan-karajovic-3a1243359/
Apache Maven GraphQL application Spring Boot

Opinions expressed by DZone contributors are their own.

Related

  • Providing Enum Consistency Between Application and Data
  • DDD and Spring Boot Multi-Module Maven Project
  • How to Build a New API Quickly Using Spring Boot and Maven
  • A Practical Guide to Creating a Spring Modulith Project

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: