Spring Boot GraphQL Fragments

Object Oriented Programming suggests reusing common objects. Sometimes Queries becomes repetitive by calling the same fields in multiple queriesSpringBoot 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 Postmanin 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
}

follow us on