Spring Boot GraphQL with HTTPS

GraphQL is a query and manipulation language tool for APIs and is agnostic of underlying server architectureSpring Boot supports HTTP and HTTPS protocols. Spring Boot GraphQL with HTTPS protocol provides an additional encryption layer to secure the data transfer and secure the communication between server and client.

HTTPS (Hypertext Transfer Protocol Secure) is a combination of basic HTTP (Hypertext Transfer Protocol) with the SSL/TLS (Secure Socket Layer/Transport Layer Security) protocol. Sometimes API requires sending sensitive data such as login credentials, bank details, credit card details, etc.

How to create a SSL Certificate

Java provides keytool in jdk\bin folder, execute the below command.

keytool -genkeypair -dname "cn=wesome, ou=wesome, o=wesome.org, c=India" -alias wesome -storetype PKCS12 -keyalg RSA -keypass wesome -keysize 2048 -keystore keystore.p12 -storepass wesome -validity 3650

it will create a keystore.p12 file, copy the file, and paste it into the root directory of the project.

Let's see an example of Spring Boot GraphQL with HTTPS

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 record AppleGraphQLController(@Autowired AppleService appleService) {
    @QueryMapping("findAllApple")
    List<Apple> findAllApple() {
        return appleService.findAllApple();
    }
}
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.service;

import org.wesome.graphql.entity.Apple;

import java.util.List;

public interface AppleService {
    List<Apple> findAllApple();
}
package org.wesome.graphql.service;

import org.springframework.stereotype.Service;
import org.wesome.graphql.data.AppleType;
import org.wesome.graphql.entity.Apple;

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

@Service
public record AppleServiceImpl() implements AppleService {
    private static final List<Apple> apples = new ArrayList<>(List.of(new Apple(1, AppleType.MACINTOSH.name(), true, 1.1F), new Apple(2, AppleType.FUJI.name(), false, 2.2F), new Apple(3, AppleType.GALA.name(), true, 3.3F), new Apple(4, AppleType.JONAGOLD.name(), false, 4.4F)));

    @Override
    public List<Apple> findAllApple() {
        return apples;
    }
}
package org.wesome.graphql;

import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;


@SpringBootApplication
public class GraphqlProjectApplication {
    public static void main(String[] args) {
        SpringApplication.run(GraphqlProjectApplication.class, args);
    }

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
            @Override
            protected void postProcessContext(Context context) {
                SecurityConstraint securityConstraint = new SecurityConstraint();
                securityConstraint.setUserConstraint("CONFIDENTIAL");
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*");
                securityConstraint.addCollection(collection);
                context.addConstraint(securityConstraint);
            }
        };
        tomcat.addAdditionalTomcatConnectors(redirectConnector());
        return tomcat;
    }

    private Connector redirectConnector() {
        Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
        connector.setScheme("http");
        connector.setPort(8080);
        connector.setSecure(false);
        connector.setRedirectPort(8443);
        return connector;
    }
}

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

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

\src\main\resources\application.properties

spring.graphql.graphiql.enabled=true
server.port=8443
security.require-ssl=true
server.ssl.key-store=keystore.p12
server.ssl.key-store-password=wesome
server.ssl.key-store-type=PKCS12
server.ssl.keyAlias=wesome
<?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>

how to access Rest API

cURL

cURL command is very useful for checking the API endpoint. The rest endpoint can be accessed via curl localhost:8080/findAllApple

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 'http://localhost:8080/graphql' \
--header 'Content-Type: application/json' \
--data '{"query":"query FindAllApple {\r\n    findAllApple {\r\n        appleId\r\n        appleName\r\n        taste\r\n    }\r\n}","variables":{}}'

GraphiQL

GraphQL provides an inbuild UserInterface GraphiQL, which can be accessed via http://localhost:8080/graphiql, since it is HTTPS protocol, the browser will automatically redirect to https://localhost:8443/graphiql?path=/graphql in the query section add the below query

query FindAllApple {
  findAllApple {
    appleId
    appleName
    available
    price
  }
}

Postman Post Method

GraphQL can be accessed via Postman as well, open Postman-> file-> import and paste the below curl

curl --location --request POST "https://localhost:8443/graphql" \
--header "Content-Type: application/json" \
--data "{\"query\":\"query FindAllApple {\n  findAllApple {\n    appleId\n    appleName\n    available\n    price\n  }\n}\",\"variables\":{}}"

Postman GraphQL Request Type

Postman provides a GraphQL request type UI, Open Postman-> file-> new->GraphQL and add the URL  https://localhost:8443/graphql in the query section add the below query

query FindAllApple {
  findAllApple {
    appleId
    appleName
    available
    price
  }
}

follow us on