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

Dariusz Kuc
Expedia Group Technology

--

Photo by Jack Anstey on Unsplash

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.

https://start.spring.io/

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
  • /playgroundPrisma Labs GraphQL Playground IDE endpoint
Prisma Labs Playground

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.

Please refer to my previous post for additional details about how to generate federated GraphQL schemas using graphql-kotlin-federation library.

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!

Photo by Jack Anstey on Unsplash

--

--