Creating AWS Lambda Functions with Kotlin

Dan Murphy
5 min readFeb 12, 2022
Kotlin + AWS lambda

Context

Serverless computing offers a number of advantages over traditional deployment strategies. They can enhance scalability, quicken release times, and reduce costs. Additionally, it is easier for lean teams to maintain serverless architecture because they do not need to worry about provisioning and maintaining servers.

There are also some cons, particularly because debugging and testing code is a bit more challenging. This complicates CICD and increases security concerns. Furthermore, a serverless architecture does not work well for long-running processes. Services like AWS CloudWatch and S3 (which will we discuss in this article) can solve some of these challenges, but it is important to be cognizant of the pros and cons before moving to a serverless architecture.

If you are working at a company or on a project with an unpredictable, non-constant request volume then the serverless route likely makes more sense for you.

Coding

After deciding that a serverless architecture makes sense for your use case, you then need to figure out the remaining tools you’ll need for the job. In this article, we will focus on setting up a Kotlin environment and using that to create an AWS Lambda Function. In addition to Kotlin, AWS Lambda also supports Java, Python, Node, and other languages.

Tools for this Tutorial

  • Kotlin (for defining the Lambda Function)
  • Maven (for managing our Kotlin project)
  • AWS Lambda
  • AWS CloudWatch (for monitoring and debugging)
  • AWS S3 (for storing the uber-JAR generated by Maven)

Setting up our Project Locally

If you do not yet have Kotlin installed on your system, you can follow the steps outlined here. Additionally, you’ll need to install Maven. TL;DR is that you can run the following:

brew install kotlin maven

To test your installation run:

$ kotlin -version
$ mvn --version

Additionally, you’ll need to have an AWS account. Everything we do in this tutorial falls under the free tier of AWS resources, but you’ll need to register and sign in to the console before moving on to the next steps. We will mostly use the command line to interact with AWS, so this tutorial also assumes that you have:

(1) Installed the AWS CLI

(2) Configured the AWS CLI to use the correct account

Creating a Simple `RequestHandler`

Setting up the Basics

When it comes to creating the actual lambda function, it is a bit more involved for Kotlin in comparison to other languages. The pros of using Kotlin are (1) it is much easier to package your dependencies into an uber-JAR and seamlessly upload them to AWS and (2) the expressiveness of the language itself makes for a good developer experience.

The first step is to set up our Kotlin project with a basic pom.xml file. A simple template that you can use is defined here. This pom file is based off the starter maven template for a kotlin project. In addition to the starter template, we add the org.codehaus.mojo plugin.

After this, we’ll need to set up our directory structure. You can do this by using a maven starter archetype in the IntelliJ IDE, or you can clone the Github repository.

kotlin_lambda_poc
├── kotlin_lambda_poc.iml
├── pom.xml
├── src
│ ├── main
│ │ └── kotlin
│ │ └── com
│ │ └── example
│ │ └── kotlin_lambda_poc
│ │ └── handler.kt
│ └── test
│ └── kotlin
│ └── com
│ └── example
│ └── kotlin_lambda_poc
│ └── handlerTest.kt

Prior to coding, we need to add some more dependencies to our pom.xml file. You can view the up-to-date pom.xml here.

In src/main/kotlin/com/example/kotlin_lambda_poc/handler.kt, add the following code:

package com.example.kotlin_lambda_poc;fun main(args: Array<String>!) {
println("Hello, world")
}

Then, from the source of your directory (with the pom.xml) run:

mvn package exec:java

You should compile correctly and return “Hello, world.”

Creating the `RequestHandler`

Now that we have our development environment fully bootstrapped, we can begin building out the actual Lambda function. The basic premise of a Lambda is a function you define that consumes two arguments: the event and the context. The event itself is provided to Lambda at runtime, and the context is composed of data that informs you about the invocation, function, and execution environment. The event provided to lambda is most easily thought of as an input to the function, and this input itself may dictate the way the function behaves.

Now that we have a basic understanding of AWS Lambda, let’s create our handler function. For a basic “AWS Lambda Hello, World” we will start with the following code:

package com.example.kotlin_lambda_poc;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

class Handler: RequestHandler<Map<String, String>, String> {
override fun handleRequest(event: Map<String, String>, context: Context): String {
return "hello"
}
}

First, we create a class that inherits from the RequestHandler interface that AWS defines in com.amazonaws.services.lambda.runtime.RequestHandler. Then, we override the handleRequest function so that it returns “hello”. Given that we already have the AWS and maven shade dependencies/plugins defined in our pom.xml file, we are ready to create our uber-jar and upload it to AWS!

Creating the uber jar

To create the uber jar we need to run the following in the command line:

mvn package

This will create an uber-jar in the target folder. The name of the jar, assuming you are using the same pom.xml we linked above, will be kotlin_lambda_poc-1.0-SNAPSHOT.jar.

Uploading our Function to AWS Lambda

Now that we have our uber-jar, we can upload the function to AWS S3 and Lambda. Run the following command to create an AWS s3 bucket and upload the uber-jar to that bucket:

aws s3api create-bucket --bucket kotlin-lambda-tutorial && aws s3api put-object --bucket kotlin-lambda-tutorial --body kotlin_lambda_poc/target/kotlin_lambda_poc-1.0-SNAPSHOT.jar --key kotlin_lambda_poc-1.0-SNAPSHOT.jar

This creates a new bucket called “kotlin-lambda-tutorial” and uploads our uber-jar to it under the key name “kotlin_lambda_poc-1.0-SNAPSHOT.jar”. Next, we need to create our lambda function and assign the code to it. You can accomplish this with the following command:

aws lambda create-function --function-name  myFunctionName --runtime java11 --handler com.example.kotlin_lambda_poc.Handler::handleRequest --role arn:aws:iam::414030767954:role/lambda-vpc --code S3Bucket="kotlin-lambda-tutorial",S3Key="kotlin_lambda_poc-1.0-SNAPSHOT.jar"

The bolded values may be different based on the name and role you assign to your lambda function. Additionally, in the future, should you want to update the code assigned to your lambda function, you can run the following:

aws lambda update-function-code --function-name myFunctionName --s3-bucket kotlin-lambda-tutorial --s3-key kotlin_lambda_poc-1.0-SNAPSHOT.jar

Lastly, you can invoke your function and save the output to output.txt with the following:

aws lambda invoke --function-name myFunctionName output.txt

If all is working, you should see “hello” when you run:

cat output.txt

Wrap Up

In this tutorial, we learned how to create an AWS Lambda function with Kotlin. We used the AWS CLI to spin up an S3 bucket, upload our code to AWS S3, and create and invoke our AWS Lambda function.

--

--