EXPEDIA GROUP TECHNOLOGY — SOFTWARE
Creating a Reactive GraphQL Server with Spring Boot and Kotlin
Learn how to create a reactive GraphQL server in a few easy steps
Spring Boot simplifies the application development process by providing a number of opinionated auto-configuration libraries that allow you to create applications with minimal setup. Let’s visualise that principle with a sample web service. Using Spring Initializr, it is trivial to create a new web app that we can modify to expose REST endpoints by simply creating a controller with a target function.
Creating a similar helloWorld query and exposing it in a GraphQL web server is not as straightforward and requires additional steps. First, we need to create a schema, then we need to create a GraphQL runtime environment and finally create a controller to process the incoming GraphQL requests. This results in a lot of boilerplate code that needs to be copied over for each new GraphQL service.
graphql-kotlin-spring-server is a Spring Boot auto-configuration library that automatically configures all the necessary beans to start up a reactive GraphQL web server and relies on graphql-kotlin-schema-generator to generate the underlying schemas directly from your source code. It applies Spring Boot’s auto-configuration principles to GraphQL servers.
Creating a GraphQL server
The simplest way to create a new Kotlin Spring Boot app is by generating one using Spring Initializr.
Once you get the sample application setup locally, you will need to add graphql-kotlin-spring-server dependency to your pom.xml
file:
<dependency>
<groupId>com.expediagroup</groupId>
<artifactId>graphql-kotlin-spring-server</artifactId>
<version>${graphql-kotlin.version}</version>
</dependency>
Next, since we will be relying on reflections to generate our schema, we also need to specify a list of supported packages that can be scanned for exposing your schema objects through reflections. Modify your application.properties
configuration file by adding the following:
graphql.packages=com.example.graphql
With the above steps completed, we can start creating our schema. In order to expose your queries, mutations and/or subscriptions in the GraphQL schema you simply implement the corresponding marker interface. Once those objects are exposed as Spring beans they will be automatically picked up by graphql-kotlin-spring-server auto-configuration library. See my previous post for more details about the GraphQL schema generator and how to generate the GraphQL schema from your source code.
Given the example above, when you run your GraphqlApplication
it will start up with the following GraphQL schema:
Your newly created GraphQL server will start up at http://localhost:8080 with the following routes preconfigured:
- /graphql — GraphQL server endpoint used for processing queries and mutations
- /sdl — convenience endpoint that returns current schema in Schema Definition Language format
- /playground — Prisma Labs GraphQL Playground IDE endpoint
Customizing the server
All the beans necessary to start a reactive GraphQL web server are automatically created by graphql-kotlin-spring-server. Many of those beans are conditionally created and their default behavior can be overwritten by providing custom beans in your application context. See our documentation for more details.
graphql-kotlin-spring-server also exposes a number of configuration properties that can be used to customize your server endpoints. For a complete list of currently supported properties please refer to our documentation.
Contextual Data
graphql-kotlin-spring-server provides a simple mechanism to build GraphQL context per query execution through GraphQLContextFactory. Once a context factory bean is available in the Spring application context it will then be used in a corresponding ContextWebFilter to populate the GraphQL context based on the incoming request and make it available during query execution.
For example, if we define our custom context as follows:
We can generate corresponding GraphQLContextFactory
bean:
Once your application is configured to build your custom MyGraphQLContext
, we can then specify it as function argument by annotating it with @GraphQLContext
. While executing the query, the corresponding GraphQL context will be read from the environment and automatically injected to the function input arguments.
The above query would produce the following GraphQL schema:
Notice that the @GraphQLContext
annotated argument is not reflected in the generated GraphQL schema.
Apollo Federation
Apollo Federation is supported out of the box by graphql-kotlin-spring-server. This feature is enabled by specifying thegraphql.federation.enabled=true
property in your application configuration and then creating a federated schema.
Since not all federated types might be accessible through the traditional query path, we also need to provide some additional hints, i.e. custom directives, to help identify them during the schema generation process as well as instrument the behavior of the federated graph. For example, given a simpleProduct
type exposed in other parts of the graph as:
We can extend it in our new service with a new reviews
field as follows:
Since the new reviews
field is not accessible through the regular query, we also need to provide a mechanism to instantiate a Product
type when processing federated requests — we need to provide corresponding FederatedTypeResolver and register it in our FederatedTypeRegistry.
Further Reading
GraphQL Kotlin Spring Server aims to simplify the process of creating a reactive GraphQL server. This library is built on top of Spring Boot and utilizes GraphQL Kotlin Schema Generator for automatically generating GraphQL schemas directly from your source code. The end result is a library that allows you to run GraphQL server with minimal setup and provides out of the box support for processing GraphQL Queries, Mutations and Subscriptions. For additional details on how to use the library please check out the examples and the documentation available on the GitHub pages.
We are also open for feedback so please raise an issue and start a discussion for any new features you would like to see!
- https://medium.com/expedia-group-tech/creating-graphql-schemas-in-kotlin-aaaac0ab0672
- https://medium.com/expedia-group-tech/apollo-federation-in-a-graphql-kotlin-server-115cea51607a
- https://expediagroup.github.io/graphql-kotlin/
- https://spring.io/projects/spring-boot
Photo by Jack Anstey on Unsplash