An HTTP Rest API is the traditional way of fetching data from the server, for each endpoints, it has a fixed contract, which will be returned as the response of the API Call. for some clients the entire response data is necessary, but for some, only a few variables may required, since REST API architecture returns all the data, the client has to accept and parse the entire response data this is also called as Over-fetching, so let's see How GraphQL Solves Over Fetching
GraphQL allows an API consumer to request the required specific data from the server and nothing else, GraphQL will return that response only.
GraphQL provides API consumers an option to request what is required as the below API query
query FindApple {
findApple {
appleName
vendors {
vendorName
}
stores {
storeName
}
}
}Let's understand How GraphQL Solves Over Fetching with an Example
The below program provides an API endpoint/findApple which provides details of Apple object along with a List of Vendor and List of Store details.
| Rest End Point | Response | |
|---|---|---|
|
|
The GraphQL controller allows the client to request only the required parameters
| GraqlQL Query | GraphQL Response |
|---|---|
|
|
Let's see the Spring Boot GraphQL program for the same
package org.wesome.graphql.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
import org.wesome.graphql.entity.Apple;
import org.wesome.graphql.service.AppleService;
import java.util.Optional;
@Controller
public record AppleGraphQLController(@Autowired AppleService appleService) {
@QueryMapping("findApple")
Optional<Apple> findApple() {
return appleService.findApple();
}
}
package org.wesome.graphql.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.wesome.graphql.entity.Apple;
import org.wesome.graphql.service.AppleService;
import java.util.Optional;
@RestController
public record AppleRestController(@Autowired AppleService appleService) {
@GetMapping(path = "/findApple", produces = "application/json")
Optional<Apple> findApple() {
return appleService.findApple();
}
}
package org.wesome.graphql.data;
public enum AppleType {
MACINTOSH, FUJI, GALA, JONAGOLD
}
package org.wesome.graphql.entity;
public record Apple(int appleId, String appleName, Boolean available, Float price) {
}
package org.wesome.graphql.entity;
public record Store(int storeId, int appleId, String storeName, String storeAddress) {
}
package org.wesome.graphql.entity;
public record Vendor(int vendorId, int appleId, String vendorName, Boolean available) {
}
package org.wesome.graphql.service;
import org.wesome.graphql.entity.Apple;
import java.util.Optional;
public interface AppleService {
Optional<Apple> findApple();
}
package org.wesome.graphql.service;
import org.springframework.stereotype.Service;
import org.wesome.graphql.entity.Apple;
import java.util.Optional;
import static org.wesome.graphql.GraphqlProjectApplication.apple;
@Service
public record AppleServiceImpl() implements AppleService {
@Override
public Optional<Apple> findApple() {
return Optional.of(apple);
}
}
package org.wesome.graphql;
import com.github.javafaker.Faker;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.wesome.graphql.data.AppleType;
import org.wesome.graphql.entity.Apple;
import org.wesome.graphql.entity.Store;
import org.wesome.graphql.entity.Vendor;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@SpringBootApplication
public class GraphqlProjectApplication implements CommandLineRunner {
public static Apple apple;
public static List<Vendor> vendors;
public static List<Store> stores;
public static void main(String[] args) {
SpringApplication.run(GraphqlProjectApplication.class, args);
}
@Override
public void run(String... args) {
Faker faker = new Faker();
vendors = IntStream.rangeClosed(1, AppleType.values().length - 1).mapToObj(value -> new Vendor(value, value, faker.name().fullName(), faker.random().nextBoolean())).collect(Collectors.toList());
stores = IntStream.rangeClosed(1, AppleType.values().length - 1).mapToObj(value -> new Store(value, value, faker.company().name(), faker.address().fullAddress())).collect(Collectors.toList());
apple = new Apple(1, AppleType.MACINTOSH.name(), faker.random().nextBoolean(), Float.valueOf(1), vendors, stores);
}
}\src\main\resources\graphql\schema.graphqls
# Apple Object
type Apple{
# primary key of apple
appleId:ID!
# apple Name
appleName:String!
# apple availability
available: Boolean
# apple Price
price:Float
# Vendor list
vendors:[Vendor]
# stores List
stores:[Store]
}
# Store Object
type Store{
# primary key of store
storeId:ID!
# primary key of apple
appleId:ID!
# apple Store Name
storeName:String!
# apple store Address
storeAddress:String!
}
# Store Object
type Vendor{
# primary key of vendor
vendorId:ID!
# primary key of apple
appleId:ID!
# apple vendor Name
vendorName:String!
# vendor availability
available: Boolean
}
# Apple Query
type Query{
# query to get all Apples
findApple:Apple
}\src\main\resources\application.properties
spring.graphql.graphiql.enabled=true
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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.1.5</version>
<relativePath/>
</parent>
<groupId>org.wesome</groupId>
<artifactId>spring-boot-graphql</artifactId>
<version>0.0.1-snapshot</version>
<name>spring-boot-graphql</name>
<description>implementing graphql in spring boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-graphql</artifactId>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-extended-scalars</artifactId>
<version>21.0</version>
</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>
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>how to access Rest API
cURL
cURL command is very useful for checking the API endpoint. The rest endpoint can be accessed via curl
| API | Rest End Point | Curl |
|---|---|---|
| findApple |
|
|
how to access GraphQL API
GraphQL provides multiple ways to access the API, let's see them
cURL
The GraphQL can be accessed via the below cURL command.
curl --location --request POST "http://localhost:8080/graphql" \
--header "Content-Type: application/json" \
--data "{\"query\":\"query FindApple {\r\n findApple {\r\n appleName\r\n vendors {\r\n vendorName\r\n }\r\n stores {\r\n storeName\r\n }\r\n }\r\n}\r\n\",\"variables\":{}}"GraphiQL
GraphQL provides an inbuild UserInterface GraphiQL, which can be accessed via http://localhost:8080/graphiql, in the query section add the below query
query FindApple {
findApple {
appleName
vendors {
vendorName
}
stores {
storeName
}
}
}Postman Post Method
GraphQL can be accessed via Postman as well, open Postman-> file-> import and paste the below curl
curl --location --request POST "http://localhost:8080/graphql" \
--header "Content-Type: application/json" \
--data "{\"query\":\"query FindApple {\r\n findApple {\r\n appleName\r\n vendors {\r\n vendorName\r\n }\r\n stores {\r\n storeName\r\n }\r\n }\r\n}\r\n\",\"variables\":{}}"Postman GraphQL Request Type
Postman provides a GraphQL request type UI, Open Postman-> file-> new->GraphQL and add the URL https://localhost:8080/graphql in the query section add the below query
query FindApple {
findApple {
appleName
vendors {
vendorName
}
stores {
storeName
}
}
}