Run AWS Lambda with Kotlin
Lambda is a buzz word nowadays, for good reasons: simple, fast and pay as you go.
Majority of lambda functions examples are written in TypeScript and, for the JVM side, Java only. That's why I'm creating this example, to anyone interested in running a Kotlin function on AWS.
I'll be using the AWS CLI only, not the AWS online console.
Create the kotlin project – gradle
First of all we need to create our kotlin project. We'll use Gradle to do it, but translate it to Maven should be trivial.
Create a folder wherever you want, navigate to it in the command shell and execute the following:
gradle init
After that, select the following options:
- Select type of project to generate:
library
- Select implementation language:
Kotlin
- Select build script DSL:
Groovy
- Generate build using new APIs and behavior
(some features may change in the next minor release):
no
Dependencies
To run our function on AWS we need to add some dependencies to our project.
implementation 'com.amazonaws:aws-lambda-java-core:1.2.2'
Apart from AWS specific, we'll need a fat jar, so we need to add a plugin to generate it:
id "com.github.johnrengelman.shadow" version "7.1.2"
That's all we need to have our proof of concept.
Create the actual Kotlin function
I'm using IntelliJ IDE
Our Lambda function will be very simple:
Implement an echo function, i.e., it will return the received input.
Let's create our main Class. I'll create the package com.ruimptech.echo
inside src/main/kotlin
. Inside that package I'll create the main kotlin class, named App
.
In order to run in AWS, our main class needs to implement the RequestHandler
interface.
As you can see in the image, there's an error, that's because the RequestHandler interface requires to specify the input and output data type. To fix that, we'll create a class for input and another for output and use them to fix the interface error.
Input class
package com.ruimptech.echo
class EchoIn {
var content: String = ""
}
Receives a simple content String.
Example: { "content": "hello" }
Output class
package com.ruimptech.echo
data class EchoOut(val content: String)
Very similar to the input class, contains the output content String, that in our proof of concept will be the received input.
Note that our EchoIn
class is not a data class, that's because a data class will not work on AWS. If we use a data class as the input, lambda execution will terminate immediately due to a initialization error.
Now that we have input and output classes, we can fix our lambda function (App class).
package com.ruimptech.echo
import com.amazonaws.services.lambda.runtime.Context
import com.amazonaws.services.lambda.runtime.LambdaLogger
import com.amazonaws.services.lambda.runtime.RequestHandler
class App : RequestHandler<EchoIn, EchoOut> {
override fun handleRequest(input: EchoIn, context: Context): EchoOut {
val logger: LambdaLogger = context.logger
logger.log("ECHO INPUT RECEIVED: " + input.content)
return EchoOut("Echo: ${input.content}")
}
}
At this point, the function is ready! Let's go over what is going on:
-
RequestHandler<EchoIn, EchoOut>
- We say to our lambda function that EchoIn and EchoOut are the input and output data types.
-
override fun handleRequest
- The actual code to be run on each incoming request
- As mentioned before, the function is very simple. We print a log with the received input and return it inside a EchoOut instance.
Create a fat jar
The com.github.johnrengelman.shadow plugin allow us to create a fat jar with a simple command:
./gradlew shadowJar
As a result, we'll find a file named lib-all.jar inside the build/libs
directory, that's our fat jar.
Deploy the lambda function
We have everything in place in our computer, now let's send it to AWS.
As any AWS deploy, we need a template to specify what we want to do. We'll use an existing AWS template (you can find the original version here) and tweak some properties:
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Kotlin Lambda Function
Resources:
function:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/lib-all.jar
Handler: com.ruimptech.echo.App::handleRequest
Description: Kotlin function
Runtime: java11
MemorySize: 512
Timeout: 10
# Function's execution role
Policies:
- AWSLambdaBasicExecutionRole
- AWSLambda_ReadOnlyAccess
- AWSXrayWriteOnlyAccess
- AWSLambdaVPCAccessExecutionRole
Tracing: Active
The main changed parameters are:
- CodeUri
- Where is the fat jar to send to AWS
- Handler
- What is the function to run
- Description
Save this template in a file named template.yml
, place it in the lib folder of the project:
From that point on, I assume you have an AWS account and the CLI is correctly configured in your computer. If not, please check this out
Now, to deploy the function we need 3 steps:
- Create a S3 bucket where the final template will be stored (the template.yml file we just created is a template to generate the final template, don't worry too much about it)
- Generate the final template and save it on the bucket created before
- Deploy the final template
These 3 steps are directly converted to 3 CLI commands:
aws s3 mb s3://lambda-kotlin
-
aws cloudformation package –template-file template.yml –s3-bucket lambda-kotlin –output-template-file template-out.yml
- Based on our template.yml, the CLI will generate the final template - template-out.yml - that we can use in the final step
-
aws cloudformation deploy –template-file template-out.yml –stack-name lambda-kotlin –capabilities CAPABILITY_NAMED_IAM
- Use the final template to deploy the lambda function
That' it! Our Kotlin Lambda function is on AWS!
Testing
Now that we have our lambda online, we can test it. To do it we need to know the name of our function. The simplest way to find it is going into AWS console and copy the name:
Now that we have our function name, let's call it from the CLI.
In order to run our test, we need to enable the literal input, that means we'll pass the payload from the command line. To enable it, open the CLI config file:
MacOS and Linux:~/.aws/config
Windows:%USERPROFILE%\.aws\config
Add the line:
cli_binary_format = raw-in-base64-out
If you want more information, check it here
The payload needs to match our EchoIn class, so to test the lambda we need to run something like:
aws lambda invoke \
--function-name lambda-kotlin-function-R4M2Bf9fxxBf \
--payload '{ "content": "Hey!" }' \
out.json
The content of the response will be stored in out.json
file and the content will be:
{"content":"Echo: Hey!"}
That's it, you just deployed and run a Kotlin Lambda function on AWS!
You can find the code on GitHub.
Top comments (0)