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
}
}
}