A powerful Java library for aggregating and executing GraphQL operations from multiple microservices using a single unified schema.
graphql-orchestrator-java simplifies the process of accessing data from various GraphQL microservices by providing a unified GraphQL schema. This enables you to query multiple microservices through a single endpoint, reducing complexity and improving performance.
The library supports two strategies to aggregate and combine the schemas from multiple microservices
- Schema Stitching with a recursive strategy
- Apollo Federation Style Schema Composition. (_Currently, it supports
@key, @requires, @extends, and @external
directives)
At query execution time, it orchestrates the GraphQL queries to the appropriate micro-services, using the popular graphql-java library as the execution engine.
- Apollo Federation Style Schema Composition
- Recursive Stitching
- Query Batching
- Type Conflict Resolution Strategy
- Pluggable
graphql-java
Instrumentation
<dependency>
<groupId>com.intuit.graphql</groupId>
<artifactId>graphql-orchestrator-java</artifactId>
<version>${graphql.orchestrator.version}</version>
</dependency>
- Implement the ServiceProvider interface. You will need a new instance for each GraphQL Service.
Consider the following 2 service providers below
class PersonNameService implements ServiceProvider {
public static final String schema =
"type Query { person: Person } "
+ "type Person { firstName : String lastName: String }";
@Override
public String getNameSpace() { return "PERSON_NAME"; }
@Override
public Map<String, String> sdlFiles() { return ImmutableMap.of("schema.graphqls", schema); }
@Override
public CompletableFuture<Map<String, Object>> query(final ExecutionInput executionInput,
final GraphQLContext context) {
//{'data':{'person':{'firstName':'GraphQL Orchestrator', 'lastName': 'Java'}}}"
Map<String, Object> data = ImmutableMap
.of("data", ImmutableMap.of("person", ImmutableMap.of("firstName", "GraphQL Orchestrator", "lastName", "Java")));
return CompletableFuture.completedFuture(data);
}
}
class PersonAddressService implements ServiceProvider {
public static final String schema =
"type Query { person: Person }"
+ "type Person { address : Address }"
+ "type Address { city: String state: String zip: String}";
@Override
public String getNameSpace() { return "PERSON_ADDRESS";}
@Override
public Map<String, String> sdlFiles() { return ImmutableMap.of("schema.graphqls", schema);}
@Override
public CompletableFuture<Map<String, Object>> query(final ExecutionInput executionInput,
final GraphQLContext context) {
//{'data':{'person':{'address':{ 'city' 'San Diego', 'state': 'CA', 'zip': '92129' }}}}"
Map<String, Object> data = ImmutableMap
.of("data", ImmutableMap.of("person", ImmutableMap.of("address", ImmutableMap.of("city","San Diego", "state","CA", "zip","92129"))));
return CompletableFuture.completedFuture(data);
}
}
- Create an instance of Orchestrator and execute the query as below.
// create a runtimeGraph by stitching service providers
RuntimeGraph runtimeGraph = SchemaStitcher.newBuilder()
.service(new PersonNameService())
.service(new PersonAddressService())
.build()
.stitchGraph();
// pass the runtime graph to GraphQLOrchestrator
GraphQLOrchestrator graphQLOrchestrator = GraphQLOrchestrator.newOrchestrator()
.runtimeGraph(runtimeGraph).build();
//Execute the query
CompletableFuture<ExecutionResult> execute = graphQLOrchestrator
.execute(
ExecutionInput.newExecutionInput()
.query("query {person {firstName lastName address {city state zip}}}")
.build()
);
ExecutionResult executionResult = execute.get();
System.out.println(executionResult.getData().toString());
// Output:
// {person={firstName=GraphQL Orchestrator, lastName=Java, address={city=San Diego, state=CA, zip=92129}}}
The Orchestrator uses a recursive algorithm to combine the schemas from multiple services and generate the following unified schema.
type Query {
person: Person
}
type Person {
firstName: String
lastName: String
address: Address
}
type Address {
city: String
state: String
zip: String
}
Graph Quilt Gateway is a SpringBoot application that uses the graphql-orchestrator-java.
Detailed Documentation can be found here
If you are interested in contributing to this project, please read the CONTRIBUTING.md file for details on our code of conduct, and the process for submitting pull requests to us.
This project is licensed under the MIT License - see the LICENSE file for details.
- Thanks to the contributors of the graphql-java library.
- Thanks to the contributors of this project for their hard work and dedication.