0% found this document useful (0 votes)
342 views1 page

Ktor and GraphQL - Getting Started

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
342 views1 page

Ktor and GraphQL - Getting Started

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1

Create a free

Learn Android & Kotlin Pricing Join Chat Search Sign In account

Hide contents
Flutter Apprentice, First Edition — Now Available!
Ktor and GraphQL:
Getting Started
Start Reading
Getting Started

What Is GraphQL?

Distinguishing Between GraphQL and


REST
Home Android & Kotlin Tutorials
What Is Ktor?

Developing the Project Ktor and GraphQL:


Setting up Model Class Getting Started
Adding Built-in Data
Learn how to create a GraphQL server using Ktor
Adding Repository Pattern

Ktor Client with GraphQL By Enzo Lizama


Jan 18 2021 · Article (20 mins) · Beginner
Creating a Schema
Subscribe now to get full access to our entire catalogue of 4,000+
Learn more
Fetching Data with Queries mobile development videos and 50+ online books.
Download Materials

5/5 6 Ratings

Version

Kotlin 1.4, IntelliJ IDEA

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 ful lling 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 nishes 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.

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 de ne your backing data.
GraphQL isn’t tied to any speci c 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 de ne the kinds of objects you can request and what elds they have.
As queries come in, GraphQL validates the queries against the schema. GraphQL
then executes the validated queries. The API developer attaches each eld 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 speci cation and a set of tools that operates over a single endpoint using
HTTP. There are other differences between the two technologies:

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.

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 con gure only
the functionality your project requires.

Extensible: Extend what you need. With a con gurable 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 rst 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 de ne 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 le in models directory. Remove any Models class
created for you and replace with:

// 1 COPY
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 de nes:

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 de ne 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 le
named database.kt to store the list of players. Add the following code:

import com.raywenderlich.kgraphqlfootball.models.Player COPY


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
modi cations 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.

Adding Repository Pattern


The Repository pattern separates the data access logic and maps it to the business
entities in the business logic. The data access logic and business logic layers
communicate via interfaces. So it’s time to create the repository. First, create the
repository directory. Then, create the IPlayerRepository.kt le. Add:

import com.raywenderlich.kgraphqlfootball.data.players COPY


import com.raywenderlich.kgraphqlfootball.models.Player
import com.raywenderlich.kgraphqlfootball.models.PlayerInput
import com.raywenderlich.kgraphqlfootball.models.Position

interface IPlayerRepository {
fun createPlayer(player: Player)
fun deletePlayer(uid: String)
fun listPlayers() : List<Player>
fun filterPlayersByPosition(position: Position): List<Player>
fun filterPlayersByTeam(team: String): List<Player>
fun updatePlayer(uid: String, playerInput: PlayerInput)
}

This interface de nes the functionality of the player repository. This interface can
be reused to abstract calls to a database, or another REST API. In this project, you’ll
de ne the implementation for each method. Add the following below the interface:

class PlayerRepository : IPlayerRepository { COPY


override fun createPlayer(player: Player) {
players.add(player)
}

override fun deletePlayer(uid: String) {


players.removeIf { it.uid == uid }
}

override fun listPlayers(): List<Player> {


return players
}

override fun filterPlayersByPosition(position: Position):List<Player> {


return players.filter { it.position == position }
}

override fun filterPlayersByTeam(team: String): List<Player> {


return players.filter { it.team == team }
}

override fun updatePlayer(uid: String, playerInput: PlayerInput) {


players.find { it.uid == uid }?.apply {
name = playerInput.name
position = playerInput.position
team = playerInput.team
}
}
}

For now, you’re working with built-in data from the list of players. So the operations
you’re going to implement are going to be from this local list. You now have all the
classes needed to expose your data with GraphQL. Well done!

Ktor Client with GraphQL


With the object model and the interface to the model complete, you’ll turn your
focus on wrapping the interface for GraphQL. Speci cally, you’ll be using KGraphQL
to wrap your interface. KGraphQL is a Kotlin implementation of GraphQL. It
provides a rich DSL to set up the GraphQL schema. You’ll start by de ning the
schema.

Creating a Schema
Your GraphQL server uses a schema to describe the shape of your data graph. This
schema de nes a hierarchy of types with elds that populate from your back-end
data stores. The schema also speci es exactly which queries and mutations are
available for clients to execute against your data graph. Start by creating the
SchemaGraphQL.kt le in the src directory and add:

import com.apurebase.kgraphql.schema.dsl.SchemaBuilder COPY


import com.raywenderlich.kgraphqlfootball.models.Player
import com.raywenderlich.kgraphqlfootball.models.PlayerInput
import com.raywenderlich.kgraphqlfootball.models.Position
import com.raywenderlich.kgraphqlfootball.respository.IPlayerRepository
import com.raywenderlich.kgraphqlfootball.respository.PlayerRepository

