Building GraphQL Gateway With Springboot Framework
This article shows the development of a simple GraphQL gateway in Java using Springboot framework to expose Rest services as GraphQL to simplify the access to resources from the frontend.
GraphQL
GraphQL is a query language for APIs defined by Facebook to solve some issues of traditional REST APIs as flexibility and simplicity.
All the resources of the API are exposed in a single request — normally a POST to /graphql — and the content is a query using GraphQL specification. The query specifies the filter and the data to be returned by the API.
In addition to queries, GraphQL provides Mutation for requests of creation, update and delete resources and Subscription for realtime queries.
Architecture of the solution
In microservices architectures it is mainly used REST to expose resources and API Gateways to consolidate them to be consumed from the frontend
The usage of GraphQL in the frontend means to change the protocol on the microservices to expose GraphQL, to avoid it we will create a Gateway to map REST definitions — Swagger spec. — to GraphQL
The below image shows the architecture of the solution proposed:
Rest services are registered in the Gateway, the Gateway maps the service with GraphQL type and resolves the queries with the corresponding Rest service.
The solution is composed by the following pieces:
graphql-registry to register Rest services in the GraphQL gateway — it works as as a service discovery -
graphql-schema maps the Swagger spec. of the Rest service to GraphQL
graphql-resolver resolves GraphQL queries with the corresponding rest service.
graphql-server exposes the /graphql endpoint
How it works
Registration of services
- The rest-service requests to graphql-registry the registration in the gateway
- graphql-registry calls to graphql-schema to add the rest-service to the GraphQL schema
- graphql-schema requests to the rest-service the Swagger spec. and maps it with GraphQL spec.
Solving queries
- front-end requests a query to the graphql-server
- graphql-server uses graphql-schema to solve the query with requests to the corresponding rest-service
Mapping Rest/Swagger to GraphQL
The main part of the gateway is the mapping of Swagger with GraphQL
Table below shows the mapping between the elements of Swagger and GraphQL
Procedure used to map Swagger paths with GraphQL query fields:
Implementation
Stack of development
Java as programming language.
Springboot as framework.
graphql-java as implementation of GraphQL for java
maven for dependency management
Springboot project
graphql-gateway-server is the boot module that exposes /graphql endpoint for queries and /registry to register rest services
graphql-server implements /graphql endpoint and executes GraphQL requests
graphql-schema implements the mapping of Swagger specs. with GraphQL
graphql-registry implements /registry endpoint to register, unregister and list rest services in the gateway
Register service rest-countries-service with swagger url http://localhost:8082/v2/api-docs
curl POST 'http://localhost:8080/registry' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "rest-countries-service",
"url": "http://localhost:8082/v2/api-docs"
}'Unregister service rest-countries-service
curl DELETE 'http://localhost:8080/registry?service=rest-countries-service'Lists registered services
curl GET 'http://localhost:8080/registry'
graphql-registry-client implements the annotation GraphQLRegistryService to register rest services during startup.
For more details please check the README and code in https://github.com/joaquin-alfaro/graphql-gateway
Usage
Setup of rest services
- Adds dependency with graphql-registry-client
<dependency>
<groupId>org.formentor</groupId>
<artifactId>graphql-registry-client</artifactId>
<version>${graphql-gateway.version}</version>
</dependency>
2. Annotate the springboot main class with GraphQLRegistryService to register the service during startup
@SpringBootApplication
@GraphQLRegistryService
public class BooksApplication {
public static void main(String[] args) {
SpringApplication.run(BooksApplication.class, args);
}
}
3. Configure the host of the graphql-gateway-server in application.yaml
graphql:
registry:
uri: http://localhost:8080
Start GraphQL gateway
java -jar graphql-gateway-server/target/graphql-gateway.jar
Example
The project in https://github.com/joaquin-alfaro/graphql-gateway includes two Springboot samples to test graphql-gateway
rest-books-services that includes the operations GET /books and /books/{id}
rest-countries-services that includes the operations GET /countries and /countries/{id}
- Build the project
mvn clean package
2. Start graphql-gateway-server in port 8080
java -jar graphql-gateway-server/target/graphql-gateway.jar
3. Start rest-countries-services in port 8082
java -jar rest-countries-service/target/*.jar
List registered services calling http://localhost:8080/registry and check that rest-countries-service appears
4. Launch queries to GraphQL gateway in http://localhost:8080/graphql
query {
countries {
iso
name
cities {
name
id
}
}
}
Resources and references
Repository in github
https://github.com/joaquin-alfaro/graphql-gateway
graphql-java
GraphQL Playground