Spring Boot GraphQL Schema Interface

SpringBoot GraphQL Schema Interface are Abstract Types that just defines the Generics Schema without implementations, a concrete class will provide all the Implementations. GraphQL also provides an Abstract Type Interface, which defines all the fields and is implemented by Concrete Types.

GraphQL Interface Type can be extended by other Interface Types or implemented by Object Type.

All the implementing Types must contain the same files defined by the Interface Type and further provide additional fields as per requirements. 

package org.wesome.graphql.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
import org.wesome.graphql.entity.Apple;
import org.wesome.graphql.entity.AppleVO;
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();
    }

    @MutationMapping("addApple")
    Apple addApple(@Argument AppleVO appleVO) {
        return appleService.addApple(appleVO);
    }
}
package org.wesome.graphql.entity;

public interface Apple {
    public int getAppleId();

    public String getAppleName();

    public Boolean getAvailable();
}
package org.wesome.graphql.entity;

public enum AppleEnum {
    MACINTOSH, FUJI
}
package org.wesome.graphql.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode
@AllArgsConstructor
public final class AppleVO {
    private String appleName;
    private Boolean available;
    private AppleEnum appleType;
}
package org.wesome.graphql.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode
@AllArgsConstructor
public final class Fuji implements Apple {
    private int appleId;
    private String appleName;
    private Boolean available;
}
package org.wesome.graphql.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode
@AllArgsConstructor
public final class Macintosh implements Apple {
    private int appleId;
    private String appleName;
    private Boolean available;
}
package org.wesome.graphql.service;

import org.wesome.graphql.entity.Apple;
import org.wesome.graphql.entity.AppleVO;

import java.util.List;

public interface AppleService {
    List<Apple> findAllApple();

    Apple addApple(AppleVO appleVO);
}
package org.wesome.graphql.service;

import org.springframework.stereotype.Service;
import org.wesome.graphql.entity.Apple;
import org.wesome.graphql.entity.AppleEnum;
import org.wesome.graphql.entity.AppleVO;
import org.wesome.graphql.entity.Fuji;
import org.wesome.graphql.entity.Macintosh;

import java.util.ArrayList;
import java.util.List;

@Service
public class AppleServiceImpl implements AppleService {
    private static final List<Apple> apples = new ArrayList<>(List.of(new Macintosh(1, "Macintosh A", true), new Macintosh(2, "Macintosh B", false), new Fuji(3, "Fuji A", true), new Fuji(4, "Fuji B", false)));

    @Override
    public List<Apple> findAllApple() {
        return apples;
    }

    @Override
    public Apple addApple(AppleVO appleVO) {
        Apple apple = null;
        if (appleVO.getAppleType() == AppleEnum.FUJI) {
            apple = new Fuji(apples.size() + 1, appleVO.getAppleName(), appleVO.getAvailable());
        } else if (appleVO.getAppleType() == AppleEnum.MACINTOSH) {
            apple = new Macintosh(apples.size() + 1, appleVO.getAppleName(), appleVO.getAvailable());
        }
        apples.add(apple);
        return apple;
    }
}
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 Enumeration
enum AppleEnum {
    MACINTOSH, FUJI
}

# Fruit Interface
interface Apple{
    # primary key of apple
    appleId:ID!
}

# Apple Object
type Macintosh implements Apple{
    # primary key of apple
    appleId:ID!
    # available Boolean
    available:Boolean
    # apple Name
    appleName:String
}

# Apple Object
type Fuji implements Apple{
    # primary key of apple
    appleId:ID!
    # available Boolean
    available:Boolean
    # apple Name
    appleName:String
}

# Apple Input Object
input AppleVO{
    #    # primary key of apple
    #    appleId:ID!
    # available Boolean
    available:Boolean
    # apple Name
    appleName:String
    # apple Name Enumeration
    appleType:AppleEnum
}

# Apple Query
type Query{
    # query to get all apples
    findAllApple:[Apple]!
}

# Apple Mutation
type Mutation{
    # mutation to add an apple
    addApple(appleVO:AppleVO):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>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </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
        __typename
        ... on Fuji {
            appleId
            available
            appleName
        }
        ... on Macintosh {
            appleId
            available
            appleName
        }
    }
}

For Mutation, use the below query

mutation AddApple {
    addApple(
        appleVO: {
            available: true
            appleName: "a"
            vendor: { vendorName: "Vendor A", available: false }
        }
    ) {
        appleId
        available
        appleName
        vendor {
            vendorId
            vendorName
            available
        }
    }
}

follow us on