Object Oriented Programming suggests reusing common objects. Sometimes Queries becomes repetitive by calling the same fields in multiple queries. SpringBoot GraphQL Fragments provides Fragments to reuse Objects in Query. Fragments are groups of selected fields ie root elements and child elements. Fragments have a name and are created from an object, interface, or union.
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.List;
@Controller
public class AppleGraphQLController {
@Autowired
private AppleService appleService;
@QueryMapping("findAllApple")
List<Apple> findAllApple() {
return appleService.findAllApple();
}
}
package org.wesome.graphql.entity;
public record Apple(int appleId, String appleName, String taste, Boolean available, Vendor buyFrom, Vendor sellTo) {
}
package org.wesome.graphql.entity;
public enum AppleTaste {
SWEET("sweet"), TANGY("tangy"), BITTER("bitter"), SOUR("sour");
private final String taste;
AppleTaste(String taste) {
this.taste = taste;
}
}
package org.wesome.graphql.entity;
public record Vendor(int id, String name, Boolean available, String location) {
}
package org.wesome.graphql.service;
import org.wesome.graphql.entity.Apple;
import java.util.List;
public interface AppleService {
List<Apple> findAllApple();
}
package org.wesome.graphql.service;
import com.github.javafaker.Faker;
import org.springframework.stereotype.Service;
import org.wesome.graphql.entity.Apple;
import org.wesome.graphql.entity.AppleTaste;
import org.wesome.graphql.entity.Vendor;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
@Service
public class AppleServiceImpl implements AppleService {
private static final List<Apple> apples = new ArrayList<>();
static {
Faker faker = new Faker();
IntStream.rangeClosed(1, 5).forEach(i -> {
Vendor buyFrom = new Vendor(faker.number().randomDigitNotZero(), faker.company().name(), faker.bool().bool(), faker.address().country());
Vendor sellTo = new Vendor(faker.number().randomDigitNotZero(), faker.company().name(), faker.bool().bool(), faker.address().country());
Apple apple = new Apple(i, faker.food().fruit(), AppleTaste.values()[faker.random().nextInt(0, 3)].name(), faker.bool().bool(), buyFrom, sellTo);
apples.add(apple);
});
}
@Override
public List<Apple> findAllApple() {
return apples;
}
}
package org.wesome.graphql;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GraphqlProjectApplication {
public static void main(String[] args) {
SpringApplication.run(GraphqlProjectApplication.class, args);
}
}\src\main\resources\graphql\schema.graphqls
# Apple Object
type Apple{
# primary key of apple
appleId:ID!
# apple Name
appleName:String
# apple Taste
taste:String
# available
available:Boolean
# Buy Apple From Vendor
buyFrom: Vendor
# Sell Apple To Vendor
sellTo: Vendor
}
# Vendor Object
type Vendor{
# primary key of Vendor
id:ID!
# vendor Name
name:String
# available
available:Boolean
# location
location:String
}
# Apple Query
type Query{
# query to get all apples
findAllApple:[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.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>GraphiQL
GraphQL provides an inbuild UserInterface GraphiQL, which can be accessed via http://localhost:8080/graphiql or access GraphQL via Postman, in the query section add the below query
query FindAllApple {
findAllApple {
appleId
appleName
taste
available
sellTo {
id
name
available
location
}
buyFrom {
id
name
available
location
}
}
}
The Vendor Object is used twice, For GraphQL Fragment, can combine both, as below query
query FindAllApple {
findAllApple {
appleId
appleName
taste
available
buyFrom {
...AppleFragment
}
sellTo {
...AppleFragment
}
}
}
fragment AppleFragment on Vendor {
id
name
available
location
}