fun SchemaBuilder.schemaValue() {
// 1
val repository: IPlayerRepository = PlayerRepository()

// TODO: Queries and mutations will go here ...

// 2
inputType<PlayerInput>{
description = "The input of the player without the identifier"
}
// 3
type<Player>{
description = "Player object with the attributes name, team, position and
identifier"
}
// 4
enum<Position>()
}

In the code above, you have to de ne two steps:

1. De ne the repository for players that you implemented in the previous section.

2. The inputType works as a object type for input data models on the GraphQL
schema.

3. Registers the Kotlin data classes with the type method to include it in the
created schema type system.
4. Registers the Kotlin enum with the enum method to include it in the created
schema type system.

If you restart your server in IntelliJ, and refresh your browser, you should notice a
Schema tab to the far right. If you click on it, you should see your models described
in the panel shown. You can see it in the screenshot below:

You’ll notice that any description you ll when describing your model is also shown
here. This can be useful for developers who might use your interface to better
understand the models provided by your endpoint.

With the data types de ned in the schema, the next step will be to add your rst
query.

Fetching Data with Queries


A GraphQL query simply reads or fetches values from your datastore. These queries
help reduce over-fetching of data. Unlike a REST API, GraphQL allows a user to
select which elds to fetch from the server. This means smaller queries and less
traf c over the network, reducing the response time.

You’ll start by adding a method to query all players by a given position. Add the
following inside the SchemaBuilder.schemaValue() function:

// 1 COPY
query("playersByPosition") {
// 2
description = "Retrieve all the players by his position"
// 3
resolver { position: Position ->
try {
// 4
repository.filterPlayersByPosition(position)
} catch (e: Exception) {
emptyList<Player>()
}
}
}

The above code breaks down as follows:

1. De ne a query with a unique name and add a description for the resolver.

2. Give the method a useful description so developers better understand its usage.

3. Use a resolver accepting a position and returning a list of Player s. Notice that
you’ll call the filterPlayersByPosition you added to the IPlayerRepository
interface.

In GraphQL every property needs a resolver. The resolver is the piece of system
logic, required to resolve the response graph. Since you de ned Position enum
type, you’re able to accept it as part of the resolver. The nal step is to setup the
schema when the application is launched.

Open up Application.kt and replace the “Hello, world” query with:

schema { schemaValue() } COPY

Now, run the application and, on the webpage, tap the Schema tab. You’ll see the
following result:

To test the implementation, try to run the playerByPosition query. In the Query
section, add:

query fetchPlayerByPosition($position: Position!){ COPY


playersByPosition(position: $position){
uid
name
position
team
}
}

Click the Query variables tab and put the following code that represents the object
in the argument eld. Here, you’re choosing to search for players who are
mid elders.

{ COPY
"position": "MID"
}

Click the middle Play button. When you execute this, you should see the following
result from the playground:

To esh out the API, add the following players and playersByTeam queries to retrieve
a list of all players, and players by team respectively.

query("players") { COPY
description = "Retrieve all players"
resolver { ->
try {
repository.listPlayers()
} catch (e: Exception) {
emptyList<Player>()
}
}
}

query("playersByTeam") {
description = "Retrieve all the players by his team"
resolver { team: String ->
try {
repository.filterPlayersByTeam(team)
} catch (e: Exception) {
emptyList<Player>()
}
}
}

Notice how the the players doesn’t require any arguments, where as playersByTeam
expects a team name as a string.

With queries complete, you can now add the ability to modify or mutate objects
using GraphQL. You’ll do that in the next section.

Writing Data with Mutations


In REST, any requests made may cause side-effects on the server. But by convention,
it’s recommended to not use GET requests to modify data. GraphQL is similar — any
query should not do a data write. However, it’s useful to establish a convention that
any operations that cause a write operation should be sent via a mutation.

You’ll rst add a mutation to allow creating new players. Add a createPlayer
mutation to the SchemaBuilder.schemaValue() function:

// 1 COPY
mutation("createPlayer") {
// 2
description = "Create a new player"
// 3
resolver { playerInput: PlayerInput ->
try {
// 4
val uid = java.util.UUID.randomUUID().toString()
val player = Player(uid, playerInput.name, playerInput.team,
playerInput.position)
repository.createPlayer(player)
true
} catch (e: Exception) {
false
}
}
}

The above code breaks down as follows:

1. Create a mutation with a unique name.

2. Give the method a description to help developers better understand the method.

3. Use a resolver accepting a PlayerInput . Recall that you de ned this class earlier
with the schema, so it can be used a typed input.
4. Create the Player object, and store it in the list.

As with queries, you’ll call the respective repository methods for each resolver that
you create. In this case, that means actions that’ll affect the result of the data. After
implementing the code above and re-running the project again, you’ll see this:

In order to test the createPlayer mutation, replace the query with:

