Ktor on Google AppEngine from Zero to Hero part 1

Peter Nagy
4 min readOct 5, 2022

Hello, I am an Android engineer with some backend engineer experience. Earlier I have used Google AppEngine PaaS environment for many small projects but because of Java (and because of mobile projects) I have lost my interesting to use that platform. For 4 years I am using Kotlin (the new Java language :) ) and I really like it so I just was looking for how can I write some backend code with Kotlin. And just I have found the Ktor from JetBrains.

Ok, and what is Ktor ?

Ktor is a framework, something like Spring Boot or other backend frameworks. It helps for developers to create backend application. The benefit of it:

  • You can use your liked Kotlin language
  • Coroutines is given, framework is using coroutine under the hood
  • You can use Plugins and easily add new features
  • You can use DSL to create backend

If you are not a fun of Ktor from my epilogue let’s see how it is working.

What is AppEngine ?

Google AppEngine (in short form GAE) is a PaaS in the Google Cloud. Long story short you are able to deploy your app in the Cloud without you have to manage your infrastructure. It is similar like AWS but it provided by Google. (If you want you can find more details here)

What is need to learn Ktor and AppEngine ?

  1. You need to register in the Google Cloud Platform (link is here) (it is free however for some service you need Credit Card and if you use too much then you should pay [pay as you go])
  2. You need to install Gcloud CLI tool (link here). With this CLI tool you can manage your application easily from a terminal. However you can do most of the things from a web page too.
  3. Install the App Engine extension for Java with the following command:
gcloud components install app-engine-java

(What I forgot to mention we will use java environment to run our application. We can do this because Kotlin is using JVM)

I am using IntelliJ IDEA (community edition). Let’s create a new project, with Gradle and you can use Kotlin DSL (it is similar like Groovy but if you are using Kotlin then use it in DSL too).

When your new app created you can edit the build.gradle.kts:

import com.google.cloud.tools.gradle.appengine.appyaml.AppEngineAppYamlExtension

val ktor_version = "2.1.2"
val kotlin_version = "1.7.10"
val gce_logback_version = "0.123.6-alpha"

plugins {
application
kotlin
("jvm") version "1.7.10"
id("com.google.cloud.tools.appengine") version "2.4.4"
id("com.github.johnrengelman.shadow") version "7.1.2"
}

application {
mainClass.set("io.ktor.server.netty.EngineMain")
}

repositories {
mavenCentral()
maven { url = uri("https://maven.pkg.jetbrains.space/public/p/ktor/eap") }
}

configure<AppEngineAppYamlExtension> {
stage {
setArtifact("build/libs/${project.name}-all.jar")
}
deploy {
version = "GCLOUD_CONFIG"
projectId = "GCLOUD_CONFIG"
}
}

dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
implementation("io.ktor:ktor-server-core:$ktor_version")
implementation("io.ktor:ktor-server-netty:$ktor_version")
implementation("com.google.cloud:google-cloud-logging-logback:$gce_logback_version")
testImplementation("io.ktor:ktor-server-test-host:$ktor_version")
testImplementation("org.jetbrains.kotlin:kotlin-test")
}

and you must edit the settings.gradle.kts

pluginManagement {
repositories {
gradlePluginPortal()
google()
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == "com.google.cloud.tools.appengine") {
useModule("com.google.cloud.tools:appengine-gradle-plugin:${requested.version}")
}
}
}
}

This is necessary because appengine plugin is not available as public gradle plugin. (Link is here)

Now we should configure the AppEngine:

Create an appengine folder under /src/main/ -> /src/main/appeingine

you can create an app.yaml file here. (Without this file appengine deploy will be failed!)

runtime: java11
entrypoint: 'java -jar {project_name}-all.jar'

In the {project_name} part you should write Your project name because later app will not able to find the proper jar file.
The file name was given from build.gradle.kts:

configure<AppEngineAppYamlExtension> {
stage {
setArtifact("build/libs/${project.name}-all.jar")
}
deploy {
version = "GCLOUD_CONFIG"
projectId = "GCLOUD_CONFIG"
}
}

If you would like to read documentation about app.yml you can find it here.

Add a package like com.demo.ktor and create a Kotlin class:

package com.demo.ktor

import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)

fun Application.module() {
routing {
get("/") {
call.respondText("Hello, world!")
}
}
}

This is the main file which will be run in the application!
We created our first “Hello world” backend call. :)
Unfortunately it is not enough we need a configuration file for the framework (without it framework will not know where should find the application).

Under the resources folder you should create a file: application.conf

ktor {
deployment {
port = 8080
}
application {
modules = [ com.demo.ktor.ApplicationKt.module ]
}
}

Here you can set your application class. This settings could be part of the Application.kt file or it could be a different configuration file (its up to you).

Optional you can set here the logback settings too, create a logback.

<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="trace">
<appender-ref ref="STDOUT"/>
</root>
<logger name="org.eclipse.jetty" level="INFO"/>
<logger name="io.netty" level="INFO"/>
</configuration>

Last step is deploy the application to the AppEngine:

First we should create the app:

gcloud projects create {your app name in AppEngine} --set-as-default

With this command we can create an application/project in the Google Cloud. If you open the Cloud console it will be the default project.

With the next command you can create it:

gcloud app create

Now environment ready to deploy, you can type the next command from IntelliJ terminal:

./gradlew appengineDeploy

IF there is any new update for the Google Cloud CLI it will update it. And try to deploy it to the cloud! Be careful at the case of first run it will be failed. And the reason is because Cloud deploy is not enabled. Go to the link which is written in the error and switch from off to on. Yes this is not an always free service. General I was able to keep in the free quota. But it is a mandatory step.

If your app is deployed, you can test it: https://{app engine project name}.appspot.com -> if everything is ok you can read Hello, world!

If there is an error you can find the route cause in the log:
https://console.cloud.google.com/logs/

Some links:

Official Ktor documentation: — https://ktor.io/docs/google-app-engine.html#prerequisites

Google AppEngine: — https://cloud.google.com/appengine

You can find this lession in the GitHub: https://github.com/petnagy/Ktor_sample/tree/main/Ktor_demo

Thanks for reading my article! If you found this post useful? Kindly tap the 👏 button below and follow :) .

--

--