Kotlin
A concise multiplatform language developed by JetBrains
Ktor 3.2.0 Is Now Available
Ktor 3.2.0 is here! This is the second minor release of the year, bringing exciting new features, performance improvements, and bug fixes. This release includes two new modules for dependency injection and HTMX, support for Gradle version catalogs, automatic configuration deserialization, Unix domain socket support for CIO, and much more. Check out the full changelog here.
🚀 Get started with Ktor 3.2.0
Ready to explore Ktor 3.2.0? Start building your next project today with our interactive project generator at start.ktor.io. Your feedback and contributions are always welcome!
📢 Join the Community on Reddit and Slack
Typed configuration
Ktor now automatically deserializes configuration files into data classes, in addition to primitive types. Let’s create a simple application.yaml that defines some database configuration.§
database: jdbcUrl: "$DB_JDBC_URL:jdbc:postgresql://localhost/ktor_database" username: "$DB_USERNAME:ktor_user" password: "$DB_PASSWORD:ktor_password"
Note: In Ktor, YAML can reference environment variables with $ENV_VAR or “$ENV_VAR:default_value” syntax, and even ${ENV_VAR} like in HOCON.
In order to deserialize structure data, we need to define it first – so we define a data class that matches our application.yaml. Once we’ve defined it, we can use it to load our configuration in a typed manner in our modules.
@Serializable data class DatabaseConfig( val jdbcUrl: String, val username: String, val password: String, ) fun Application.module() { property<DatabaseConfig>("database") }
Dependency injection
The 3.2.0 release features a brand new module! Dependency injection (DI) is a crucial feature for many teams, and it was highly requested by the community. This module is completely optional, but when enabled, it allows Ktor to offer additional functionality out of the box for DI users. Ktor DI is built on top of coroutines, just like Ktor itself, which is really powerful since it easily allows for the concurrent initialization of your application.
It automatically closes AutoCloseable instances or allows to configure your own cleanup handlers. When the server receives a stop command, the HikariDataSource will close automatically, and then the custom cleanup handler for Database will be executed.
fun Application.database(@Property("database") config: DatabaseConfig) { dependencies { provide("optional-name") { HikariDataSource(...) } provide { Database.connect(resolve<HikariDataSource>("optional-name")) } cleanup { database: Database -> TransactionManager.closeAndUnregister(database) } } }
Ktor DI also allows for easy integration with existing DI frameworks, and Koin 4.1 has an experimental module that already integrates with Ktor 3.2.0-EAP, offering seamless interoperability between Ktor DI and Koin. More details can be found on the Koin website.
Suspend modules
Along with these new features, Ktor now also supports suspend, or asynchronous, modules. These make it possible to await dependencies that require suspension for their initialization. They also make it easy to parallelize large, complex dependency graphs.
suspend fun Application.module() { val database: Database = dependencies.resolve() ... }
Unix domain socket support for CIO
The CIO client and server engine now support Unix domain sockets! This support provides more efficient bidirectional communication between processes on the same system, allowing them to eliminate the networking overhead completely.
To use Unix domain sockets, you need to explicitly configure your embeddedServer to use a unixConnector by specifying the path to the socket.
val server = embeddedServer(CIO, configure = { unixConnector("/tmp/test-unix-socket-client.sock") }) { routing { get("/") { call.respondText("Hello, Unix socket world!") } } }
To communicate with the Ktor server listening to Unix domain sockets, you also need to connect to the same Unix domain socket file.
val response = HttpClient(CIO) { defaultRequest { unixSocket("/tmp/test-unix-socket-client.sock") } }.get("/")
HTMX
The new HTMX module includes tight integration with kotlinx.html and the Ktor Routing DSL. This allows you to more easily define HTML attributes for HTMX and define routes that automatically include HTMX headers.
fun Application.routing() { hx.get("/status") { /* Return HTML content */ } get("/status") { call.respondHtml { head { script { src = "https://unpkg.com/htmx.org@1.9.12" } } body { div { attributes.hx { get = "/status" trigger = "load" } } } } } }
Ktor version catalog
Version catalogs have quickly become the standard for managing dependencies and their versions in Gradle. They allow us to reference dependencies in a type-safe way from our Gradle scripts and manage dependencies in a single location. Ktor now exports a version catalog, just as it does a Maven BOM. To use Ktor’s version catalog, you need to import it into your settings.gradle.kts:
dependencyResolutionManagement { versionCatalogs { create("ktorLibs") { from("io.ktor:ktor-version-catalog:3.2.0") } } }
Once imported, you can reference all Ktor modules in a type-safe way from all your build.gradle.kts configurations.
dependencies { implementation(ktorLibs.server.netty) implementation(ktorLibs.server.contentNegotiation) implementation(ktorLibs.serialization.kotlinx.json) }
Android R8 regression
There is a known regression in the Ktor 3.2.0 release regarding Android R8. For more information about the issue, you can check out this issue on YouTrack. It will be fixed in the 3.2.1 release, and we’re also working to improve our pipelines and test suites to prevent regression in this area in the future.
🚀 Thank you!
We want to say thank you to everyone for your contributions and feedback!
A special shout-out to reonaore, markozajc, rururux, OmniacDev, and StefMa for their first contributions to Ktor, as well as to MarcusDunn and Philip Wedemann for their active contributions.
Start building your next project at start.ktor.io. Your feedback and contributions are always welcome!
🔗 Get Started With Ktor | 📢 Join the Community on Reddit and Slack