Reputation: 7371
Does AWS Lambda functions provide support for Kotlin language? Currently Lambda function creation wizard don't contains Kotlin option in the runtime dropdown list:
But there are Java 8 and different Node.js versions. Which platform is more appropriate for function written on Kotlin in context of AWS Lambda - JVM or Node.js? And which Kotlin frameworks can I use to write a Lambda function?
Upvotes: 8
Views: 9824
Reputation: 10724
Up to today, all developers writing Kotlin code have been using the AWS SDK for Java. Today AWS has released an official SDK for Kotlin. See the details here:
https://aws.amazon.com/blogs/developer/aws-sdk-for-kotlin-alpha-release/
Upvotes: 4
Reputation: 33422
Kotlin/JVM
The most natural way to create an AWS Lambda function on Kotlin would be to use Kotlin/JVM and target Java 8 Lambda runtime. Kotlin's interop with Java is really great. JVM Lambda functions should be packed in fat JARs, i.e. JAR files with all the dependencies included. It's easy to do with Gradle:
build.gradle.kts:
plugins {
kotlin("jvm").version("1.3.41") // (1)
id("com.github.johnrengelman.shadow").version("5.1.0") // (2)
}
repositories {
jcenter()
}
dependencies {
implementation(kotlin("stdlib-jdk8")) // (3)
implementation("com.amazonaws:aws-lambda-java-core:1.2.0") // (4)
}
Then just create a handler:
Handler.kt:
class Handler : RequestHandler<Input, Output> { // (1)
override fun handleRequest(input: Input, context: Context): Output {
println(input)
return Output()
}
}
RequestHandler
class. All you have to do is to implement it's single method handleRequest
. Input
and Output
can be your POJOs (POKOs), just make sure they can be serialized and deserialized with Jackson (Lambda's docs doesn't mention it implicitly, but if something fails you'll see Jackson mentions in logs); or primitive types; or some predefined classes.Take a look at the complete code sample here: it contains a function that could be used with Lambda Proxy Integrations in API Gateway .
That's it for Kotlin/JVM. Very easy.
Kotlin/JS
I am not an expert with Kotlin/JS, but you could target Node.js runtime as well, though it won't be as straightforward as JVM.
The idea will be to compile (transpile) your Kotlin code into JavaScript and deploy it as a usual JavaScript Lambda function (i.e. ZIP).
The handler can look like this:
Handler.kt
import kotlin.js.json
@JsName("handle")
fun handle(input: dynamic, context: dynamic): dynamic {
println(JSON.stringify(input))
val result: dynamic = json(
"statusCode" to 307,
"headers" to json(
"Location" to "https://google.com"
)
)
return result
}
The complete example can be found here. It does the same as Kotlin/JVM Lambda function above (responds with redirects), but it runs on Node.js 10.x runtime.
Project setup is slightly harder for Kotlin/JS: you'll need to package the transpiled JS along with dependencies (node_modules
) in a ZIP file. There may be a lot of ways to do that, you can take a look at one of them here.
Bonus: Kotlin/Native!
Amazon announced Lambda Runtime API on AWS re:Invent 2018. It allows developers, among other things, to build Lambda functions using any technology they want via so-called Custom Runtimes. Yes, it’s now possible to author a function on PHP, Perl, Pascal (anybody?) or even Bash (they use it in the docs)!
Custom runtime functions work a little bit differently than usual functions. A runtime’s job is to:
Here is a picture to help you grasp a function’s lifecycle:
A very basic handler can look like this:
Handler.kt:
fun main() = runBlocking { // (1)
val client = HttpClient(Curl) // (2)
while (true) { // (3)
val invocation = client.call("http://${getenv("AWS_LAMBDA_RUNTIME_API")!!.toKString()}/2018-06-01/runtime/invocation/next") {
method = HttpMethod.Get
} // (4)
// (5)
val invocationId = invocation.response.headers["Lambda-Runtime-Aws-Request-Id"]
// (6)
client.call("http://${getenv("AWS_LAMBDA_RUNTIME_API")!!.toKString()}/2018-06-01/runtime/invocation/$invocationId/response") {
method = HttpMethod.Post
body = TextContent(
"{\"statusCode\": 307, \"headers\": {\"Location\": \"https://google.com\"}}",
ContentType.Application.Json
)
}
}
}
runBlocking
.Curl
engine. This is the initialization phase from the picture at the beginning of this post.As you see, you'll need to write much more code in case of Kotlin/Native. Take a look at a complete example here.
Conclusions
You probably shouldn't look at Kotlin/JS and Kotlin/Native for Lambda functions yet.
Kotlin/JS gives you almost nothing compared to JavaScript and TypeScript but requires more lines of code to achieve the same result. Facing JS's inherent dynamism causes some pain, Kotlin/JS interop IMHO is not as good as in case of Kotlin/JVM. The build is more complex as well as it will require you to configure Gradle and NPM to work together (while JS/TS will require only NPM, and Kotlin/JVM requires only Gradle).
Kotlin/Native requires you to write more code to just handle the events. Plus, you won't be able to easily use any AWS SDKs: JVM libraries will not work with Kotlin/Native (though you could probably use C/C++ SDK which is much more low-level than JVM). The build is more complex as well.
If you're interested in comparing different languages/runtimes for AWS Lambda, take a look at this repo I've linked a few times above. It has Lambdas implemented in Java, Kotlin/JVM, Kotlin/JS, Kotlin/Native, JS, Ruby, Python and Bash. To read more about Kotlin/Native for AWS Lambdas go here. The article also has a comparison of speed of functions in different languages. TLDR:
Upvotes: 14
Reputation: 13972
In Javaland, if you're putting a Kotlin program on a server you should make it a fat jar, so you can execute it on any JVM without having to worry about explicit support for Kotlin.
Alternatively, if you don't want to pay the JVM startup costs for a AWS Lambda cold start you might look at using the Kotlin targeting the Node.js runtime instead of the JVM. But I'd take almost the exact same approach here: (trans)compile your Kotlin to Javascript on a build server, package up your (now) Javascripts + NPM modules and send that up to Lambda. This may or may not work depending on how much you wrote your code assuming Java packages...
So, I think the answer to your question is two fold:
But in both cases you don't need explicit support for Kotlin, just the bytecode that your compile process generates (JVM, or Javascript/Node)
Upvotes: 6