GraphQL is a more flexible query language and runtime for APIs that lets clients request exactly the data they need by making data fetching more efficient. Compared to REST, GraphQL allows clients to define the exact structure of the response, making data retrieval smoother and more efficient. Integrating GraphQL with Java applications, especially in microservices, can boost data fetching speed and overall performance.
In this article, we will learn how to make a call to a GraphQL service from a Java application using Spring Boot and graphql-java
.
Prerequisites:
- Basic knowledge of Java and Spring Boot.
- Basic knowledge of the GraphQL.
- Maven for building dependency management.
- JDK and IntelliJ IDEA installed in your system.
Calling a GraphQL Service From a Java Application
To call a GraphQL service, it is necessary to understand the following concepts:
- What is GraphQL?
- Differences between GraphQL and REST
- Using
WebClient
for GraphQL API interaction
GraphQL
GraphQL is an API query language that allows clients to specify exactly which data they need. Compared to REST, it is more efficient, as it supports:
- Client-Specified Queries: The client defines the response structure, avoiding over-fetching and under-fetching of data.
- Single Endpoint: Unlike REST, GraphQL uses one endpoint to handle all queries, mutations, and subscriptions.
- Queries and Mutations:
- Queries are used for data retrieval (similar to GET requests).
- Mutations modify server data (similar to POST, PUT, or DELETE requests).
- GraphQL Schema: Defines the data types and relationships available through the API, serving as a contract between server and client.
Setting Up the Java Application to Call GraphQL
To call a GraphQL service from Java, the main steps are defining the query, sending it to the GraphQL endpoint, and processing the response.
1. Define the GraphQL Query
GraphQL queries are JSON objects with a "query" key. For example:
{
"query": "query { users { id name email } }"
}
In this query, we request each user's id
, name
, and email
.
2. Use WebClient
to Send the Query
WebClient is a non-blocking HTTP client from Spring WebFlux. It is an alternative to RestTemplate
, providing better performance and flexibility for modern web applications.
Why Use WebClient?
- Non-blocking: Allows better handling of asynchronous operations.
- Reactivity: Supports reactive programming, useful for handling data streams.
Constructing the WebClient: Configure WebClient
with the GraphQL server’s base URL:
WebClient webClient = WebClient.builder()
.baseUrl("http://localhost:8080/graphql")
.build();
Sending the Query: Send the query as a POST request using WebClient
:
String query = "{ \"query\": \"query { users { id name email } }\" }";
String response = webClient.post()
.bodyValue(query)
.retrieve()
.bodyToMono(String.class)
.block();
This POST request sends the GraphQL query to the server, which returns the JSON response with the requested data.
3. Process the GraphQL Response
The GraphQL response is a JSON object containing the data key with the results. For instance:
{
"data": {
"users": [
{
"id": "1",
"name": "John Doe",
"email": "[email protected]"
},
{
"id": "2",
"name": "Jane Smith",
"email": "[email protected]"
}
]
}
}
This response includes the data object which contains the array of users.
By understanding these steps and the role of the each component, we can effectively integrate the GraphQL service with a Java application.
Example: Setting Up a GraphQL Server Application with Spring Boot
This section provides a sample setup for a GraphQL server with Spring Boot.
Step 1: Create a Spring Boot Project
Create a new Spring Boot project with the following settings:
- Name:
graphql-server-demo
- Type: Maven Project
Click on the Next button.
Step 2: Add the Dependencies
Add the following dependencies into the Spring Boot Project:
- Spring Web
- Spring Boot DevTools
- Lombok
- Spring Data JPA
- MySQL Driver
- Spring for GraphQL
Click on the Create button.
Project Structure
After the project creation done, set up the project structure as shown in the below image:
Step 3: Configure Application Properties
Open the application.properties file and add the following MySQL, Hibernate and GraphQL configuration.
spring.application.name=graphql-server-demo
# MySQL Database configuration
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=mypassword
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
# Show SQL queries in the console (Optional)
spring.jpa.show-sql=true
# GraphQL Configuration
graphql.servlet.mapping=/graphql
graphql.graphiql.enabled=true
Step 4: Define the GraphQL Schema
Define a GraphQL schema for queries in schema.graphqls
:
type Query {
users: [User]
userById(id: ID!): User
}
type User {
id: ID!
name: String!
email: String!
}
Step 5: Create the data.sql file
We will now create the data.sql file to insert the default data into the database.
INSERT INTO user (name, email) VALUES ('John Doe', '[email protected]');
INSERT INTO user (name, email) VALUES ('Jane Smith', '[email protected]');
INSERT INTO user (name, email) VALUES ('Alice Johnson', '[email protected]');
INSERT INTO user (name, email) VALUES ('Bob Brown', '[email protected]');
INSERT INTO user (name, email) VALUES ('Charlie Davis', '[email protected]');
Step 6: Create the User Entity
Create a User
class to represent user data:
Java
package com.gfg.graphqlserverdemo;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;
@Data
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
}
Step 7: Create the UserRepository Interface
Java
package com.gfg.graphqlserverdemo;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
Step 8: Create the UserService Class
Java
package com.gfg.graphqlserverdemo;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public List<User> getAllUsers() {
return userRepository.findAll();
}
public Optional<User> getUserById(Long id) {
return userRepository.findById(id);
}
}
Step 9: Create the UserController Class
Java
package com.gfg.graphqlserverdemo;
import com.gfg.graphqlserverdemo.User;
import com.gfg.graphqlserverdemo.UserService;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
import reactor.core.publisher.Mono;
import java.util.List;
@Controller
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@QueryMapping
public Mono<List<User>> users() {
return (Mono<List<User>>) userService.getAllUsers();
}
@QueryMapping
public Mono<User> userById(Long id) {
return Mono.justOrEmpty(userService.getUserById(id));
}
}
Step 10: Main class
No changes are required in the main class.
Java
package com.gfg.graphqlserverdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GraphqlServerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(GraphqlServerDemoApplication.class, args);
}
}
pom.xml File:
XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.gfg</groupId>
<artifactId>graphql-server-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>graphql-server-demo</name>
<description>graphql-server-demo</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<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-graphql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>11.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</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>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.graphql</groupId>
<artifactId>spring-graphql-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Step 11: Run the Application
Once the project is completed, we will run the application and it will start at port 8080.
Setting Up a GraphQL Client Application
Step 1: Create a new Spring Boot Project
Create a new Spring Boot project using IntelliJ IDEA, then choose the following options:
- Name: graphql-client-demo
- Language: Java
- Type: Maven
- Packaging: Jar
Click on the Next button.
Step 2: Add the Dependencies
Add the following dependencies into the Spring Boot project:
- Spring Reactive Web
- Lombok
- Spring Boot DevTools
Click on the Create button.
Project Structure
Once the project is created, set the file structure as shown in the below image:
Step 3: Configure Application Properties
Now, we will configure the properties in application.properties.
spring.application.name=graphql-client-demo
server.port=8081
graphql.service.url=http://localhost:8080/graphql
Step 4: Create the User Class
Java
package com.gfg.graphqlclientdemo;
import lombok.Data;
@Data
public class User {
private String id;
private String name;
private String email;
}
Step 5: Create the UserService Class
Java
package com.gfg.graphqlclientdemo;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.util.List;
@Service
public class UserService {
private final WebClient webClient;
private final ObjectMapper objectMapper;
public UserService(@Value("${graphql.service.url}") String graphqlUrl) {
this.webClient = WebClient.builder()
.baseUrl(graphqlUrl)
.build();
this.objectMapper = new ObjectMapper();
}
public Mono<List<User>> fetchUsers() {
String query = "{ \"query\": \"query { users { id name email } } }\" }";
return webClient.post()
.bodyValue(query)
.retrieve()
.onStatus(HttpStatusCode::isError,
response -> Mono.error(new RuntimeException("Failed to fetch users: " + response.statusCode().value()))
)
.bodyToMono(String.class)
.map(response -> {
try {
JsonNode jsonNode = objectMapper.readTree(response);
JsonNode usersNode = jsonNode.get("data").get("users");
return objectMapper.convertValue(usersNode,
objectMapper.getTypeFactory().constructCollectionType(List.class, User.class));
} catch (Exception e) {
throw new RuntimeException("Failed to parse GraphQL response", e);
}
});
}
}
Step 6: Create the UserController class
Java
package com.gfg.graphqlclientdemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/users")
public List<User> getUsers() {
return (List<User>) userService.fetchUsers();
}
}
Step 7: Main class
No changes are required in the main class.
Java
package com.gfg.graphqlclientdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GraphqlClientDemoApplication {
public static void main(String[] args) {
SpringApplication.run(GraphqlClientDemoApplication.class, args);
}
}
pom.xml File:
XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.gfg</groupId>
<artifactId>graphql-client-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>graphql-client-demo</name>
<description>graphql-client-demo</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Step 9: Run the Application
Once the project is completed, we will run the project and it will start at port 8081.
Conclusion
Integrating GraphQL with a Java application allows for the efficient data fetching and flexibility in the API communication. By using the WebClient in the Spring Boot Project, we can easily send the queries to the GraphQL service and parse the results into Java objects. This method is particularly useful for the microservices and applications that need to fetch nested or complex data structures.
Similar Reads
How to Create a Simple Spring Boot Application?
Spring Boot is one of the most popular frameworks for building Java-based web applications. It is used because it simplifies the development process by providing default configurations and also reduces boilerplate code. In this article, we will cover the steps to create a simple Spring Boot applicat
2 min read
How to Deploy Spring Boot Application in Kubernetes ?
The Spring Boot framework provides an assortment of pre-configured templates and tools to make the development of Java-based applications simpler. With little configuration, it enables developers to quickly design production-ready, stand-alone apps. Kubernetes, commonly referred to as K8s, is an ope
7 min read
Add Build Properties to a Spring Boot Application
Spring Boot framework is an open-source framework for developing web applications with high performance and the Spring Boot makes it much easier to develop Spring-based applications developed by Java programming In this article, we will learn how to add build properties to a Spring Boot Application.
4 min read
How to Install Spring Boot Application in Hostinger?
Spring Boot is a popular platform for developing Java-based web applications, known for its robust features and ease of use. Hostinger offers high-quality, affordable hosting that is well-suited for Spring Boot applications. This article will guide you through deploying your Spring Boot application
4 min read
How to Set Context Path in Spring Boot Application?
The context path is a prefix to the URL path used to identify and differentiate between different context(s). In Spring Boot, by default, the applications are accessed by context path â/â. That means we can access the application directly at http://localhost:PORT/. For example http://localhost:8080/
6 min read
How to Run Your First Spring Boot Application in Eclipse IDE?
Spring Boot is built on the top of the spring and contains all the features of spring. And is becoming a favorite of developers these days because of its rapid production-ready environment which enables the developers to directly focus on the logic instead of struggling with the configuration and se
3 min read
How to Run Spring Boot Application?
Spring Boot is built on the top of Spring and contains all the features of Spring. And it is becoming a favorite of developers these days because of its rapid production-ready environment which enables the developers to directly focus on the logic instead of struggling with the configuration and set
8 min read
Using WebSocket to Build an Interactive Web Application in Spring Boot
WebSockets enable two-way communication over a single, persistent connection, allowing for real-time, bidirectional data exchange between the client and server. Unlike traditional HTTP, which is request-response based, WebSocket communication allows for real-time, bi-directional communication betwee
6 min read
How To Build And Deploy Spring Boot Application In Tomcat For DevOps ?
Spring Boot is a famous Java framework for building stand-alone applications. Now if we are going to build web applications using Spring Boot then it may not be useful to build stand-alone applications as we need to deploy the application on the web. Spring Boot by default packages the application i
9 min read
Configuring Store Procedure in Spring Boot Application
The Store Procedure is a prepared SQL statement that is used over and over again (Reusable code). So, if we have an SQL query that we need to write over and over again, we can save it as a Stored Procedure, and then just call it to execute it. We can also pass parameters to a Stored Procedure so tha
4 min read