Deploying fatjar Ktor applications on Google Cloud App Engine
Tags: kotlin, cloud, serverless
Published: 2019-09-11 13:28:38

---
title: Deploying fatjar Ktor applications on Google Cloud App Engine
published: true
description: 
tags: kotlin, cloud, serverless
---

# The original serverless platform

[Google App Engine](https://cloud.google.com/appengine) or GAE for short. Has always been an amazing service to run your web applications. Some highlights:

* Supports multiple runtimes ([java](https://cloud.google.com/appengine/docs/standard/java/), [python](https://cloud.google.com/appengine/docs/python/), [go](https://cloud.google.com/appengine/docs/standard/go111/), [php](https://cloud.google.com/appengine/docs/standard/php7/), [ruby](https://cloud.google.com/appengine/docs/standard/ruby/), [nodejs](https://cloud.google.com/appengine/docs/standard/nodejs/) )
* Serverless execution mode, pay only for requests in flight
* Offers free tier for some services
* Support for versioning and traffic splitting
* Task scheduling and queuing of background tasks
* Many more, visit the official documentation for more information.

However for java developers there have always been a problem, you could only deploy war files, restricting you to the Servlet Spec.

Not anymore, starting with the java11 runtime, GAE now offers a way to run self contained jar files ([Ktor](https://ktor.io), SpringBoot, [Micronaut](https://micronaut.io), [Quarkus](https://quarkus.io)).

# Introducing the Java11 runtime

Starting with the [java11](https://cloud.google.com/appengine/docs/standard/java11/) runtime, you can now deploy a "fat jar" file and execute it instead of deploying a war file into a Jetty container.

All you need to do is create a new `app.yaml` file that contains the correct entrypoint command:

```yaml
runtime: java11
instance_class: F2
entrypoint: 'java  -jar frontend-1.0-SNAPSHOT-all.jar'
service: default

```

You can pass any valid java argument to the JRE and if you would like to learn all the possible options of the yaml file, check the [documentation](https://cloud.google.com/appengine/docs/standard/java11/config/appref)

# Skelleton project for ktor on GAE

Today I'll share my skelleton project for running ktor apps on GAE. Please feel free to clone it from [here](https://github.com/viniciusccarvalho/ktor-on-gae-sample) and use it as starting point.

## Project layout

```
.
├── build.gradle
├── gradle
│   └── wrapper
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   ├── appengine
    │   ├── java
    │   ├── kotlin
    │   └── resources
    └── test
        ├── java
        ├── kotlin
        └── resources
```

I've always liked the standard gradle project layout. The only difference here is the `appengine` folder under our `main` directory. This contains the `app.yaml` deployment file.

## Gradle configuration

First off, this project uses gradle 5.6. Your `gradle/wrapper/gradle-wrapper.properties` should look like this:

```
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
```

The `build.gradle` is generic enough that you can literally just copy and paste and use it for your project. As I mentioned before this is a template I use for all my projects.

```
buildscript {
    ext.kotlin_version = '1.3.50'
    ext.ktor_version = '1.2.4'
    repositories {
        mavenCentral()
        jcenter()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.github.jengelman.gradle.plugins:shadow:5.1.0'
        classpath 'com.google.cloud.tools:appengine-gradle-plugin:1.+'
    }
}


apply plugin: 'kotlin'
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'com.google.cloud.tools.appengine'

group 'io.igx.cloud'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

mainClassName = "io.ktor.server.netty.EngineMain"

repositories {
    mavenCentral()
    jcenter()
}


appengine {
    stage {
        artifact = "build/libs/$project.name-$project.version-all.jar"
    }
}

test {
    useJUnitPlatform()
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    implementation "io.ktor:ktor-server-core:$ktor_version"
    implementation "io.ktor:ktor-server-netty:$ktor_version"
    implementation "io.ktor:ktor-gson:$ktor_version"


    testImplementation "org.assertj:assertj-core:3.13.2"
    testImplementation "io.mockk:mockk:1.9.3"
    testImplementation "org.junit.jupiter:junit-jupiter:5.5.1"
    testImplementation 'org.koin:koin-test:2.0.1'

}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
```

I'm using [shadow](https://imperceptiblethoughts.com/shadow/) plugin to create my fat jar. It integrates nicely on my `application` gradle phase and generates an artifact appending `-all` to its name.

I've also modified the `appengine` defaults to point to the new jar created via the `shadow` plugin.

And last, I added the gradle appengine plugin.

Very simple, but reusable and saves me a ton of time. To build/deploy

```
./gradlew clean build
./gradlew appengineDeploy
```

That's it, hope you enjoy it.

Happy coding