Kotlin "Server-less" Functions
Recently I found the need to create a Server-less Function for a project and was disappointed in both the lack of Kotlin options and the tightly-coupled, framework-specific code necessary to implement one. This lead me to ponder about how a Server-less Function could be implemented in Kotlin. These musings are what I discuss in this article. Note, this is just a rough idea and not a fully worked out solution.
TL;DR
This article posits a Kotlin Server-less Function library using annotation processing as a means to automatically coordinate the functions appropriately.
What is a "Server-less" Function?
This may not be the appropriate terminology, but essentially, a Server-less Function is a hosted function in the cloud that performs a single focus action. These functions can be triggered by an HTTP endpoint, another Server-less Function, or some other service.
Why is "Server-less" in quotes?
😂 These functions do actually run in a Server. But all the noise about setting up and configuring a Server is abstracted out. This lets the developer just focus on the implementation logic for the action the function performs.
Achieving this in Kotlin
There are a few popular Kotlin server-side frameworks, including:
However, these are full Kotlin server solutions not merely a Server-less Function framework/library. The closest one resembling a Server-less Function framework is http4k. From their introduction on their website they state:
http4k is a lightweight but fully-featured HTTP toolkit written in pure Kotlin that enables the serving and consuming of HTTP services in a functional and consistent way. http4k applications are just Kotlin functions which can be mounted into a running backend.
The library seems well put together. I have used it before in some personal projects and it is a pretty solid option for a Kotlin backend. It also almost provides exactly what I am looking for with respect to functions:
fun main() {
val app: HttpHandler = { request: Request -> Response(OK).body(request.body) }
val server = app.asServer(SunHttp(8000)).start()
}
The HttpHandler
is essentially a "Server-less" Function. It's just a Kotlin function that takes in an HTTP Request
object and returns an HTTP Response
object. Unfortunately, however, you will still need to explicitly start the Server and state which Server implementation you are using (this is done in the main()
function above). On a larger application with numerous functions, this could become a bit more cumbersome. Also, the library works only on the JVM, so it's not Kotlin Multi-platform which would nice.
My "Server-less" Function library vision
- Kotlin Multi-platform
- Framework and platform agnostic
- Simple, yet flexible, API
- Boilerplate and setup code handled for you
- Multiple function support
The way I envisioned this was to have an annotation, say @ServerFunction
, that would be provided on a Kotlin function simply like:
@ServerFunction
fun performAction(request: HttpRequest): HttpResponse { ... }
The parameter provided to the function would be the HttpRequest
object and the function would be expected to return an HttpResponse
. It may be perferrable, for testability reasons for one, to annotate a class rather than a top-level function. So, perhaps there would be an interface that the annotated class must implement:
@ServerFunction
class MyServerlessFunction : ServerlessFunction {
override fun invoke(request: HttpRequest): HttpResponse { ... }
}
The annotation processor's responsibility would be to gather all the functions and set them up along with the actual server (or server abstraction). So this means you will no longer have an entry point function, such as main
, to coordinate the functions and launch the server.
The code generated by the annotation processor could even use the http4k
library underneath and just handle the coordination and setup of the server. It's a simple idea, but if done correctly, the library could be both framework and platform agnostic (giving it the most flexibility - imagine being able to choose between KotlinJs/NodeJs and KotlinJVM and use the same code), and simple enough to hack something together real quick. This library would require:
- A Kotlin Multi-platform annotation processor (like this one) or a Gradle or Kotlin Compiler plugin
- A Kotlin Multi-platform representation of an HTTP Request and Response
- One module for the Annotations and Interfaces
- One module for the Annotation Processor
- Some form of server abstraction
- Coordination between the different functions
- Endpoint management
End
A Kotlin Server-less Function library with a simple API would be beneficial for developers to quickly launch a function without the overhead of learning an entire framework. They could use any existing Kotlin libraries, tools, and build systems they need. And will have ultimate flexibility in launching the functions to whatever server they desire. While not fully worked through, this concept may provide the groundwork to building such a library.