Spring Boot GraphQL Interceptors

Interceptors are special types of components that intercept or catch requests before reaching the controller, GraphQL provides a WebGraphQlInterceptor that intercepts HTTP and WebSocket requests. GraphQL provides WebGraphQlRequest and WebGraphQlResponse classes for request and response Interceptors.

Interceptors can have multiple purposes, such as checking if some specific parameter is passed in the header or adding a request id into the response body or header, Let's see all these use cases.

package org.wesome.graphql.config;

import graphql.ExecutionResult;
import org.springframework.graphql.server.WebGraphQlInterceptor;
import org.springframework.graphql.server.WebGraphQlRequest;
import org.springframework.graphql.server.WebGraphQlResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

@Component
public class RequestIdInterceptor implements WebGraphQlInterceptor {
    @Override
    public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
        System.out.println("executing RequestIdInterceptor");
        return chain.next(request).map(response -> {
            ExecutionResult executionResult = response.getExecutionResult();
            Map<Object, Object> newExtensions = new HashMap<>();
            if (executionResult.getExtensions() != null) {
                newExtensions.putAll(executionResult.getExtensions());
            }
            newExtensions.put("request_id", request.getId());
            return response.transform(builder -> builder.extensions(newExtensions).build()
            );
        });
    }
}
package org.wesome.graphql.config;

import org.springframework.graphql.server.WebGraphQlInterceptor;
import org.springframework.graphql.server.WebGraphQlRequest;
import org.springframework.graphql.server.WebGraphQlResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
public class ResponseInterceptor implements WebGraphQlInterceptor {
    @Override
    public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
        return chain.next(request).map(response -> {
            response.getResponseHeaders().add("version", "v1");
            return response;
        });
    }
}
package org.wesome.graphql.config;

import org.springframework.graphql.server.WebGraphQlInterceptor;
import org.springframework.graphql.server.WebGraphQlRequest;
import org.springframework.graphql.server.WebGraphQlResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
public class TestingInterceptor implements WebGraphQlInterceptor {
    @Override
    public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
        System.out.println("executing TestingInterceptor");
        boolean betaFeatures = request.getHeaders().containsKey("test");
        request.configureExecutionInput((executionInput, builder) -> {
            executionInput.getGraphQLContext().put("test", betaFeatures);
            return executionInput;
        });
        return chain.next(request);
    }
}
package org.wesome.graphql.controllers;

import graphql.GraphQLContext;
import graphql.execution.ExecutionId;
import graphql.schema.DataFetchingEnvironment;
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(DataFetchingEnvironment env) {
        GraphQLContext localContext = env.getGraphQlContext();
        ExecutionId executionId = env.getExecutionId();
        System.out.println("executionId = " + executionId);
        System.out.println("testing features = " + localContext.get("test"));
        return appleService.findAllApple();
    }
}
package org.wesome.graphql.entity;

public record Apple(int appleId, String appleName, String appleTaste, String now) {
}
package org.wesome.graphql.entity;

public enum AppleTaste {
    SWEET("sweet"), TANGY("tangy"), BITTER("bitter"), SOUR("sour");
    private final String appleTaste;

    AppleTaste(String appleTaste) {
        this.appleTaste = appleTaste;
    }
}
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 java.time.LocalTime;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
public class AppleServiceImpl implements AppleService {
    private static List<Apple> apples;

    static {
        Faker faker = new Faker();
        apples = IntStream.rangeClosed(1, 10).mapToObj(value -> new Apple(value, faker.food().fruit(), AppleTaste.values()[faker.random().nextInt(0, 3)].name(), LocalTime.now().toString())).collect(Collectors.toList());
    }

    @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 AppleTaste
    appleTaste:String
    # current time
    now : String
}
# Apple Query
type Query{
    # query to get all apples
    findAllApple:[Apple]
}

\src\main\resources\application.properties

spring.graphql.graphiql.enabled=true

pom.xml

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

in the header section add below JSON

{
  "test": true
}

 

follow us on