Ktor and GraphQL: Getting Started

Learn how to create a GraphQL server using Ktor By Enzo Lizama.

Leave a rating/review
Download materials
Save for later
Share

Ktor is a framework for easily building connected applications — mobile, web, browser and desktop apps. Ktor applications are written in Kotlin and give developers the ability to quickly build asynchronous web applications.

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, giving clients the power to ask for exactly what they need and nothing more.

In this tutorial, you’ll focus on:

  • Using Ktor to create a GraphQL API using the KGraphQL library.
  • Using KGraphQL rich DSL to set up the GraphQL schemas.
  • Executing basic operations (queries and mutations) around built-in data.

You’ll learn more about GraphQL by creating a project named RWFootballPlayersGraphQL, which will serve information about soccer players through a GraphQL interface.

Getting Started

Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.

You’ll need IntelliJ IDEA with the Ktor plugin installed. Then, open the starter project and wait until the IDE finishes loading the project dependencies and indexing the project. Now, you have a fully functional GraphQL server.

Start your server by pressing the green play icon beside the main function. Test to make sure your server is running by going to localhost:8080/graphql. You should see the following page in your browser.

Start project — Playground

With your server up and running, next you’ll dive into what exactly is GraphQL.

What Is GraphQL?

GraphQL is a query language for your API and a server-side runtime for handling queries. Think of GraphQL as a facade around your existing API or database. GraphQL also leverages the use of a type system to define your backing data. GraphQL isn’t tied to any specific database or storage engine. Instead, it is backed by your existing code and data.

API developers use GraphQL to create a schema to describe all the possible data that clients can query through that service. A GraphQL schema consists of object types, which define the kinds of objects you can request and what fields they have. As queries come in, GraphQL validates the queries against the schema. GraphQL then executes the validated queries. The API developer attaches each field in a schema to a function called a resolver. During execution, the resolver is called to produce the value. You’ll create a resolver later in this tutorial.

Distinguishing Between GraphQL and REST

The main difference between GraphQL and REST is that REST is an architectural concept for network-based software. GraphQL, on the other hand, is a query language, a specification and a set of tools that operates over a single endpoint using HTTP. There are other differences between the two technologies:

Table showing differences between GraphQL and REST

But they have similarities as well. Both provide information to front-end clients in JSON and have ways to identify if an operation is going to read or write data. Both also end up calling functions on the server to perform different kinds of requests. The following diagram from the ApolloGraphQL blog summarizes the difference.

Rest VS GraphQL

Where REST tends to have multiple endpoints, GraphQL has a single endpoint.

What Is Ktor?

Ktor is an asynchronous framework for quickly creating web applications in Kotlin with minimal effort. You can develop microservices, web applications and more. Ktor describes itself as fun, free and open source.

Some of the more remarkable reasons to develop with Ktor include that it is:

  • Lightweight: Use what you need. Ktor allows you to transparently configure only the functionality your project requires.
  • Extensible: Extend what you need. With a configurable pipeline, you can create the extensions you need and place them anywhere you want.
  • Multiplatform: Run it where you need it. Built from the ground up with Kotlin Multiplatform technology, you can deploy Ktor applications anywhere.
  • Asynchronous: Scale as you need it. Using Kotlin coroutines, Ktor is truly asynchronous and highly scalable.

For this tutorial, you’ll work with Ktor as your server-side framework to build this project.

Developing the Project

GraphQL has the ability to interface with all sorts of data sources, including databases, REST endpoints, etc… However, to manage the scope of this tutorial, you’ll work with data stored in memory. After you’ve opened up the starter project in your IDE, the first step is to set up the object model class before exposing the GraphQL models.

Setting up Model Class

Before creating a GraphQL schema, it’s necessary to define the object model that will be exposed by the service. Start by creating a models folder in the src directory. Then, create the model.kt file in models directory. Remove any Models class created for you and replace with:

// 1
enum class Position {
  GK, // Goalkeeper
  DEF, // Defender
  MID, // Midfielder
  FRW  // Forward
}

// 2
data class Player(var uid: String, var name: String, var team: String, var position: Position)

// 3
data class PlayerInput(val name: String, val team: String, val position: Position)

Here’s what the above code defines:

  1. The Position enum class describes the different positions for a player.
  2. The Player data class provides the attributes for the model.
  3. The PlayerInput is the model that you’re going to send when you want to operate with the data source.

Adding Built-in Data

After you define the object model, it’s time to create the built-in data that simulates a database. Create a folder named data in the src directory. Then, create a file named database.kt to store the list of players. Add the following code:

import com.raywenderlich.kgraphqlfootball.models.Player
import com.raywenderlich.kgraphqlfootball.models.Position
    
val players = mutableListOf(
  Player("abc123", "Sergio Ramos", "Real Madrid", Position.DEF),
  Player("abc124", "Lionel Messi", "Barcelona", Position.FRW),
  Player("abc125", "Cristiano Ronaldo", "Juventus", Position.FRW),
  Player("abc126", "Leon Goretzka", "Bayern Munich", Position.MID),
  Player("abc127", "Manuel Neuer", "Bayern Munich", Position.GK),
  Player("abc128", "Neymar Jr", "PSG", Position.FRW),
  Player("abc129", "Casemiro", "Real Madrid", Position.MID)
)

Notice that you’re creating a mutable list of Players. This is so you can make modifications through GraphQL calls in a later section.

With the data created, you’ll turn your focus on wrapping an interface around the data to facilitate reading/writing to/from the list. To do this, you’ll make use of the Repository pattern.