mutation createNewPlayer($playerInput: PlayerInput!){ COPY


createPlayer(playerInput:$playerInput)
}

Inside the Query variables, put the following code that represents the object in the
argument eld:

{ COPY
"playerInput": {
"name": "Test player",
"position": "DEF",
"team": "Barcelona"
}
}

When you execute this, expect the following result from the playground:

Congratulations! You’ve successfully created a GraphQL API! If you want to


challenge yourself, try to query your API to retrieve the list of players after creating a
new one. Similarly, checkout the completed project for implementations of
deletePlayer and updatePlayer to see how to delete and update a player respectively.

Where to Go From Here?


You can download the completed project les by clicking the Download Materials
button at the top or bottom of the tutorial.

You’ve just learned how to create a GraphQL application using Ktor and KGraphQL!
Although you’ve scratched the surface, there are many areas of either Ktor, or
KGraphQL you might want to explore.

Understand how to pass Context to each request.

How to add server-side authorization and authentication.

How to deploy your Ktor application.

To learn more about GraphQL, go to: https://graphql.org/

We hope you enjoyed this tutorial. If you have any questions, please join the
discussion below.

Getting Started Tools & Libraries Android & Kotlin Tutorials

Download Materials Mark Complete

raywenderlich.com Weekly

The raywenderlich.com newsletter is the easiest way to stay up-to-date on


everything you need to know as a mobile developer.

stevewozniak@apple.com Sign up now

Get a weekly digest of our tutorials and courses, and receive a free in-depth email course as a
bonus!

Average Rating Add a rating for this content 6 ratings

5 /5 Sign in to add a rating

All videos. All books.


One low price.
The mobile development world moves
quickly — and you don’t want to get left
behind. Learn iOS, Swift, Android,
Kotlin, Dart, Flutter and more with the
largest and highest-quality catalog of
video courses and books on the
internet.

Learn more

More like this

Gradle Plugin Tutorial for Android: Getting NEW

Started
Learn how to create a Gradle plugin within your existing Android app, or as
a standalone project that you can publish and use in any Android project.
Jun 7 2021 · Article (25 mins)

SOLID Principles for iOS Apps NEW

SOLID is a group of principles that lead you to write clear and organized
code without additional effort. Learn how to apply it to your SwiftUI iOS
apps.

Jun 7 2021 · Article (40 mins)

Open Call for Tech Editors and Authors on the NEW


Server-Side Swift Team
We’re looking for Server-Side Swift developers to join the team. Read on
for how to apply!
Jun 4 2021 · Article (5 mins)

Announcing Flutter Apprentice, First Edition! NEW


Everything you need to get started with Flutter—Widgets, UI, Navigation,
Networking, Persistence, State Management, and Deployment. You name it.
Our new Flutter Apprentice book has it!
Jun 2 2021 · Article (10 mins)

Contributors

Enzo Lizama Kevin D Moore


Enzo is a software engineer passionate I really enjoy developing Android and
about mobile development topics, in iOS applications and in my spare time
beta version because is always finding create apps that I freely share. I have
ways to... been...

AUTHOR TECH EDITOR

John Hagemann Adriana Kutenko


John is a writer, editor, and instructor Graphic Illustrator with a Bachelor’s
who is always looking for ways to plain Degree in Fine Arts. I am a perpetual
talk the world around him. perfection seeker with a big passion for
History...
EDITOR
ILLUSTRATOR

Vijay Sharma Eric Soto


Vijay is a husband, father and senior Eric is Android Tutorial Team Lead and
mobile engineer. Based out of Canada's a Professional Software Engineer and
capital, Vijay has worked on dozens of certified Agile-Scrum Master focusing
apps for... on Apple iOS...

FPE TEAM LEAD

Comments

Show Comments.

All videos. All books.


One low price.
A raywenderlich.com subscription is the best way to
learn and master mobile development — plans start
at just $19.99/month!

Learn iOS, Swift, Android, Kotlin, Flutter and Dart


development and unlock our massive catalog of 50+
books and 4,000+ videos.

Learn more

Places Company Community All videos. All books. One low price.

iOS & Swift About Join RW Chat A raywenderlich.com subscription is the best way to
The largest and most up-to-date learn and master mobile development — plans start at
collection of courses and books on Android & Kotlin Terms & Conditions Mobile App just $19.99/month!
iOS, Swift, Android, Kotlin, Flutter,
Flutter Privacy Policy Podcast Learn iOS, Swift, Android, Kotlin, Flutter and Dart
Dart, Server-Side Swift, Unity and
more! development and unlock our massive catalogue of 50+
Server-Side Swift Forums
books and 4,000+ videos.
Support
Unity Newsletter
Learn more
Library Help Free Books for Meetups
FAQ

Contact Us

© 2021 Razeware LLC Made with ♥ from around the world 6000+ Tutorials and counting

You might also like