Ktor is a modern, open-source, multiplatform framework developed by JetBrains for building asynchronous servers and clients applications in Kotlin. Leveraging the power of Coroutines, it offers a lightweight and flexible foundation for creating high-performance applications. While relatively new, Ktor is backed by a growing community and is seeing increasing adoption for its speed, convenience, and ease of use.
In this topic, we will focus on its capabilities for building the server-side of an application.
Project settings
When creating a Ktor project, you will encounter various settings:
Build System: You can choose your preferred build system from Gradle (with Kotlin or Groovy DSL), Maven, or the experimental Amper. The build system automates processes like compiling source code and managing dependencies. You can also opt to use a
libs.version.tomlversion catalog for Gradle and Amper projects to centralize dependency management. In this topic, we will proceed with Gradle with Kotlin DSL.Project Artifact: This defines the group and name for your project, for example,
com.example.ktor-sample. The group is typically a reversed domain name, and the artifact name is your project's identifier.Ktor Version: This is the version of Ktor you want to use. It's usually recommended to start with the latest stable version.
Engine: An engine is used to run your server. It represents the underlying request processing machinery. You can choose from Netty, Jetty, Tomcat, or CIO (Coroutine-based I/O). For now, we will stick to the default, Netty.
We will explore the differences between engines in a later topic.
Configuration: You can choose to specify server parameters (like port and host) either directly in code, or externally in a YAML or HOCON file. Using a configuration file provides more flexibility, allowing you to change settings without recompiling your application. We will use a YAML file for now.
Include Samples: If checked, the generator will create simple "Hello World" code for any plugins you add, which can be useful for understanding how they work.
Plugins: Plugins are optional building blocks that provide common functionality outside of your core application logic, such as authentication, serialization, routing, cookie support, compression, and so on.
Project creation
There are several ways to create a Ktor project. We will go through the web-based Ktor project generator, the IntelliJ IDEA Ultimate plugin, and the new Ktor CLI tool.
To create a Ktor project using the official web generator, follow the steps below:
Navigate to the Ktor Project Generator.
In the Project artifact field, enter a name for your project, for example,
com.example.hello-ktor:Click Configure to expand the project settings dropdown and adjust them if needed. For this example, match the settings below:
For this example, we don't need to add any plugins. If we did, we could simply search for one, like "serialization", and click Add:
Click the Download button. A ZIP archive containing your project will be downloaded. Unpack it into your desired project directory.
If you use IntelliJ IDEA Ultimate, you can use the integrated Ktor plugin:
On the welcome screen, click New Project. Otherwise, from the main menu, select File → New → Project.
Choose Ktor from the list of generators on the left:
Fill in your project details like Name and Location. You can configure the Engine, Build System, and other settings here. Click Advanced Settings to see options like the Ktor version and configuration file type. For now, match the settings and click Next:
On the next screen, you can add plugins to your project. We don't need any at the moment. If we did, we could simply search for one, like "serialization", and click Add:
Click Create. IntelliJ IDEA will generate the project and open it for you.
For command-line enthusiasts, the Ktor CLI provides an interactive way to generate projects:
First, install the Ktor CLI:
For Linux and macOS, the tool can be installed via Homebrew:
brew install ktorFor Windows, the tool can be installed via WinGet:
winget install Jetbrains.KtorCLIRun the interactive generator with the command
ktor new.You may be required to restart your terminal session.
Enter your project's name when prompted. You can also change the project location.
You can change the project's group once it has been generated.
The next step allows you to search for and add plugins from different categories like Administration, Security, etc. For now, we will skip this:
Press CTRL+G to generate the project files in the specified location.
At the moment, some settings such as selecting the Ktor version or server engine aren't configurable. The engine defaults to Netty, and the version used depends on the ktor CLI tool's version.
Explore, and run in IntelliJ IDEA
If you created the project in IntelliJ IDEA, it's already open. If you downloaded it or generated it via Ktor CLI, click Open on IntelliJ's welcome screen. Otherwise, from the main menu, select File → Open, then choose your project's root folder (make sure it's extracted if downloaded).
The project has a standard layout:
The main source code is located under
src/main/kotlin.Resources, such as configuration files, are placed in
src/main/resources.The build script,
build.gradle.kts, is in the project's root directory. It defines your project's dependencies and other build-related settings.
Let's examine the generated code. You will find two Kotlin files in your src/main/kotlin directory:
Application.ktThis file contains the entry point for the application:
package com.example import io.ktor.server.application.* fun main(args: Array<String>) { io.ktor.server.netty.EngineMain.main(args) } fun Application.module() { configureRouting() }main(): The main function callsio.ktor.server.netty.EngineMain.main(args)which starts the Netty engine and automatically loads its configuration from a resource file (application.yamlin our case).Application.module()is the main module of your application. In Ktor, a module is simply a function that configures a part of the application's functionality. You can have more than one module, each with its own features (via plugins), and purpose. Ourmodulecurrently just callsconfigureRouting()to set up our endpoints.
Routing.ktThis file defines the application's endpoints:
package com.example import io.ktor.server.application.* import io.ktor.server.response.* import io.ktor.server.routing.* fun Application.configureRouting() { routing { get("/") { call.respondText("Hello World!") } } }This code sets up a handler for HTTP
GETrequests to the root path/. When a request is received, it responds with the plain text "Hello World!".
The glue that connects the server's main function your module function (application logic) is the configuration file found in src/main/resources/application.yaml:
ktor:
application:
modules:
- com.example.ApplicationKt.module
deployment:
port: 8080This YAML file configures two areas:
Deployment: The port is a virtual point where network connections start and end. Here we specify that the server should run on port
8080. It is important that this port is free on your machine, otherwise, the application will fail to start.Application: When the application starts, it loads the specified modules. Our entry point to
com.example.ApplicationKt.module, which is themodule()extension function inside theApplication.ktfile.
It's worth noting that if we had chosen the 'Configuration in code' option during project setup, this file wouldn't exist. Instead, our main function would manually start the server and pass parameters directly, like so:
fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module)
.start(wait = true)
}However, these two approaches are not mutually exclusive. Even when using embeddedServer to define core settings like port, you can still include a configuration file (YAML or HOCON) to manage other values like API keys which your application can read from.
To run your application from within IntelliJ IDEA:
Click the run button in the top-bar (or use the default shortcut SHIFT+F10):
Ensure the selected configuration is 'EngineMain'.
Or, click the green button in the gutter next to the
mainfunction and choose Run 'ApplicationKt.main()':
A link will appear in the Run tool window's console:
Open the link and verify that everything is working. You should see the "Hello World!" text displayed.
Conclusion
We've created and run our first application with Ktor. As seen, getting a project up and running is quite easy and fast. Ktor allows you to build applications by composing only the features you need through plugins. It offers a compelling, lightweight, and coroutine-native choice for building modern web applications in Kotlin.