Serverless Kotlin with OpenFaaS

Serverless Kotlin on OpenFaaS

With this article, my goal is to demonstrate how Serverless Kotlin can look like by introducing you to one of the coolest Serverless platforms: OpenFaaS. OpenFaaS is an open-source, community-owned project that you may use to run your functions and microservices on any public or private cloud. You can run your Docker image on OpenFaaS, which runs and scales it for you. As a result, you are free to choose any programming language as long as it can be packaged into a Docker image. Throughout this post, we want to learn about the concepts behind Serverless and Function as a Service (FaaS), and how we can deploy Serverless Kotlin functions to OpenFaaS.

Serverless and Function as a Service

Serverless Computing

With Serverless Computing, we describe a cloud model in which server management and infrastructure decisions don’t have to be tackled by the developers, but are taken care of by the cloud providers themselves. The term “Serverless” describes the fact that we don’t have to care much about infrastructure setup, scaling, and maintenance and that we can focus on developing code which can easily be deployed into production. The Serverless opportunities seem endless, and so does the landscape map published by the Cloud Native Computing Foundation (CNCF), which you can find here.

serverless-landscape

Serverless architecture is said to be the next big thing and somewhat the advancement of microservices: Monolith -> Microservices -> Serverless architecture

Function as a Service

One of the most essential Serverless offerings are so-called compute runtimes, also known as function as a service (FaaS) platforms. Many vendors provide these platforms, with the most prominent ones being AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. There are also open-source alternatives, such as Apache OpenWhisk or Oracle’s Fn Project. Many more tools and platforms exist, which are also part of the landscape map shown above.
The general idea behind FaaS is to offer a platform that can be used to execute code triggered by some event. The code can be deployed without maintaining infrastructure and just by uploading functionality to the cloud, which takes care of executing and also scaling the function. “Functions” in the context of FaaS are rather small units that generally should be stateless and can, as a result, easily be scaled horizontally. A FaaS platform will not only scale out your code if it’s under heavy load but also take care of removing instances if the function has not been invoked much for a while. This technique, for starters, helps to optimize costs but also requires awareness of cold start situations. Serverless overall has relevant positive characteristics and should be part of our discussions around reliable architecture alternatives. If you want to learn a bit more about the concepts and what Serverless architecture entails, I recommend watching “Serverless: the Future of Software Architecture” by Peter Sbarski. To be clear, I personally don’t believe that you should go Serverless no matter what, but rather see it as a valid concept that might solve parts of your problems.

OpenFaaS – Containers as Functions

OpenFaaS, as explained on their web site, “makes it simple to turn anything into a Serverless function that runs on Linux or Windows through Docker Swarm or Kubernetes”. They promise that it lets us run any code anywhere at any scale. You could describe OpenFaaS as a “containers as a function” platform since its form of abstracting functions is a Docker image. That characteristic is an excellent trait as it allows us to package any code into a Docker image, and OpenFaaS runs it, scales it, and also provides metrics for us. To be honest, it’s worth mentioning that a specific tool needs to be added to your containers, which is called Function Watchdog, a tiny Golang HTTP server which connects your function with the outside world. OpenFaaS itself runs on, e.g., Kubernetes or Docker Swarm is open source under MIT license, and is written in Go. You can find the GitHub project here.

No vendor lock-in

OpenFaaS relies on Docker images used to package our code, and the tool itself runs on platforms such as Kubernetes. The community has adopted all of these technologies and knows how to use them. As a result, you may move your OpenFaaS instance around to and from any public or private cloud without issue. OpenFaaS does not make you dependent on a particular vendor, which is contrary to what you get when relying on technologies like AWS Lambda. The fact of being dependent on a particular vendor is known as a vendor lock-in.

Other similar projects

The idea of deploying independent containers to a compute engine can be discovered in a few more projects. You can find a comparison of multiple similar tools here.

Serverless Kotlin deployed on OpenFaaS

Now that we’ve learned about the general ideas behind Serverless, FaaS and what OpenFaaS does, we want to get our hands a bit dirty by setting up an OpenFaaS Kubernetes cluster and learning how we can deploy functions to it.

OpenFaaS Deployment using Kubernetes

The following is based on the official guide. Read it to get more information and learn about alternative approaches.

As a first step, you need to make sure to have a Kubernetes cluster set up. If you want to run Kubernetes on a local machine, various tools can help you set up the cluster (e.g. k3s or minikube). On Mac and Windows, you can also use Docker’s desktop edition to run a Kubernetes cluster locally.
After having set up Kubernetes, we can start deploying OpenFaaS to the cluster. It’s incredibly easy using k3sup

# Install k3sup
curl -sLS https://get.k3sup.dev | sh
sudo install k3sup /usr/local/bin/ # <- this step might not be necessary
chmod +x k3sup
# applies openfaas namespaces, create user, applies helm chart
k3sup app install openfaas

After that, inspecting your cluster, you will find several running OpenFaaS pods.

You should be able to view the gateway UI via http://127.0.0.1:31112/ui/ where you log in using the credentials generated by k3sup. You can get the password via kubectl:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)

To allow faas-cli (needs to be installed) to access your newly deployed services, make sure to
1) set OPENFAAS_URL via export OPENFAAS_URL=http://127.0.0.1:31112
2) log in via faas-cli login --password {YOUR_PASSWORD_HERE}

The following script logs you in automatically:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
echo -n $PASSWORD | faas-cli login --username admin --password-stdin

That’s it – We’re all set and can start deploying Serverless functions. 🎉

Creating and Deploying an OpenFaaS function

OpenFaaS offers different means and interfaces for deploying functions to the platform. We may use the CLI, the gateway UI, or the provided REST API, which is documented via this Swagger yaml.

Templates

The most straightforward way for getting started is via OpenFaaS’ template engine. With the faas-cli, we can create new functions based on available templates existing for various programming languages and tools. To get a list of all existing templates, you should run faas-cli template pull first. Running faas-cli new --list now, you should see a list of templates similar to the following:

csharp csharp-armhf dockerfile dockerfile-armhf go go-armhf java12 java8 node node-arm64 node-armhf node12 php7 python python-armhf python3 python3-armhf ruby

More templates are available via the OpenFaaS Store, which you can examine by running faas-cli template store list. Neither of both sources currently contains a Kotlin template, which I would love to change. Therefore, a change request is awaiting feedback and will hopefully add some official Kotlin to OpenFaaS.
On the bright side, it is quite easy to add my Kotlin templates to the cli by executing faas-cli template pull https://github.com/s1monw1/openfaas-kotlin. You should find two additional Kotlin variants now via faas-cli new --list. Let’s create a classic Kotlin function using the kotlin template:

faas-cli new hello-readers --lang=kotlin
# function can be found in ./hello-readers

By convention, OpenFaaS only exposes a particular part of each template to the user. If you want to look into that further, check out the Kotlin template and see how it is structured. The function is the one we have to deal with after running the faas-cli new command mentioned above.

Modify the template

In the newly generated function hello-readers, we can find a source file Handler.kt, which is the spot where we can implement the HTTP handling for our function. It’s a simple request-response mapper, and to demo it, we simply change the default body to "Hello kotlinexpertise readers".

class Handler : IHandler {
    override fun handle(request: IRequest): IResponse {
        return Response(body = "Hello kotlinexpertise readers")
    }
}

Build and Deploy

Build the function

Next to the hello-readers folder, OpenFaaS should have generated a YAML file called hello-readers.yml. It contains the information the cli needs to build and deploy our function. You can learn more about the relevant YAML structure and how you may want to modify it here. Let’s build it.

# by default, OpenFaaS looks for a stack.yml file which can be adjusted using the -f flag
faas-cli build -f hello-readers.yml 

OpenFaaS now runs the Dockerfile contained in the template (not visible to the user) to build the image which we can then deploy. There’s also a faas-cli up command available that wraps the build, push and deploy commands for our convenience. Either way, whether you use faas-cli up or faas-cli deploy, the result looks similar to the following output.

A successful deployment

> faas-cli deploy -f hello-readers.yml
Deploying: hello-readers.
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.

Deployed. 202 Accepted.
URL: http://127.0.0.1:31112/function/hello-readers

Clicking that URL reveals the message we previously configured: “Hello kotlinexpertise readers”. You can also examine the deployed function via the gateway UI.

Why would I use Kotlin to develop Serverless?

In the previous section, we saw that we could choose from a wide variety of programming languages to write Serverless functions for OpenFaaS. What language works best for you and makes the most sense depends on the use case and what you’re trying to achieve. Common Serverless languages are, e.g., Node, Python, and Go, but you’ll also find C#, Java, and even more in use.
Having a limited set of programming languages in a company probably leads to better internal tooling and also mitigates the issue of not being able to switch teams easily due to language barriers. I’m not a big fan of having hundreds of services all written in different languages, which most like would become problematic at some point. Most bigger tech companies limit their language portfolio and only add new ones if circumstances demand it.
I personally have been using Kotlin for almost four years now, and it was clear that I would also use it to explore the Serverless space. We at bryter have started using Kotlin Serverless functions not too long ago, and it’s working out well so far. Most of our backend services run Kotlin, and it’s the language we’re most experienced with. Nevertheless, we know that it might become necessary to add more languages, e.g., for performance reasons. The JVM footprint cannot be ignored and might impact performance here and there, for instance, when it comes to cold starts. To tweak things a bit, Graal VM could be a good option.
In a previous post, I wrote about the Server as a Function toolkit http4k, which is a fantastic library to enable Serverless functions in Kotlin. Http4k backs the functions we use at bryter, and I also proposed a corresponding template for the OpenFaaS store.

Serverless tooling for Kotlin

A pretty new framework named kotless (Kotlin Serverless) is currently being developed by Jetbrains with the goal of making it easy to turn Kotlin applications into ready-to-deploy functions and even handle the deployment which currently only works with AWS Lambda. The framework has a few very interesting features and I’m looking forward to see where kotless is heading.

Summary and Lookout

Serverless approaches and related architectural implications are relevant and something we should be aware of when considering approaches to modern software architecture. Functions as a service, as a Serverless related topic, has been around for a while. The big cloud players Amazon, Google, and Microsoft, provide the most prominent tools. Still, we can also get around vendor lock-in by opting to choose more independent platforms like the one I presented to you in this article: OpenFaaS. We saw that setting up OpenFaaS is no rocket science, and it can run on your local machine, which enables an excellent way to get started. You can choose from a big set of programming languages and just need to make sure that your code can be packaged as a Docker image to be able to deploy it to OpenFaaS. Templates can help with setting up functions quickly, and it’s not too hard to write your own function templates if necessary. I have shown an example of a Kotlin template and how the resulting HTTP handler (representing the function) looks like. Kotlin is a valid alternative amongst many others, and you should decide on a case-to-case basis, which programming language best suits your function’s needs. As I mentioned, I’ve been using the presented technologies for a while and currently work on a real-life use case to utilize that stuff to set up a dynamic, highly scalable and expandable platform, which I want to talk more about in upcoming articles.

The post Serverless Kotlin with OpenFaaS appeared first on Kotlin Expertise Blog.

Continue ReadingServerless Kotlin with OpenFaaS

Serverless Kotlin with OpenFaaS

Serverless Kotlin on OpenFaaS

With this article, my goal is to demonstrate how Serverless Kotlin can look like by introducing you to one of the coolest Serverless platforms: OpenFaaS. OpenFaaS is an open-source, community-owned project that you may use to run your functions and microservices on any public or private cloud. You can run your Docker image on OpenFaaS, which runs and scales it for you. As a result, you are free to choose any programming language as long as it can be packaged into a Docker image. Throughout this post, we want to learn about the concepts behind Serverless and Function as a Service (FaaS), and how we can deploy Serverless Kotlin functions to OpenFaaS.

Serverless and Function as a Service

Serverless Computing

With Serverless Computing, we describe a cloud model in which server management and infrastructure decisions don’t have to be tackled by the developers, but are taken care of by the cloud providers themselves. The term “Serverless” describes the fact that we don’t have to care much about infrastructure setup, scaling, and maintenance and that we can focus on developing code which can easily be deployed into production. The Serverless opportunities seem endless, and so does the landscape map published by the Cloud Native Computing Foundation (CNCF), which you can find here.

serverless-landscape

Serverless architecture is said to be the next big thing and somewhat the advancement of microservices: Monolith -> Microservices -> Serverless architecture

Function as a Service

One of the most essential Serverless offerings are so-called compute runtimes, also known as function as a service (FaaS) platforms. Many vendors provide these platforms, with the most prominent ones being AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. There are also open-source alternatives, such as Apache OpenWhisk or Oracle’s Fn Project. Many more tools and platforms exist, which are also part of the landscape map shown above.
The general idea behind FaaS is to offer a platform that can be used to execute code triggered by some event. The code can be deployed without maintaining infrastructure and just by uploading functionality to the cloud, which takes care of executing and also scaling the function. “Functions” in the context of FaaS are rather small units that generally should be stateless and can, as a result, easily be scaled horizontally. A FaaS platform will not only scale out your code if it’s under heavy load but also take care of removing instances if the function has not been invoked much for a while. This technique, for starters, helps to optimize costs but also requires awareness of cold start situations. Serverless overall has relevant positive characteristics and should be part of our discussions around reliable architecture alternatives. If you want to learn a bit more about the concepts and what Serverless architecture entails, I recommend watching “Serverless: the Future of Software Architecture” by Peter Sbarski. To be clear, I personally don’t believe that you should go Serverless no matter what, but rather see it as a valid concept that might solve parts of your problems.

OpenFaaS – Containers as Functions

OpenFaaS, as explained on their web site, “makes it simple to turn anything into a Serverless function that runs on Linux or Windows through Docker Swarm or Kubernetes”. They promise that it lets us run any code anywhere at any scale. You could describe OpenFaaS as a “containers as a function” platform since its form of abstracting functions is a Docker image. That characteristic is an excellent trait as it allows us to package any code into a Docker image, and OpenFaaS runs it, scales it, and also provides metrics for us. To be honest, it’s worth mentioning that a specific tool needs to be added to your containers, which is called Function Watchdog, a tiny Golang HTTP server which connects your function with the outside world. OpenFaaS itself runs on, e.g., Kubernetes or Docker Swarm is open source under MIT license, and is written in Go. You can find the GitHub project here.

No vendor lock-in

OpenFaaS relies on Docker images used to package our code, and the tool itself runs on platforms such as Kubernetes. The community has adopted all of these technologies and knows how to use them. As a result, you may move your OpenFaaS instance around to and from any public or private cloud without issue. OpenFaaS does not make you dependent on a particular vendor, which is contrary to what you get when relying on technologies like AWS Lambda. The fact of being dependent on a particular vendor is known as a vendor lock-in.

Other similar projects

The idea of deploying independent containers to a compute engine can be discovered in a few more projects. You can find a comparison of multiple similar tools here.

Serverless Kotlin deployed on OpenFaaS

Now that we’ve learned about the general ideas behind Serverless, FaaS and what OpenFaaS does, we want to get our hands a bit dirty by setting up an OpenFaaS Kubernetes cluster and learning how we can deploy functions to it.

OpenFaaS Deployment using Kubernetes

The following is based on the official guide. Read it to get more information and learn about alternative approaches.

As a first step, you need to make sure to have a Kubernetes cluster set up. If you want to run Kubernetes on a local machine, various tools can help you set up the cluster (e.g. k3s or minikube). On Mac and Windows, you can also use Docker’s desktop edition to run a Kubernetes cluster locally.
After having set up Kubernetes, we can start deploying OpenFaaS to the cluster. It’s incredibly easy using k3sup

# Install k3sup
curl -sLS https://get.k3sup.dev | sh
sudo install k3sup /usr/local/bin/ # <- this step might not be necessary
chmod +x k3sup
# applies openfaas namespaces, create user, applies helm chart
k3sup app install openfaas

After that, inspecting your cluster, you will find several running OpenFaaS pods.

You should be able to view the gateway UI via http://127.0.0.1:31112/ui/ where you log in using the credentials generated by k3sup. You can get the password via kubectl:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)

To allow faas-cli (needs to be installed) to access your newly deployed services, make sure to
1) set OPENFAAS_URL via export OPENFAAS_URL=http://127.0.0.1:31112
2) log in via faas-cli login --password {YOUR_PASSWORD_HERE}

The following script logs you in automatically:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
echo -n $PASSWORD | faas-cli login --username admin --password-stdin

That’s it – We’re all set and can start deploying Serverless functions. 🎉

Creating and Deploying an OpenFaaS function

OpenFaaS offers different means and interfaces for deploying functions to the platform. We may use the CLI, the gateway UI, or the provided REST API, which is documented via this Swagger yaml.

Templates

The most straightforward way for getting started is via OpenFaaS’ template engine. With the faas-cli, we can create new functions based on available templates existing for various programming languages and tools. To get a list of all existing templates, you should run faas-cli template pull first. Running faas-cli new --list now, you should see a list of templates similar to the following:

csharp csharp-armhf dockerfile dockerfile-armhf go go-armhf java12 java8 node node-arm64 node-armhf node12 php7 python python-armhf python3 python3-armhf ruby

More templates are available via the OpenFaaS Store, which you can examine by running faas-cli template store list. Neither of both sources currently contains a Kotlin template, which I would love to change. Therefore, a change request is awaiting feedback and will hopefully add some official Kotlin to OpenFaaS.
On the bright side, it is quite easy to add my Kotlin templates to the cli by executing faas-cli template pull https://github.com/s1monw1/openfaas-kotlin. You should find two additional Kotlin variants now via faas-cli new --list. Let’s create a classic Kotlin function using the kotlin template:

faas-cli new hello-readers --lang=kotlin
# function can be found in ./hello-readers

By convention, OpenFaaS only exposes a particular part of each template to the user. If you want to look into that further, check out the Kotlin template and see how it is structured. The function is the one we have to deal with after running the faas-cli new command mentioned above.

Modify the template

In the newly generated function hello-readers, we can find a source file Handler.kt, which is the spot where we can implement the HTTP handling for our function. It’s a simple request-response mapper, and to demo it, we simply change the default body to "Hello kotlinexpertise readers".

class Handler : IHandler {
    override fun handle(request: IRequest): IResponse {
        return Response(body = "Hello kotlinexpertise readers")
    }
}

Build and Deploy

Build the function

Next to the hello-readers folder, OpenFaaS should have generated a YAML file called hello-readers.yml. It contains the information the cli needs to build and deploy our function. You can learn more about the relevant YAML structure and how you may want to modify it here. Let’s build it.

# by default, OpenFaaS looks for a stack.yml file which can be adjusted using the -f flag
faas-cli build -f hello-readers.yml 

OpenFaaS now runs the Dockerfile contained in the template (not visible to the user) to build the image which we can then deploy. There’s also a faas-cli up command available that wraps the build, push and deploy commands for our convenience. Either way, whether you use faas-cli up or faas-cli deploy, the result looks similar to the following output.

A successful deployment

> faas-cli deploy -f hello-readers.yml
Deploying: hello-readers.
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.

Deployed. 202 Accepted.
URL: http://127.0.0.1:31112/function/hello-readers

Clicking that URL reveals the message we previously configured: “Hello kotlinexpertise readers”. You can also examine the deployed function via the gateway UI.

Why would I use Kotlin to develop Serverless?

In the previous section, we saw that we could choose from a wide variety of programming languages to write Serverless functions for OpenFaaS. What language works best for you and makes the most sense depends on the use case and what you’re trying to achieve. Common Serverless languages are, e.g., Node, Python, and Go, but you’ll also find C#, Java, and even more in use.
Having a limited set of programming languages in a company probably leads to better internal tooling and also mitigates the issue of not being able to switch teams easily due to language barriers. I’m not a big fan of having hundreds of services all written in different languages, which most like would become problematic at some point. Most bigger tech companies limit their language portfolio and only add new ones if circumstances demand it.
I personally have been using Kotlin for almost four years now, and it was clear that I would also use it to explore the Serverless space. We at bryter have started using Kotlin Serverless functions not too long ago, and it’s working out well so far. Most of our backend services run Kotlin, and it’s the language we’re most experienced with. Nevertheless, we know that it might become necessary to add more languages, e.g., for performance reasons. The JVM footprint cannot be ignored and might impact performance here and there, for instance, when it comes to cold starts. To tweak things a bit, Graal VM could be a good option.
In a previous post, I wrote about the Server as a Function toolkit http4k, which is a fantastic library to enable Serverless functions in Kotlin. Http4k backs the functions we use at bryter, and I also proposed a corresponding template for the OpenFaaS store.

Serverless tooling for Kotlin

A pretty new framework named kotless (Kotlin Serverless) is currently being developed by Jetbrains with the goal of making it easy to turn Kotlin applications into ready-to-deploy functions and even handle the deployment which currently only works with AWS Lambda. The framework has a few very interesting features and I’m looking forward to see where kotless is heading.

Summary and Lookout

Serverless approaches and related architectural implications are relevant and something we should be aware of when considering approaches to modern software architecture. Functions as a service, as a Serverless related topic, has been around for a while. The big cloud players Amazon, Google, and Microsoft, provide the most prominent tools. Still, we can also get around vendor lock-in by opting to choose more independent platforms like the one I presented to you in this article: OpenFaaS. We saw that setting up OpenFaaS is no rocket science, and it can run on your local machine, which enables an excellent way to get started. You can choose from a big set of programming languages and just need to make sure that your code can be packaged as a Docker image to be able to deploy it to OpenFaaS. Templates can help with setting up functions quickly, and it’s not too hard to write your own function templates if necessary. I have shown an example of a Kotlin template and how the resulting HTTP handler (representing the function) looks like. Kotlin is a valid alternative amongst many others, and you should decide on a case-to-case basis, which programming language best suits your function’s needs. As I mentioned, I’ve been using the presented technologies for a while and currently work on a real-life use case to utilize that stuff to set up a dynamic, highly scalable and expandable platform, which I want to talk more about in upcoming articles.

The post Serverless Kotlin with OpenFaaS appeared first on Kotlin Expertise Blog.

Continue ReadingServerless Kotlin with OpenFaaS

Serverless Kotlin with OpenFaaS

Serverless Kotlin on OpenFaaS

With this article, my goal is to demonstrate how Serverless Kotlin can look like by introducing you to one of the coolest Serverless platforms: OpenFaaS. OpenFaaS is an open-source, community-owned project that you may use to run your functions and microservices on any public or private cloud. You can run your Docker image on OpenFaaS, which runs and scales it for you. As a result, you are free to choose any programming language as long as it can be packaged into a Docker image. Throughout this post, we want to learn about the concepts behind Serverless and Function as a Service (FaaS), and how we can deploy Serverless Kotlin functions to OpenFaaS.

Serverless and Function as a Service

Serverless Computing

With Serverless Computing, we describe a cloud model in which server management and infrastructure decisions don’t have to be tackled by the developers, but are taken care of by the cloud providers themselves. The term “Serverless” describes the fact that we don’t have to care much about infrastructure setup, scaling, and maintenance and that we can focus on developing code which can easily be deployed into production. The Serverless opportunities seem endless, and so does the landscape map published by the Cloud Native Computing Foundation (CNCF), which you can find here.

serverless-landscape

Serverless architecture is said to be the next big thing and somewhat the advancement of microservices: Monolith -> Microservices -> Serverless architecture

Function as a Service

One of the most essential Serverless offerings are so-called compute runtimes, also known as function as a service (FaaS) platforms. Many vendors provide these platforms, with the most prominent ones being AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. There are also open-source alternatives, such as Apache OpenWhisk or Oracle’s Fn Project. Many more tools and platforms exist, which are also part of the landscape map shown above.
The general idea behind FaaS is to offer a platform that can be used to execute code triggered by some event. The code can be deployed without maintaining infrastructure and just by uploading functionality to the cloud, which takes care of executing and also scaling the function. “Functions” in the context of FaaS are rather small units that generally should be stateless and can, as a result, easily be scaled horizontally. A FaaS platform will not only scale out your code if it’s under heavy load but also take care of removing instances if the function has not been invoked much for a while. This technique, for starters, helps to optimize costs but also requires awareness of cold start situations. Serverless overall has relevant positive characteristics and should be part of our discussions around reliable architecture alternatives. If you want to learn a bit more about the concepts and what Serverless architecture entails, I recommend watching “Serverless: the Future of Software Architecture” by Peter Sbarski. To be clear, I personally don’t believe that you should go Serverless no matter what, but rather see it as a valid concept that might solve parts of your problems.

OpenFaaS – Containers as Functions

OpenFaaS, as explained on their web site, “makes it simple to turn anything into a Serverless function that runs on Linux or Windows through Docker Swarm or Kubernetes”. They promise that it lets us run any code anywhere at any scale. You could describe OpenFaaS as a “containers as a function” platform since its form of abstracting functions is a Docker image. That characteristic is an excellent trait as it allows us to package any code into a Docker image, and OpenFaaS runs it, scales it, and also provides metrics for us. To be honest, it’s worth mentioning that a specific tool needs to be added to your containers, which is called Function Watchdog, a tiny Golang HTTP server which connects your function with the outside world. OpenFaaS itself runs on, e.g., Kubernetes or Docker Swarm is open source under MIT license, and is written in Go. You can find the GitHub project here.

No vendor lock-in

OpenFaaS relies on Docker images used to package our code, and the tool itself runs on platforms such as Kubernetes. The community has adopted all of these technologies and knows how to use them. As a result, you may move your OpenFaaS instance around to and from any public or private cloud without issue. OpenFaaS does not make you dependent on a particular vendor, which is contrary to what you get when relying on technologies like AWS Lambda. The fact of being dependent on a particular vendor is known as a vendor lock-in.

Other similar projects

The idea of deploying independent containers to a compute engine can be discovered in a few more projects. You can find a comparison of multiple similar tools here.

Serverless Kotlin deployed on OpenFaaS

Now that we’ve learned about the general ideas behind Serverless, FaaS and what OpenFaaS does, we want to get our hands a bit dirty by setting up an OpenFaaS Kubernetes cluster and learning how we can deploy functions to it.

OpenFaaS Deployment using Kubernetes

The following is based on the official guide. Read it to get more information and learn about alternative approaches.

As a first step, you need to make sure to have a Kubernetes cluster set up. If you want to run Kubernetes on a local machine, various tools can help you set up the cluster (e.g. k3s or minikube). On Mac and Windows, you can also use Docker’s desktop edition to run a Kubernetes cluster locally.
After having set up Kubernetes, we can start deploying OpenFaaS to the cluster. It’s incredibly easy using k3sup

# Install k3sup
curl -sLS https://get.k3sup.dev | sh
sudo install k3sup /usr/local/bin/ # <- this step might not be necessary
chmod +x k3sup
# applies openfaas namespaces, create user, applies helm chart
k3sup app install openfaas

After that, inspecting your cluster, you will find several running OpenFaaS pods.

You should be able to view the gateway UI via http://127.0.0.1:31112/ui/ where you log in using the credentials generated by k3sup. You can get the password via kubectl:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)

To allow faas-cli (needs to be installed) to access your newly deployed services, make sure to
1) set OPENFAAS_URL via export OPENFAAS_URL=http://127.0.0.1:31112
2) log in via faas-cli login --password {YOUR_PASSWORD_HERE}

The following script logs you in automatically:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
echo -n $PASSWORD | faas-cli login --username admin --password-stdin

That’s it – We’re all set and can start deploying Serverless functions. 🎉

Creating and Deploying an OpenFaaS function

OpenFaaS offers different means and interfaces for deploying functions to the platform. We may use the CLI, the gateway UI, or the provided REST API, which is documented via this Swagger yaml.

Templates

The most straightforward way for getting started is via OpenFaaS’ template engine. With the faas-cli, we can create new functions based on available templates existing for various programming languages and tools. To get a list of all existing templates, you should run faas-cli template pull first. Running faas-cli new --list now, you should see a list of templates similar to the following:

csharp csharp-armhf dockerfile dockerfile-armhf go go-armhf java12 java8 node node-arm64 node-armhf node12 php7 python python-armhf python3 python3-armhf ruby

More templates are available via the OpenFaaS Store, which you can examine by running faas-cli template store list. Neither of both sources currently contains a Kotlin template, which I would love to change. Therefore, a change request is awaiting feedback and will hopefully add some official Kotlin to OpenFaaS.
On the bright side, it is quite easy to add my Kotlin templates to the cli by executing faas-cli template pull https://github.com/s1monw1/openfaas-kotlin. You should find two additional Kotlin variants now via faas-cli new --list. Let’s create a classic Kotlin function using the kotlin template:

faas-cli new hello-readers --lang=kotlin
# function can be found in ./hello-readers

By convention, OpenFaaS only exposes a particular part of each template to the user. If you want to look into that further, check out the Kotlin template and see how it is structured. The function is the one we have to deal with after running the faas-cli new command mentioned above.

Modify the template

In the newly generated function hello-readers, we can find a source file Handler.kt, which is the spot where we can implement the HTTP handling for our function. It’s a simple request-response mapper, and to demo it, we simply change the default body to "Hello kotlinexpertise readers".

class Handler : IHandler {
    override fun handle(request: IRequest): IResponse {
        return Response(body = "Hello kotlinexpertise readers")
    }
}

Build and Deploy

Build the function

Next to the hello-readers folder, OpenFaaS should have generated a YAML file called hello-readers.yml. It contains the information the cli needs to build and deploy our function. You can learn more about the relevant YAML structure and how you may want to modify it here. Let’s build it.

# by default, OpenFaaS looks for a stack.yml file which can be adjusted using the -f flag
faas-cli build -f hello-readers.yml 

OpenFaaS now runs the Dockerfile contained in the template (not visible to the user) to build the image which we can then deploy. There’s also a faas-cli up command available that wraps the build, push and deploy commands for our convenience. Either way, whether you use faas-cli up or faas-cli deploy, the result looks similar to the following output.

A successful deployment

> faas-cli deploy -f hello-readers.yml
Deploying: hello-readers.
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.

Deployed. 202 Accepted.
URL: http://127.0.0.1:31112/function/hello-readers

Clicking that URL reveals the message we previously configured: “Hello kotlinexpertise readers”. You can also examine the deployed function via the gateway UI.

Why would I use Kotlin to develop Serverless?

In the previous section, we saw that we could choose from a wide variety of programming languages to write Serverless functions for OpenFaaS. What language works best for you and makes the most sense depends on the use case and what you’re trying to achieve. Common Serverless languages are, e.g., Node, Python, and Go, but you’ll also find C#, Java, and even more in use.
Having a limited set of programming languages in a company probably leads to better internal tooling and also mitigates the issue of not being able to switch teams easily due to language barriers. I’m not a big fan of having hundreds of services all written in different languages, which most like would become problematic at some point. Most bigger tech companies limit their language portfolio and only add new ones if circumstances demand it.
I personally have been using Kotlin for almost four years now, and it was clear that I would also use it to explore the Serverless space. We at bryter have started using Kotlin Serverless functions not too long ago, and it’s working out well so far. Most of our backend services run Kotlin, and it’s the language we’re most experienced with. Nevertheless, we know that it might become necessary to add more languages, e.g., for performance reasons. The JVM footprint cannot be ignored and might impact performance here and there, for instance, when it comes to cold starts. To tweak things a bit, Graal VM could be a good option.
In a previous post, I wrote about the Server as a Function toolkit http4k, which is a fantastic library to enable Serverless functions in Kotlin. Http4k backs the functions we use at bryter, and I also proposed a corresponding template for the OpenFaaS store.

Serverless tooling for Kotlin

A pretty new framework named kotless (Kotlin Serverless) is currently being developed by Jetbrains with the goal of making it easy to turn Kotlin applications into ready-to-deploy functions and even handle the deployment which currently only works with AWS Lambda. The framework has a few very interesting features and I’m looking forward to see where kotless is heading.

Summary and Lookout

Serverless approaches and related architectural implications are relevant and something we should be aware of when considering approaches to modern software architecture. Functions as a service, as a Serverless related topic, has been around for a while. The big cloud players Amazon, Google, and Microsoft, provide the most prominent tools. Still, we can also get around vendor lock-in by opting to choose more independent platforms like the one I presented to you in this article: OpenFaaS. We saw that setting up OpenFaaS is no rocket science, and it can run on your local machine, which enables an excellent way to get started. You can choose from a big set of programming languages and just need to make sure that your code can be packaged as a Docker image to be able to deploy it to OpenFaaS. Templates can help with setting up functions quickly, and it’s not too hard to write your own function templates if necessary. I have shown an example of a Kotlin template and how the resulting HTTP handler (representing the function) looks like. Kotlin is a valid alternative amongst many others, and you should decide on a case-to-case basis, which programming language best suits your function’s needs. As I mentioned, I’ve been using the presented technologies for a while and currently work on a real-life use case to utilize that stuff to set up a dynamic, highly scalable and expandable platform, which I want to talk more about in upcoming articles.

The post Serverless Kotlin with OpenFaaS appeared first on Kotlin Expertise Blog.

Continue ReadingServerless Kotlin with OpenFaaS

Serverless Kotlin with OpenFaaS

Serverless Kotlin on OpenFaaS

With this article, my goal is to demonstrate how Serverless Kotlin can look like by introducing you to one of the coolest Serverless platforms: OpenFaaS. OpenFaaS is an open-source, community-owned project that you may use to run your functions and microservices on any public or private cloud. You can run your Docker image on OpenFaaS, which runs and scales it for you. As a result, you are free to choose any programming language as long as it can be packaged into a Docker image. Throughout this post, we want to learn about the concepts behind Serverless and Function as a Service (FaaS), and how we can deploy Serverless Kotlin functions to OpenFaaS.

Serverless and Function as a Service

Serverless Computing

With Serverless Computing, we describe a cloud model in which server management and infrastructure decisions don’t have to be tackled by the developers, but are taken care of by the cloud providers themselves. The term “Serverless” describes the fact that we don’t have to care much about infrastructure setup, scaling, and maintenance and that we can focus on developing code which can easily be deployed into production. The Serverless opportunities seem endless, and so does the landscape map published by the Cloud Native Computing Foundation (CNCF), which you can find here.

serverless-landscape

Serverless architecture is said to be the next big thing and somewhat the advancement of microservices: Monolith -> Microservices -> Serverless architecture

Function as a Service

One of the most essential Serverless offerings are so-called compute runtimes, also known as function as a service (FaaS) platforms. Many vendors provide these platforms, with the most prominent ones being AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. There are also open-source alternatives, such as Apache OpenWhisk or Oracle’s Fn Project. Many more tools and platforms exist, which are also part of the landscape map shown above.
The general idea behind FaaS is to offer a platform that can be used to execute code triggered by some event. The code can be deployed without maintaining infrastructure and just by uploading functionality to the cloud, which takes care of executing and also scaling the function. “Functions” in the context of FaaS are rather small units that generally should be stateless and can, as a result, easily be scaled horizontally. A FaaS platform will not only scale out your code if it’s under heavy load but also take care of removing instances if the function has not been invoked much for a while. This technique, for starters, helps to optimize costs but also requires awareness of cold start situations. Serverless overall has relevant positive characteristics and should be part of our discussions around reliable architecture alternatives. If you want to learn a bit more about the concepts and what Serverless architecture entails, I recommend watching “Serverless: the Future of Software Architecture” by Peter Sbarski. To be clear, I personally don’t believe that you should go Serverless no matter what, but rather see it as a valid concept that might solve parts of your problems.

OpenFaaS – Containers as Functions

OpenFaaS, as explained on their web site, “makes it simple to turn anything into a Serverless function that runs on Linux or Windows through Docker Swarm or Kubernetes”. They promise that it lets us run any code anywhere at any scale. You could describe OpenFaaS as a “containers as a function” platform since its form of abstracting functions is a Docker image. That characteristic is an excellent trait as it allows us to package any code into a Docker image, and OpenFaaS runs it, scales it, and also provides metrics for us. To be honest, it’s worth mentioning that a specific tool needs to be added to your containers, which is called Function Watchdog, a tiny Golang HTTP server which connects your function with the outside world. OpenFaaS itself runs on, e.g., Kubernetes or Docker Swarm is open source under MIT license, and is written in Go. You can find the GitHub project here.

No vendor lock-in

OpenFaaS relies on Docker images used to package our code, and the tool itself runs on platforms such as Kubernetes. The community has adopted all of these technologies and knows how to use them. As a result, you may move your OpenFaaS instance around to and from any public or private cloud without issue. OpenFaaS does not make you dependent on a particular vendor, which is contrary to what you get when relying on technologies like AWS Lambda. The fact of being dependent on a particular vendor is known as a vendor lock-in.

Other similar projects

The idea of deploying independent containers to a compute engine can be discovered in a few more projects. You can find a comparison of multiple similar tools here.

Serverless Kotlin deployed on OpenFaaS

Now that we’ve learned about the general ideas behind Serverless, FaaS and what OpenFaaS does, we want to get our hands a bit dirty by setting up an OpenFaaS Kubernetes cluster and learning how we can deploy functions to it.

OpenFaaS Deployment using Kubernetes

The following is based on the official guide. Read it to get more information and learn about alternative approaches.

As a first step, you need to make sure to have a Kubernetes cluster set up. If you want to run Kubernetes on a local machine, various tools can help you set up the cluster (e.g. k3s or minikube). On Mac and Windows, you can also use Docker’s desktop edition to run a Kubernetes cluster locally.
After having set up Kubernetes, we can start deploying OpenFaaS to the cluster. It’s incredibly easy using k3sup

# Install k3sup
curl -sLS https://get.k3sup.dev | sh
sudo install k3sup /usr/local/bin/ # <- this step might not be necessary
chmod +x k3sup
# applies openfaas namespaces, create user, applies helm chart
k3sup app install openfaas

After that, inspecting your cluster, you will find several running OpenFaaS pods.

You should be able to view the gateway UI via http://127.0.0.1:31112/ui/ where you log in using the credentials generated by k3sup. You can get the password via kubectl:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)

To allow faas-cli (needs to be installed) to access your newly deployed services, make sure to
1) set OPENFAAS_URL via export OPENFAAS_URL=http://127.0.0.1:31112
2) log in via faas-cli login --password {YOUR_PASSWORD_HERE}

The following script logs you in automatically:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
echo -n $PASSWORD | faas-cli login --username admin --password-stdin

That’s it – We’re all set and can start deploying Serverless functions. 🎉

Creating and Deploying an OpenFaaS function

OpenFaaS offers different means and interfaces for deploying functions to the platform. We may use the CLI, the gateway UI, or the provided REST API, which is documented via this Swagger yaml.

Templates

The most straightforward way for getting started is via OpenFaaS’ template engine. With the faas-cli, we can create new functions based on available templates existing for various programming languages and tools. To get a list of all existing templates, you should run faas-cli template pull first. Running faas-cli new --list now, you should see a list of templates similar to the following:

csharp csharp-armhf dockerfile dockerfile-armhf go go-armhf java12 java8 node node-arm64 node-armhf node12 php7 python python-armhf python3 python3-armhf ruby

More templates are available via the OpenFaaS Store, which you can examine by running faas-cli template store list. Neither of both sources currently contains a Kotlin template, which I would love to change. Therefore, a change request is awaiting feedback and will hopefully add some official Kotlin to OpenFaaS.
On the bright side, it is quite easy to add my Kotlin templates to the cli by executing faas-cli template pull https://github.com/s1monw1/openfaas-kotlin. You should find two additional Kotlin variants now via faas-cli new --list. Let’s create a classic Kotlin function using the kotlin template:

faas-cli new hello-readers --lang=kotlin
# function can be found in ./hello-readers

By convention, OpenFaaS only exposes a particular part of each template to the user. If you want to look into that further, check out the Kotlin template and see how it is structured. The function is the one we have to deal with after running the faas-cli new command mentioned above.

Modify the template

In the newly generated function hello-readers, we can find a source file Handler.kt, which is the spot where we can implement the HTTP handling for our function. It’s a simple request-response mapper, and to demo it, we simply change the default body to "Hello kotlinexpertise readers".

class Handler : IHandler {
    override fun handle(request: IRequest): IResponse {
        return Response(body = "Hello kotlinexpertise readers")
    }
}

Build and Deploy

Build the function

Next to the hello-readers folder, OpenFaaS should have generated a YAML file called hello-readers.yml. It contains the information the cli needs to build and deploy our function. You can learn more about the relevant YAML structure and how you may want to modify it here. Let’s build it.

# by default, OpenFaaS looks for a stack.yml file which can be adjusted using the -f flag
faas-cli build -f hello-readers.yml 

OpenFaaS now runs the Dockerfile contained in the template (not visible to the user) to build the image which we can then deploy. There’s also a faas-cli up command available that wraps the build, push and deploy commands for our convenience. Either way, whether you use faas-cli up or faas-cli deploy, the result looks similar to the following output.

A successful deployment

> faas-cli deploy -f hello-readers.yml
Deploying: hello-readers.
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.

Deployed. 202 Accepted.
URL: http://127.0.0.1:31112/function/hello-readers

Clicking that URL reveals the message we previously configured: “Hello kotlinexpertise readers”. You can also examine the deployed function via the gateway UI.

Why would I use Kotlin to develop Serverless?

In the previous section, we saw that we could choose from a wide variety of programming languages to write Serverless functions for OpenFaaS. What language works best for you and makes the most sense depends on the use case and what you’re trying to achieve. Common Serverless languages are, e.g., Node, Python, and Go, but you’ll also find C#, Java, and even more in use.
Having a limited set of programming languages in a company probably leads to better internal tooling and also mitigates the issue of not being able to switch teams easily due to language barriers. I’m not a big fan of having hundreds of services all written in different languages, which most like would become problematic at some point. Most bigger tech companies limit their language portfolio and only add new ones if circumstances demand it.
I personally have been using Kotlin for almost four years now, and it was clear that I would also use it to explore the Serverless space. We at bryter have started using Kotlin Serverless functions not too long ago, and it’s working out well so far. Most of our backend services run Kotlin, and it’s the language we’re most experienced with. Nevertheless, we know that it might become necessary to add more languages, e.g., for performance reasons. The JVM footprint cannot be ignored and might impact performance here and there, for instance, when it comes to cold starts. To tweak things a bit, Graal VM could be a good option.
In a previous post, I wrote about the Server as a Function toolkit http4k, which is a fantastic library to enable Serverless functions in Kotlin. Http4k backs the functions we use at bryter, and I also proposed a corresponding template for the OpenFaaS store.

Serverless tooling for Kotlin

A pretty new framework named kotless (Kotlin Serverless) is currently being developed by Jetbrains with the goal of making it easy to turn Kotlin applications into ready-to-deploy functions and even handle the deployment which currently only works with AWS Lambda. The framework has a few very interesting features and I’m looking forward to see where kotless is heading.

Summary and Lookout

Serverless approaches and related architectural implications are relevant and something we should be aware of when considering approaches to modern software architecture. Functions as a service, as a Serverless related topic, has been around for a while. The big cloud players Amazon, Google, and Microsoft, provide the most prominent tools. Still, we can also get around vendor lock-in by opting to choose more independent platforms like the one I presented to you in this article: OpenFaaS. We saw that setting up OpenFaaS is no rocket science, and it can run on your local machine, which enables an excellent way to get started. You can choose from a big set of programming languages and just need to make sure that your code can be packaged as a Docker image to be able to deploy it to OpenFaaS. Templates can help with setting up functions quickly, and it’s not too hard to write your own function templates if necessary. I have shown an example of a Kotlin template and how the resulting HTTP handler (representing the function) looks like. Kotlin is a valid alternative amongst many others, and you should decide on a case-to-case basis, which programming language best suits your function’s needs. As I mentioned, I’ve been using the presented technologies for a while and currently work on a real-life use case to utilize that stuff to set up a dynamic, highly scalable and expandable platform, which I want to talk more about in upcoming articles.

The post Serverless Kotlin with OpenFaaS appeared first on Kotlin Expertise Blog.

Continue ReadingServerless Kotlin with OpenFaaS

Serverless Kotlin with OpenFaaS

Serverless Kotlin on OpenFaaS

With this article, my goal is to demonstrate how Serverless Kotlin can look like by introducing you to one of the coolest Serverless platforms: OpenFaaS. OpenFaaS is an open-source, community-owned project that you may use to run your functions and microservices on any public or private cloud. You can run your Docker image on OpenFaaS, which runs and scales it for you. As a result, you are free to choose any programming language as long as it can be packaged into a Docker image. Throughout this post, we want to learn about the concepts behind Serverless and Function as a Service (FaaS), and how we can deploy Serverless Kotlin functions to OpenFaaS.

Serverless and Function as a Service

Serverless Computing

With Serverless Computing, we describe a cloud model in which server management and infrastructure decisions don’t have to be tackled by the developers, but are taken care of by the cloud providers themselves. The term “Serverless” describes the fact that we don’t have to care much about infrastructure setup, scaling, and maintenance and that we can focus on developing code which can easily be deployed into production. The Serverless opportunities seem endless, and so does the landscape map published by the Cloud Native Computing Foundation (CNCF), which you can find here.

serverless-landscape

Serverless architecture is said to be the next big thing and somewhat the advancement of microservices: Monolith -> Microservices -> Serverless architecture

Function as a Service

One of the most essential Serverless offerings are so-called compute runtimes, also known as function as a service (FaaS) platforms. Many vendors provide these platforms, with the most prominent ones being AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. There are also open-source alternatives, such as Apache OpenWhisk or Oracle’s Fn Project. Many more tools and platforms exist, which are also part of the landscape map shown above.
The general idea behind FaaS is to offer a platform that can be used to execute code triggered by some event. The code can be deployed without maintaining infrastructure and just by uploading functionality to the cloud, which takes care of executing and also scaling the function. “Functions” in the context of FaaS are rather small units that generally should be stateless and can, as a result, easily be scaled horizontally. A FaaS platform will not only scale out your code if it’s under heavy load but also take care of removing instances if the function has not been invoked much for a while. This technique, for starters, helps to optimize costs but also requires awareness of cold start situations. Serverless overall has relevant positive characteristics and should be part of our discussions around reliable architecture alternatives. If you want to learn a bit more about the concepts and what Serverless architecture entails, I recommend watching “Serverless: the Future of Software Architecture” by Peter Sbarski. To be clear, I personally don’t believe that you should go Serverless no matter what, but rather see it as a valid concept that might solve parts of your problems.

OpenFaaS – Containers as Functions

OpenFaaS, as explained on their web site, “makes it simple to turn anything into a Serverless function that runs on Linux or Windows through Docker Swarm or Kubernetes”. They promise that it lets us run any code anywhere at any scale. You could describe OpenFaaS as a “containers as a function” platform since its form of abstracting functions is a Docker image. That characteristic is an excellent trait as it allows us to package any code into a Docker image, and OpenFaaS runs it, scales it, and also provides metrics for us. To be honest, it’s worth mentioning that a specific tool needs to be added to your containers, which is called Function Watchdog, a tiny Golang HTTP server which connects your function with the outside world. OpenFaaS itself runs on, e.g., Kubernetes or Docker Swarm is open source under MIT license, and is written in Go. You can find the GitHub project here.

No vendor lock-in

OpenFaaS relies on Docker images used to package our code, and the tool itself runs on platforms such as Kubernetes. The community has adopted all of these technologies and knows how to use them. As a result, you may move your OpenFaaS instance around to and from any public or private cloud without issue. OpenFaaS does not make you dependent on a particular vendor, which is contrary to what you get when relying on technologies like AWS Lambda. The fact of being dependent on a particular vendor is known as a vendor lock-in.

Other similar projects

The idea of deploying independent containers to a compute engine can be discovered in a few more projects. You can find a comparison of multiple similar tools here.

Serverless Kotlin deployed on OpenFaaS

Now that we’ve learned about the general ideas behind Serverless, FaaS and what OpenFaaS does, we want to get our hands a bit dirty by setting up an OpenFaaS Kubernetes cluster and learning how we can deploy functions to it.

OpenFaaS Deployment using Kubernetes

The following is based on the official guide. Read it to get more information and learn about alternative approaches.

As a first step, you need to make sure to have a Kubernetes cluster set up. If you want to run Kubernetes on a local machine, various tools can help you set up the cluster (e.g. k3s or minikube). On Mac and Windows, you can also use Docker’s desktop edition to run a Kubernetes cluster locally.
After having set up Kubernetes, we can start deploying OpenFaaS to the cluster. It’s incredibly easy using k3sup

# Install k3sup
curl -sLS https://get.k3sup.dev | sh
sudo install k3sup /usr/local/bin/ # <- this step might not be necessary
chmod +x k3sup
# applies openfaas namespaces, create user, applies helm chart
k3sup app install openfaas

After that, inspecting your cluster, you will find several running OpenFaaS pods.

You should be able to view the gateway UI via http://127.0.0.1:31112/ui/ where you log in using the credentials generated by k3sup. You can get the password via kubectl:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)

To allow faas-cli (needs to be installed) to access your newly deployed services, make sure to
1) set OPENFAAS_URL via export OPENFAAS_URL=http://127.0.0.1:31112
2) log in via faas-cli login --password {YOUR_PASSWORD_HERE}

The following script logs you in automatically:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
echo -n $PASSWORD | faas-cli login --username admin --password-stdin

That’s it – We’re all set and can start deploying Serverless functions. 🎉

Creating and Deploying an OpenFaaS function

OpenFaaS offers different means and interfaces for deploying functions to the platform. We may use the CLI, the gateway UI, or the provided REST API, which is documented via this Swagger yaml.

Templates

The most straightforward way for getting started is via OpenFaaS’ template engine. With the faas-cli, we can create new functions based on available templates existing for various programming languages and tools. To get a list of all existing templates, you should run faas-cli template pull first. Running faas-cli new --list now, you should see a list of templates similar to the following:

csharp csharp-armhf dockerfile dockerfile-armhf go go-armhf java12 java8 node node-arm64 node-armhf node12 php7 python python-armhf python3 python3-armhf ruby

More templates are available via the OpenFaaS Store, which you can examine by running faas-cli template store list. Neither of both sources currently contains a Kotlin template, which I would love to change. Therefore, a change request is awaiting feedback and will hopefully add some official Kotlin to OpenFaaS.
On the bright side, it is quite easy to add my Kotlin templates to the cli by executing faas-cli template pull https://github.com/s1monw1/openfaas-kotlin. You should find two additional Kotlin variants now via faas-cli new --list. Let’s create a classic Kotlin function using the kotlin template:

faas-cli new hello-readers --lang=kotlin
# function can be found in ./hello-readers

By convention, OpenFaaS only exposes a particular part of each template to the user. If you want to look into that further, check out the Kotlin template and see how it is structured. The function is the one we have to deal with after running the faas-cli new command mentioned above.

Modify the template

In the newly generated function hello-readers, we can find a source file Handler.kt, which is the spot where we can implement the HTTP handling for our function. It’s a simple request-response mapper, and to demo it, we simply change the default body to "Hello kotlinexpertise readers".

class Handler : IHandler {
    override fun handle(request: IRequest): IResponse {
        return Response(body = "Hello kotlinexpertise readers")
    }
}

Build and Deploy

Build the function

Next to the hello-readers folder, OpenFaaS should have generated a YAML file called hello-readers.yml. It contains the information the cli needs to build and deploy our function. You can learn more about the relevant YAML structure and how you may want to modify it here. Let’s build it.

# by default, OpenFaaS looks for a stack.yml file which can be adjusted using the -f flag
faas-cli build -f hello-readers.yml 

OpenFaaS now runs the Dockerfile contained in the template (not visible to the user) to build the image which we can then deploy. There’s also a faas-cli up command available that wraps the build, push and deploy commands for our convenience. Either way, whether you use faas-cli up or faas-cli deploy, the result looks similar to the following output.

A successful deployment

> faas-cli deploy -f hello-readers.yml
Deploying: hello-readers.
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.

Deployed. 202 Accepted.
URL: http://127.0.0.1:31112/function/hello-readers

Clicking that URL reveals the message we previously configured: “Hello kotlinexpertise readers”. You can also examine the deployed function via the gateway UI.

Why would I use Kotlin to develop Serverless?

In the previous section, we saw that we could choose from a wide variety of programming languages to write Serverless functions for OpenFaaS. What language works best for you and makes the most sense depends on the use case and what you’re trying to achieve. Common Serverless languages are, e.g., Node, Python, and Go, but you’ll also find C#, Java, and even more in use.
Having a limited set of programming languages in a company probably leads to better internal tooling and also mitigates the issue of not being able to switch teams easily due to language barriers. I’m not a big fan of having hundreds of services all written in different languages, which most like would become problematic at some point. Most bigger tech companies limit their language portfolio and only add new ones if circumstances demand it.
I personally have been using Kotlin for almost four years now, and it was clear that I would also use it to explore the Serverless space. We at bryter have started using Kotlin Serverless functions not too long ago, and it’s working out well so far. Most of our backend services run Kotlin, and it’s the language we’re most experienced with. Nevertheless, we know that it might become necessary to add more languages, e.g., for performance reasons. The JVM footprint cannot be ignored and might impact performance here and there, for instance, when it comes to cold starts. To tweak things a bit, Graal VM could be a good option.
In a previous post, I wrote about the Server as a Function toolkit http4k, which is a fantastic library to enable Serverless functions in Kotlin. Http4k backs the functions we use at bryter, and I also proposed a corresponding template for the OpenFaaS store.

Serverless tooling for Kotlin

A pretty new framework named kotless (Kotlin Serverless) is currently being developed by Jetbrains with the goal of making it easy to turn Kotlin applications into ready-to-deploy functions and even handle the deployment which currently only works with AWS Lambda. The framework has a few very interesting features and I’m looking forward to see where kotless is heading.

Summary and Lookout

Serverless approaches and related architectural implications are relevant and something we should be aware of when considering approaches to modern software architecture. Functions as a service, as a Serverless related topic, has been around for a while. The big cloud players Amazon, Google, and Microsoft, provide the most prominent tools. Still, we can also get around vendor lock-in by opting to choose more independent platforms like the one I presented to you in this article: OpenFaaS. We saw that setting up OpenFaaS is no rocket science, and it can run on your local machine, which enables an excellent way to get started. You can choose from a big set of programming languages and just need to make sure that your code can be packaged as a Docker image to be able to deploy it to OpenFaaS. Templates can help with setting up functions quickly, and it’s not too hard to write your own function templates if necessary. I have shown an example of a Kotlin template and how the resulting HTTP handler (representing the function) looks like. Kotlin is a valid alternative amongst many others, and you should decide on a case-to-case basis, which programming language best suits your function’s needs. As I mentioned, I’ve been using the presented technologies for a while and currently work on a real-life use case to utilize that stuff to set up a dynamic, highly scalable and expandable platform, which I want to talk more about in upcoming articles.

The post Serverless Kotlin with OpenFaaS appeared first on Kotlin Expertise Blog.

Continue ReadingServerless Kotlin with OpenFaaS

Serverless Kotlin with OpenFaaS

Serverless Kotlin on OpenFaaS

With this article, my goal is to demonstrate how Serverless Kotlin can look like by introducing you to one of the coolest Serverless platforms: OpenFaaS. OpenFaaS is an open-source, community-owned project that you may use to run your functions and microservices on any public or private cloud. You can run your Docker image on OpenFaaS, which runs and scales it for you. As a result, you are free to choose any programming language as long as it can be packaged into a Docker image. Throughout this post, we want to learn about the concepts behind Serverless and Function as a Service (FaaS), and how we can deploy Serverless Kotlin functions to OpenFaaS.

Serverless and Function as a Service

Serverless Computing

With Serverless Computing, we describe a cloud model in which server management and infrastructure decisions don’t have to be tackled by the developers, but are taken care of by the cloud providers themselves. The term “Serverless” describes the fact that we don’t have to care much about infrastructure setup, scaling, and maintenance and that we can focus on developing code which can easily be deployed into production. The Serverless opportunities seem endless, and so does the landscape map published by the Cloud Native Computing Foundation (CNCF), which you can find here.

serverless-landscape

Serverless architecture is said to be the next big thing and somewhat the advancement of microservices: Monolith -> Microservices -> Serverless architecture

Function as a Service

One of the most essential Serverless offerings are so-called compute runtimes, also known as function as a service (FaaS) platforms. Many vendors provide these platforms, with the most prominent ones being AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. There are also open-source alternatives, such as Apache OpenWhisk or Oracle’s Fn Project. Many more tools and platforms exist, which are also part of the landscape map shown above.
The general idea behind FaaS is to offer a platform that can be used to execute code triggered by some event. The code can be deployed without maintaining infrastructure and just by uploading functionality to the cloud, which takes care of executing and also scaling the function. “Functions” in the context of FaaS are rather small units that generally should be stateless and can, as a result, easily be scaled horizontally. A FaaS platform will not only scale out your code if it’s under heavy load but also take care of removing instances if the function has not been invoked much for a while. This technique, for starters, helps to optimize costs but also requires awareness of cold start situations. Serverless overall has relevant positive characteristics and should be part of our discussions around reliable architecture alternatives. If you want to learn a bit more about the concepts and what Serverless architecture entails, I recommend watching “Serverless: the Future of Software Architecture” by Peter Sbarski. To be clear, I personally don’t believe that you should go Serverless no matter what, but rather see it as a valid concept that might solve parts of your problems.

OpenFaaS – Containers as Functions

OpenFaaS, as explained on their web site, “makes it simple to turn anything into a Serverless function that runs on Linux or Windows through Docker Swarm or Kubernetes”. They promise that it lets us run any code anywhere at any scale. You could describe OpenFaaS as a “containers as a function” platform since its form of abstracting functions is a Docker image. That characteristic is an excellent trait as it allows us to package any code into a Docker image, and OpenFaaS runs it, scales it, and also provides metrics for us. To be honest, it’s worth mentioning that a specific tool needs to be added to your containers, which is called Function Watchdog, a tiny Golang HTTP server which connects your function with the outside world. OpenFaaS itself runs on, e.g., Kubernetes or Docker Swarm is open source under MIT license, and is written in Go. You can find the GitHub project here.

No vendor lock-in

OpenFaaS relies on Docker images used to package our code, and the tool itself runs on platforms such as Kubernetes. The community has adopted all of these technologies and knows how to use them. As a result, you may move your OpenFaaS instance around to and from any public or private cloud without issue. OpenFaaS does not make you dependent on a particular vendor, which is contrary to what you get when relying on technologies like AWS Lambda. The fact of being dependent on a particular vendor is known as a vendor lock-in.

Other similar projects

The idea of deploying independent containers to a compute engine can be discovered in a few more projects. You can find a comparison of multiple similar tools here.

Serverless Kotlin deployed on OpenFaaS

Now that we’ve learned about the general ideas behind Serverless, FaaS and what OpenFaaS does, we want to get our hands a bit dirty by setting up an OpenFaaS Kubernetes cluster and learning how we can deploy functions to it.

OpenFaaS Deployment using Kubernetes

The following is based on the official guide. Read it to get more information and learn about alternative approaches.

As a first step, you need to make sure to have a Kubernetes cluster set up. If you want to run Kubernetes on a local machine, various tools can help you set up the cluster (e.g. k3s or minikube). On Mac and Windows, you can also use Docker’s desktop edition to run a Kubernetes cluster locally.
After having set up Kubernetes, we can start deploying OpenFaaS to the cluster. It’s incredibly easy using k3sup

# Install k3sup
curl -sLS https://get.k3sup.dev | sh
sudo install k3sup /usr/local/bin/ # <- this step might not be necessary
chmod +x k3sup
# applies openfaas namespaces, create user, applies helm chart
k3sup app install openfaas

After that, inspecting your cluster, you will find several running OpenFaaS pods.

You should be able to view the gateway UI via http://127.0.0.1:31112/ui/ where you log in using the credentials generated by k3sup. You can get the password via kubectl:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)

To allow faas-cli (needs to be installed) to access your newly deployed services, make sure to
1) set OPENFAAS_URL via export OPENFAAS_URL=http://127.0.0.1:31112
2) log in via faas-cli login --password {YOUR_PASSWORD_HERE}

The following script logs you in automatically:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
echo -n $PASSWORD | faas-cli login --username admin --password-stdin

That’s it – We’re all set and can start deploying Serverless functions. 🎉

Creating and Deploying an OpenFaaS function

OpenFaaS offers different means and interfaces for deploying functions to the platform. We may use the CLI, the gateway UI, or the provided REST API, which is documented via this Swagger yaml.

Templates

The most straightforward way for getting started is via OpenFaaS’ template engine. With the faas-cli, we can create new functions based on available templates existing for various programming languages and tools. To get a list of all existing templates, you should run faas-cli template pull first. Running faas-cli new --list now, you should see a list of templates similar to the following:

csharp csharp-armhf dockerfile dockerfile-armhf go go-armhf java12 java8 node node-arm64 node-armhf node12 php7 python python-armhf python3 python3-armhf ruby

More templates are available via the OpenFaaS Store, which you can examine by running faas-cli template store list. Neither of both sources currently contains a Kotlin template, which I would love to change. Therefore, a change request is awaiting feedback and will hopefully add some official Kotlin to OpenFaaS.
On the bright side, it is quite easy to add my Kotlin templates to the cli by executing faas-cli template pull https://github.com/s1monw1/openfaas-kotlin. You should find two additional Kotlin variants now via faas-cli new --list. Let’s create a classic Kotlin function using the kotlin template:

faas-cli new hello-readers --lang=kotlin
# function can be found in ./hello-readers

By convention, OpenFaaS only exposes a particular part of each template to the user. If you want to look into that further, check out the Kotlin template and see how it is structured. The function is the one we have to deal with after running the faas-cli new command mentioned above.

Modify the template

In the newly generated function hello-readers, we can find a source file Handler.kt, which is the spot where we can implement the HTTP handling for our function. It’s a simple request-response mapper, and to demo it, we simply change the default body to "Hello kotlinexpertise readers".

class Handler : IHandler {
    override fun handle(request: IRequest): IResponse {
        return Response(body = "Hello kotlinexpertise readers")
    }
}

Build and Deploy

Build the function

Next to the hello-readers folder, OpenFaaS should have generated a YAML file called hello-readers.yml. It contains the information the cli needs to build and deploy our function. You can learn more about the relevant YAML structure and how you may want to modify it here. Let’s build it.

# by default, OpenFaaS looks for a stack.yml file which can be adjusted using the -f flag
faas-cli build -f hello-readers.yml 

OpenFaaS now runs the Dockerfile contained in the template (not visible to the user) to build the image which we can then deploy. There’s also a faas-cli up command available that wraps the build, push and deploy commands for our convenience. Either way, whether you use faas-cli up or faas-cli deploy, the result looks similar to the following output.

A successful deployment

> faas-cli deploy -f hello-readers.yml
Deploying: hello-readers.
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.

Deployed. 202 Accepted.
URL: http://127.0.0.1:31112/function/hello-readers

Clicking that URL reveals the message we previously configured: “Hello kotlinexpertise readers”. You can also examine the deployed function via the gateway UI.

Why would I use Kotlin to develop Serverless?

In the previous section, we saw that we could choose from a wide variety of programming languages to write Serverless functions for OpenFaaS. What language works best for you and makes the most sense depends on the use case and what you’re trying to achieve. Common Serverless languages are, e.g., Node, Python, and Go, but you’ll also find C#, Java, and even more in use.
Having a limited set of programming languages in a company probably leads to better internal tooling and also mitigates the issue of not being able to switch teams easily due to language barriers. I’m not a big fan of having hundreds of services all written in different languages, which most like would become problematic at some point. Most bigger tech companies limit their language portfolio and only add new ones if circumstances demand it.
I personally have been using Kotlin for almost four years now, and it was clear that I would also use it to explore the Serverless space. We at bryter have started using Kotlin Serverless functions not too long ago, and it’s working out well so far. Most of our backend services run Kotlin, and it’s the language we’re most experienced with. Nevertheless, we know that it might become necessary to add more languages, e.g., for performance reasons. The JVM footprint cannot be ignored and might impact performance here and there, for instance, when it comes to cold starts. To tweak things a bit, Graal VM could be a good option.
In a previous post, I wrote about the Server as a Function toolkit http4k, which is a fantastic library to enable Serverless functions in Kotlin. Http4k backs the functions we use at bryter, and I also proposed a corresponding template for the OpenFaaS store.

Serverless tooling for Kotlin

A pretty new framework named kotless (Kotlin Serverless) is currently being developed by Jetbrains with the goal of making it easy to turn Kotlin applications into ready-to-deploy functions and even handle the deployment which currently only works with AWS Lambda. The framework has a few very interesting features and I’m looking forward to see where kotless is heading.

Summary and Lookout

Serverless approaches and related architectural implications are relevant and something we should be aware of when considering approaches to modern software architecture. Functions as a service, as a Serverless related topic, has been around for a while. The big cloud players Amazon, Google, and Microsoft, provide the most prominent tools. Still, we can also get around vendor lock-in by opting to choose more independent platforms like the one I presented to you in this article: OpenFaaS. We saw that setting up OpenFaaS is no rocket science, and it can run on your local machine, which enables an excellent way to get started. You can choose from a big set of programming languages and just need to make sure that your code can be packaged as a Docker image to be able to deploy it to OpenFaaS. Templates can help with setting up functions quickly, and it’s not too hard to write your own function templates if necessary. I have shown an example of a Kotlin template and how the resulting HTTP handler (representing the function) looks like. Kotlin is a valid alternative amongst many others, and you should decide on a case-to-case basis, which programming language best suits your function’s needs. As I mentioned, I’ve been using the presented technologies for a while and currently work on a real-life use case to utilize that stuff to set up a dynamic, highly scalable and expandable platform, which I want to talk more about in upcoming articles.

The post Serverless Kotlin with OpenFaaS appeared first on Kotlin Expertise Blog.

Continue ReadingServerless Kotlin with OpenFaaS

Serverless Kotlin with OpenFaaS

Serverless Kotlin on OpenFaaS

With this article, my goal is to demonstrate how Serverless Kotlin can look like by introducing you to one of the coolest Serverless platforms: OpenFaaS. OpenFaaS is an open-source, community-owned project that you may use to run your functions and microservices on any public or private cloud. You can run your Docker image on OpenFaaS, which runs and scales it for you. As a result, you are free to choose any programming language as long as it can be packaged into a Docker image. Throughout this post, we want to learn about the concepts behind Serverless and Function as a Service (FaaS), and how we can deploy Serverless Kotlin functions to OpenFaaS.

Serverless and Function as a Service

Serverless Computing

With Serverless Computing, we describe a cloud model in which server management and infrastructure decisions don’t have to be tackled by the developers, but are taken care of by the cloud providers themselves. The term “Serverless” describes the fact that we don’t have to care much about infrastructure setup, scaling, and maintenance and that we can focus on developing code which can easily be deployed into production. The Serverless opportunities seem endless, and so does the landscape map published by the Cloud Native Computing Foundation (CNCF), which you can find here.

serverless-landscape

Serverless architecture is said to be the next big thing and somewhat the advancement of microservices: Monolith -> Microservices -> Serverless architecture

Function as a Service

One of the most essential Serverless offerings are so-called compute runtimes, also known as function as a service (FaaS) platforms. Many vendors provide these platforms, with the most prominent ones being AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. There are also open-source alternatives, such as Apache OpenWhisk or Oracle’s Fn Project. Many more tools and platforms exist, which are also part of the landscape map shown above.
The general idea behind FaaS is to offer a platform that can be used to execute code triggered by some event. The code can be deployed without maintaining infrastructure and just by uploading functionality to the cloud, which takes care of executing and also scaling the function. “Functions” in the context of FaaS are rather small units that generally should be stateless and can, as a result, easily be scaled horizontally. A FaaS platform will not only scale out your code if it’s under heavy load but also take care of removing instances if the function has not been invoked much for a while. This technique, for starters, helps to optimize costs but also requires awareness of cold start situations. Serverless overall has relevant positive characteristics and should be part of our discussions around reliable architecture alternatives. If you want to learn a bit more about the concepts and what Serverless architecture entails, I recommend watching “Serverless: the Future of Software Architecture” by Peter Sbarski. To be clear, I personally don’t believe that you should go Serverless no matter what, but rather see it as a valid concept that might solve parts of your problems.

OpenFaaS – Containers as Functions

OpenFaaS, as explained on their web site, “makes it simple to turn anything into a Serverless function that runs on Linux or Windows through Docker Swarm or Kubernetes”. They promise that it lets us run any code anywhere at any scale. You could describe OpenFaaS as a “containers as a function” platform since its form of abstracting functions is a Docker image. That characteristic is an excellent trait as it allows us to package any code into a Docker image, and OpenFaaS runs it, scales it, and also provides metrics for us. To be honest, it’s worth mentioning that a specific tool needs to be added to your containers, which is called Function Watchdog, a tiny Golang HTTP server which connects your function with the outside world. OpenFaaS itself runs on, e.g., Kubernetes or Docker Swarm is open source under MIT license, and is written in Go. You can find the GitHub project here.

No vendor lock-in

OpenFaaS relies on Docker images used to package our code, and the tool itself runs on platforms such as Kubernetes. The community has adopted all of these technologies and knows how to use them. As a result, you may move your OpenFaaS instance around to and from any public or private cloud without issue. OpenFaaS does not make you dependent on a particular vendor, which is contrary to what you get when relying on technologies like AWS Lambda. The fact of being dependent on a particular vendor is known as a vendor lock-in.

Other similar projects

The idea of deploying independent containers to a compute engine can be discovered in a few more projects. You can find a comparison of multiple similar tools here.

Serverless Kotlin deployed on OpenFaaS

Now that we’ve learned about the general ideas behind Serverless, FaaS and what OpenFaaS does, we want to get our hands a bit dirty by setting up an OpenFaaS Kubernetes cluster and learning how we can deploy functions to it.

OpenFaaS Deployment using Kubernetes

The following is based on the official guide. Read it to get more information and learn about alternative approaches.

As a first step, you need to make sure to have a Kubernetes cluster set up. If you want to run Kubernetes on a local machine, various tools can help you set up the cluster (e.g. k3s or minikube). On Mac and Windows, you can also use Docker’s desktop edition to run a Kubernetes cluster locally.
After having set up Kubernetes, we can start deploying OpenFaaS to the cluster. It’s incredibly easy using k3sup

# Install k3sup
curl -sLS https://get.k3sup.dev | sh
sudo install k3sup /usr/local/bin/ # <- this step might not be necessary
chmod +x k3sup
# applies openfaas namespaces, create user, applies helm chart
k3sup app install openfaas

After that, inspecting your cluster, you will find several running OpenFaaS pods.

You should be able to view the gateway UI via http://127.0.0.1:31112/ui/ where you log in using the credentials generated by k3sup. You can get the password via kubectl:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)

To allow faas-cli (needs to be installed) to access your newly deployed services, make sure to
1) set OPENFAAS_URL via export OPENFAAS_URL=http://127.0.0.1:31112
2) log in via faas-cli login --password {YOUR_PASSWORD_HERE}

The following script logs you in automatically:

PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
echo -n $PASSWORD | faas-cli login --username admin --password-stdin

That’s it – We’re all set and can start deploying Serverless functions. 🎉

Creating and Deploying an OpenFaaS function

OpenFaaS offers different means and interfaces for deploying functions to the platform. We may use the CLI, the gateway UI, or the provided REST API, which is documented via this Swagger yaml.

Templates

The most straightforward way for getting started is via OpenFaaS’ template engine. With the faas-cli, we can create new functions based on available templates existing for various programming languages and tools. To get a list of all existing templates, you should run faas-cli template pull first. Running faas-cli new --list now, you should see a list of templates similar to the following:

csharp csharp-armhf dockerfile dockerfile-armhf go go-armhf java12 java8 node node-arm64 node-armhf node12 php7 python python-armhf python3 python3-armhf ruby

More templates are available via the OpenFaaS Store, which you can examine by running faas-cli template store list. Neither of both sources currently contains a Kotlin template, which I would love to change. Therefore, a change request is awaiting feedback and will hopefully add some official Kotlin to OpenFaaS.
On the bright side, it is quite easy to add my Kotlin templates to the cli by executing faas-cli template pull https://github.com/s1monw1/openfaas-kotlin. You should find two additional Kotlin variants now via faas-cli new --list. Let’s create a classic Kotlin function using the kotlin template:

faas-cli new hello-readers --lang=kotlin
# function can be found in ./hello-readers

By convention, OpenFaaS only exposes a particular part of each template to the user. If you want to look into that further, check out the Kotlin template and see how it is structured. The function is the one we have to deal with after running the faas-cli new command mentioned above.

Modify the template

In the newly generated function hello-readers, we can find a source file Handler.kt, which is the spot where we can implement the HTTP handling for our function. It’s a simple request-response mapper, and to demo it, we simply change the default body to "Hello kotlinexpertise readers".

class Handler : IHandler {
    override fun handle(request: IRequest): IResponse {
        return Response(body = "Hello kotlinexpertise readers")
    }
}

Build and Deploy

Build the function

Next to the hello-readers folder, OpenFaaS should have generated a YAML file called hello-readers.yml. It contains the information the cli needs to build and deploy our function. You can learn more about the relevant YAML structure and how you may want to modify it here. Let’s build it.

# by default, OpenFaaS looks for a stack.yml file which can be adjusted using the -f flag
faas-cli build -f hello-readers.yml 

OpenFaaS now runs the Dockerfile contained in the template (not visible to the user) to build the image which we can then deploy. There’s also a faas-cli up command available that wraps the build, push and deploy commands for our convenience. Either way, whether you use faas-cli up or faas-cli deploy, the result looks similar to the following output.

A successful deployment

> faas-cli deploy -f hello-readers.yml
Deploying: hello-readers.
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.

Deployed. 202 Accepted.
URL: http://127.0.0.1:31112/function/hello-readers

Clicking that URL reveals the message we previously configured: “Hello kotlinexpertise readers”. You can also examine the deployed function via the gateway UI.

Why would I use Kotlin to develop Serverless?

In the previous section, we saw that we could choose from a wide variety of programming languages to write Serverless functions for OpenFaaS. What language works best for you and makes the most sense depends on the use case and what you’re trying to achieve. Common Serverless languages are, e.g., Node, Python, and Go, but you’ll also find C#, Java, and even more in use.
Having a limited set of programming languages in a company probably leads to better internal tooling and also mitigates the issue of not being able to switch teams easily due to language barriers. I’m not a big fan of having hundreds of services all written in different languages, which most like would become problematic at some point. Most bigger tech companies limit their language portfolio and only add new ones if circumstances demand it.
I personally have been using Kotlin for almost four years now, and it was clear that I would also use it to explore the Serverless space. We at bryter have started using Kotlin Serverless functions not too long ago, and it’s working out well so far. Most of our backend services run Kotlin, and it’s the language we’re most experienced with. Nevertheless, we know that it might become necessary to add more languages, e.g., for performance reasons. The JVM footprint cannot be ignored and might impact performance here and there, for instance, when it comes to cold starts. To tweak things a bit, Graal VM could be a good option.
In a previous post, I wrote about the Server as a Function toolkit http4k, which is a fantastic library to enable Serverless functions in Kotlin. Http4k backs the functions we use at bryter, and I also proposed a corresponding template for the OpenFaaS store.

Serverless tooling for Kotlin

A pretty new framework named kotless (Kotlin Serverless) is currently being developed by Jetbrains with the goal of making it easy to turn Kotlin applications into ready-to-deploy functions and even handle the deployment which currently only works with AWS Lambda. The framework has a few very interesting features and I’m looking forward to see where kotless is heading.

Summary and Lookout

Serverless approaches and related architectural implications are relevant and something we should be aware of when considering approaches to modern software architecture. Functions as a service, as a Serverless related topic, has been around for a while. The big cloud players Amazon, Google, and Microsoft, provide the most prominent tools. Still, we can also get around vendor lock-in by opting to choose more independent platforms like the one I presented to you in this article: OpenFaaS. We saw that setting up OpenFaaS is no rocket science, and it can run on your local machine, which enables an excellent way to get started. You can choose from a big set of programming languages and just need to make sure that your code can be packaged as a Docker image to be able to deploy it to OpenFaaS. Templates can help with setting up functions quickly, and it’s not too hard to write your own function templates if necessary. I have shown an example of a Kotlin template and how the resulting HTTP handler (representing the function) looks like. Kotlin is a valid alternative amongst many others, and you should decide on a case-to-case basis, which programming language best suits your function’s needs. As I mentioned, I’ve been using the presented technologies for a while and currently work on a real-life use case to utilize that stuff to set up a dynamic, highly scalable and expandable platform, which I want to talk more about in upcoming articles.

The post Serverless Kotlin with OpenFaaS appeared first on Kotlin Expertise Blog.

Continue ReadingServerless Kotlin with OpenFaaS

Server as a function with Kotlin – http4k

Server as a function with Kotlin – http4k

Have you ever heard about the concept of “Server as a Function”? The idea is that we write our server application based on just ordinary functions, which is based on a concept outlined in the paper Your Server as a Function written and published by Twitter/Marius Eriksen. In the Kotlin world, the most prominent implementation of this concept is http4k, which the maintainers describe as an “HTTP toolset written in Kotlin with a focus on creating simple, testable APIs”. The best part about it is that http4k applications are just Kotlin functions that we can test straightforwardly. Take a look at this first example:

First http4k server example

val app: HttpHandler = { request: Request -> Response(OK).body(request.body) }
val server = app.asServer(SunHttp(8000)).start()

This code shows a fully functional http4k application consisting of a single Kotlin function app which we embedded into a SunHttp server, one example of available server implementations we may choose from. Note the type HttpHandler here, which represents one of the two essential concepts in the idea of “Server as a Function”:

  • HttpHandler ((Request) -> Response): abstraction to process HTTP requests into responses by mapping the first into the latter
  • Filter (HttpHandler -> HttpHandler): abstraction to add pre and post-processing like caching, debugging, authentication handling, and more to an HttpHandler. Filters are composable/stackable

Every http4k application can be composed of HttpHandlers in combination with Filters, both of which are simple type aliases for ordinary Kotlin function types. Http4k comes with zero dependencies if we don’t count the Kotlin standard library as one. Since http4k applications, in their pure form, only entail some nested Kotlin functions; there is no reflection or annotation processing involved. As a result, http4k applications can start and stop super quickly which also makes them a reasonable candidate to be deployed on Function-as-a-Service environments (as opposed to e.g., Spring Boot applications).

More advanced http4k application

Let’s take a look at a more advanced example of an http4k server.

val pingPongHandler: HttpHandler = { _ -> Response(OK).body("pong!") }

val greetHandler: HttpHandler = { req: Request ->
    val name: String? = req.query("name")
    Response(OK).body("hello ${name ?: "unknown!"}")
}

val routing: RoutingHttpHandler = routes(
     "/ping" bind GET to pingPongHandler,
     "/greet" bind GET to greetHandler
)

val requestTimeLogger: Filter = Filter { next: HttpHandler ->
     { request: Request ->
         val start = clock.millis()
         val response = next(request)
         val latency = clock.millis() - start
         logger { "Request to ${request.uri} took ${latency}ms" }
         response
     }
}

val app: HttpHandler =
     ResponseFilters.GZip()
     .then(requestTimeLogger)
     .then(routing)

In this snippet, we can see a few exciting things http4k applications may entail. The first two expressions are definitions of HttpHandlers, in which the first one takes any response and maps it to an OK response containing “pong” in its body. The second handler takes a request, extracts a name, and greets the caller. In the next step, we apply routing to the handlers by assigning one particular route to each handler. As we can see, the pingPongHandler is used to serve a client who invokes /ping, while the greetHandler is used to cover /greet.

Routing

Routing in http4k works with arbitrary levels of nesting, which works flawlessly since routing itself results in a new HttpHandler (strictly speaking, a special kind of type RoutingHttpHandler), just like the original ones.

Filters

As mentioned before, the other important concept we want to look at is Filters. For starters, we create a requestTimeLogger that intercepts each incoming request by measuring its processing time and logging the elapsed time. Filters can be combined using the then method, which allows us to define chains of filters. The corresponding API looks like this:

fun Filter.then(next: Filter): Filter

In the example application above, we add our custom filter to one of the default filters called GZip. Once we have combined all our filters, we want to add an HttpHandler to our filter chain. Again, there’s a then function we can use to do so:

fun Filter.then(next: HttpHandler): HttpHandler

As we can see, this again results in an HttpHandler. You all probably got the idea by now – It only needs two simple types to express how an HTTP server should operate.

The shown GZip filter is just one of many default filters we may choose from. Others cover concerns like caching, CORS, basic authentication or cookie handling and can be found in the org.http4k.filter package.

Calling HttpHandlers

So what did we get out of that nesting which resulted in yet another HttpHandler called app? Well, this itself does not entail running an actual server yet. However, it describes how requests are handled. We can use this object, as well as other separate HttpHandlers and Filters, and invoke it directly (e.g. in our tests). No HTTP required. Let’s see this in action:

//call handler directly
val handlerResponse: Response = pingPongHandler(Request(GET, "/any"))

//call handler through routing
val routingCallResponse: Response = app(Request(GET, "/ping").header("accept-encoding", "gzip"))

app.asServer(Jetty(9000)).start()

Http4k comes with its own implementations of a Request and a Response, first of which can be used to invoke an HttpHandler. Calling the unattractive pingPongHandler yields something similar to HTTP/1.1 200 OK pong! while calling the final app handler gives us a gzipped response due to the applied GZip filter. This call also implies a log informing about the duration of the request: 2019-09-20T21:22:55.300768Z LOG - Request to /ping took 3ms. Please note that, while it was fine to call pingPongHandler with a random URI (/any), we had to use the designated /ping URI when invoking the routing-backed app.
Last, but not least, we start our very own http4k HttpHandler as a server on a Jetty with port 9000. Find a list of available server implementations here.

Lenses

One of the things a sophisticated HTTP app has to deal with is taking stuff out and also putting stuff into HTTP messages. When we take parameters out of requests, we also care about validating these values. Http4k comes with a fascinating concept that helps us deal with the stated concerns: Lenses.

Basic Definition

Lenses, according to multiple resources, were first used in the Haskell world and are a functional concept that may appear slightly hard to understand. Let me try to describe it in a shallow, understandable manner. Let’s say we have a class Whole which comes with different fields part1, part2, and so on. A lens basically composes a getter and a setter focusing on precisely one part of Whole. A Part1Lens lens getter would take an instance of Whole to return the part it is focused on, i.e., part1. The lens setter, on the other hand, takes a Whole along with a value to set the focused part to and then returns a new Whole with the updated part. Remember that a lens can be used to both get and set a part of a whole object. Now, let’s learn how this concept helps us with handling HTTP messages.

Lenses in http4k

Following the basic idea of a lens, http4k lenses are bi-directional entities which can be used to either get or set a particular value from/onto an HTTP message. The corresponding API to describe lenses comes in the form of a DSL which also lets us define the requirement (optional vs. mandatory) of the HTTP part we are mounting a lens on. Since HTTP messages are a rather complex container, we can have lenses focusing on different areas of the messages: Query, Header, Path, FormField, Body. Let’s see some examples of how lenses can be created:

// lens focusing on the path variable name
val nameLens = Path.string().of("name")

// lens focusing on a required query parameter city
val requiredQuery = Query.required("city")

// lens focusing on a required and non empty string city 
val nonEmptyQuery = Query.nonEmptyString().required("city")

// lens focusing on an optional header Content-Length with type int 
val optionalHeader = Header.int().optional("Content-Length")

// lens focusing on text body
val responseBody = Body.string(ContentType.TEXT_PLAIN).toLens()

So far, the API for creating lenses looks more or less straightforward but what about using them on a target? Here’s the pseudo code syntax for
a) Retrieving a value: <lens>.extract(<target>), or <lens>(<target>)
b) Setting a value: <lens>.inject(<value>, <target>), or <lens>(<value>, <target>)

Use Lens to Retrieve value from HTTP Request

Reusing the greet sample from earlier, let’s modify our code to make use of lenses when retrieving a value:

val nameLens: BiDiLens<Request, String> =
    Query.nonEmptyString().required("name")

val greetHandler: HttpHandler = { req: Request ->
     val name: String = nameLens.extract(req) //or nameLens(req)
     Response(OK).body("hello $name")
}

We create a bidirectional lens focusing on the query part of our message to extract a required and non-empty name from it. Now, if a client happens to call the endpoint without providing a name query parameter, the lens automatically returns an error since it was defined as “required” and “nonEmpty”. Please note that, by default, the application exposes much detail to the client announcing the error as org.http4k.lens.LensFailure: query 'name' must be string including a detailed stack trace. Rather than that, we want to map all lens errors to HTTP 400 responses which implies that the client provided invalid data. Therefore, http4k offers a ServerFilters.CatchLensFailure filter which we can easily activate in our filter chain:

// gzip omitted
val app: HttpHandler = ServerFilters.CatchLensFailure
 .then(requestTimeLogger)
 .then(routing)

Use Lens to Set value in HTTP Request

After looking into extracting values from HTTP messages, how can we use the nameLens to set a value in an HTTP request?

val req = Request(GET, "/greet/{name}")
val reqWithName = nameLens.inject("kotlin", req)
// alternatively, http4k offers a with function that can apply multiple lenses at once
val reqWithName = Request(GET, "/greet/{name}").with(
    nameLens of "simon" //, more lenses
)

The example shows how we create an instance of Request and inject a value via one or many lenses. We can use the Lens::inject function to specify the value we want to set into an arbitrary instance of Request. Now that we saw a basic example of a string lens, we want to dig into handling some more advanced JSON content.

JSON handling

We can choose from several JSON implementations, including e.g., the common Gson and Jackson library. I personally prefer Jackson as it comes with a great Kotlin module (Kudos to my friend Jayson Minard 😉). After adding a JSON format module to our application, we can start marshaling objects to and from HTTP messages using lenses. Let’s consider a partially complete REST API that manages persons:

[...]
import org.http4k.format.Jackson.auto

class PersonHandlerProvider(private val service: PersonService) {
    private val personLens: BiDiBodyLens<Person> = Body.auto<Person>().toLens()
    private val personListLens: BiDiBodyLens<List<Person>> = Body.auto<List<Person>>().toLens()

     fun getAllHandler(): HttpHandler = {
             Response(OK).with( 
                 personListLens of service.findAll()
             )
        }

     fun postHandler(): HttpHandler = { req ->
             val personToAdd = personLens.extract(req)
             service.add(personToAdd)
             Response(OK)
         }

     //...more
}

In this example, we see a class that provides two handlers representing common actions you would expect from a REST API. The getAllHandler fetches all currently stored entities and returns them to the client. We make use of a BiDiBodyLens<List<Person>> (BiDirectional) that we created via the org.http4k.format.Jackson.auto extension for Jackson. As noted in the http4k documentation, “the auto() method needs to be manually imported as IntelliJ won’t pick it up automatically”. We can use the resulting lens like already shown earlier by providing a value of type List<Person> and inject it into an HTTP Response as shown in the getAllHandler implementation.
The postHandler, on the other hand, provides an implementation of an HttpHandler, that extracts a Person entity from the request and adds it to the storage. Again, we use a lens to extract that JSON entity from the request easily.

This already concludes our sneak peek on lenses. As we saw, lenses are a fantastic tool that lets us extract and inject parts of an HTTP message and also provides simple means of validating those parts. Now, that we have seen the most fundamental concepts of the http4k toolset, let’s consider how we can test such applications.

Testing

Most of the time, when we consider testing applications that sit on top of a web framework, we have to worry about details of that framework which can make testing harder than it should be. Spoiler Alert: This is not quite the case with http4k 🎉

We have already learned that HttpHandlers, one of the two core concepts in the http4k toolset, are just regular Kotlin functions mapping requests to responses and even a complete http4k application again is just an HttpHandler and thus a callable function. As a result, entire and partial http4k apps can be tested easily and without additional work. Nevertheless, the makers of http4k thought that it would still be helpful to provide some additional modules which support us with testing our applications. One of these modules is http4k-testing-hamkrest, which adds a set of Hamkrest matchers, we can use to verify details of message objects more easily.

Http4k Handler Test Example

import com.natpryce.hamkrest.assertion.assertThat
import org.http4k.core.Method
import org.http4k.core.Request
import org.http4k.core.Status
import org.http4k.hamkrest.hasStatus
import org.junit.jupiter.api.Test

class PersonHandlerProviderTest {

    val systemUnderTest = PersonHandlerProvider(PersonService())

    @Test
    fun getAll_handler_can_be_invoked_as_expected(){
        val getAll: HttpHandler = systemUnderTest.getAllHandler()

        val result: Response = getAll(Request(Method.GET, "/some-uri"))

        assertThat(result, hasStatus(Status.OK))
    }
}

This snippet demonstrates a test for the PersonHandlerProvider we have worked with earlier already. As shown, it’s pretty straightforward to call an HttpHandler with a Request object and then use Hamkrest or whatever assertion library you prefer to check the resulting Response. Testing Filters, on the other hand, is “harder”. To be honest though, it’s just one tiny thing we need to do on top of what we did with handlers. Filters map one HttpHandler into another one by applying some intermediate pre or post-processing. Instead of investigating the mapping between handlers itself, it would be more convenient to again send a Request through that filter and look into the resulting Response. The good news is: It’s super easy to do just that:

Http4k Filter Test Example

val addExtraHeaderFilter = Filter { next ->
    {
        next(it).header("x-extra-header", "some value")
    }
}

@Test
fun adds_a_special_header() {
    val handler: HttpHandler = addExtraHeaderFilter.then { Response(OK) }

    val response: Response = handler(Request(GET, "/echo"))

    assertThat(response, hasStatus(OK).and(hasHeader("x-extra-header", "some value")))
}

We have a Filter called addExtraHeaderFilter that adds a custom header to a processed request and then forwards it to the next filter. The goal is to send a simple request through that filter in our test. What we can do, is making the filter a simple HttpHandler by adding a dumb { Response(OK) } handler to it via then. As a result, we can invoke the newly created handler, now containing our very own filter, and investigate whether the resulting Response object contains the new expected header. There we go – both handlers and filters got tested 🙃
To wrap up, I want to say that this was just a quick look at the happy paths of testing http4k apps with mostly familiar tools. It might become necessary to test against the actual running server and verify Responses on a lower level, e.g., comparing the resulting JSON directly. Doing that is also possible and supported via the Approval Testing module. Later in this article, we want to look at the client module of http4k, which again opens up some new possibilities.

Serverless

One of the hottest topics of our time is Serverless computing. You know, that thing where we can run our code on other people’s… servers. One part of it is known as Function as a Service, or FaaS and the most common ones include AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. The general idea is that these vendors provide a platform where we can deploy our code, and they take care of managing resources and scaling our application on demand. One of the downsides of Serverless is that our functions may be spun down by the platform if it’s not being used until someone wants to use it again, which would require a fresh startup. What does that mean for us? We need to choose target platforms and tools which allow a fast start-up of our application. Spring on the JVM in its classical form, for instance, would probably not be the best tool for that use case. However, as you can image, http4k with its small footprint and super quick start-up times is a great choice. It even comes with native support for AWS Lambda.

I won’t dive much deeper into this topic as part of this article, but I’m planning to write a much more detailed post on what we can do with http4k on a FaaS platform. Stay tuned.

Client as a Function

By now, we have learned how cool http4k is and why it’s a great tool to develop server applications. HTTP Servers don’t make much sense without clients using them, so we want to conclude this article by looking at the other side – Clients as a Function.
The http4k core library comes with everything we need to get started with clients. Clients in http4k again are just a special form of an HttpHandler, as we can see in this little snippet:

val request = Request(Method.GET, "https://kotlinexpertise.com/sitemap.xml")
val client: HttpHandler = JavaHttpClient()
val response = client(request)

The shown JavaHttpClient is the default implementation that comes with the core library. If we were to prefer OkHttp, Apache, or Jetty instead, we would find a related module to replace the default. Since we program against interfaces (clients are HttpHandlers), it’s not a big deal to swap out implementations at any time. The core library obviously comes with several default Filters we can apply to our client which can be found in the ClientFilters.kt file that contains stuff like BasicAuth, Gzip and more stuff you’d expect for a client. The fact that all concepts of http4k servers, including handlers, filters and also lenses, can be reused in http4k clients opens up quite a few possibilities so that it can make much sense to e.g., use the client module to test your servers an vice versa.

Summary and Lookout

I personally learned to appreciate http4k a lot in the last couple of weeks. Once you’ve made yourself comfortable with the basic concepts, it becomes straightforward to develop (which includes testing) server applications quickly. Http4k comes with an incredible list of supported concepts and technologies including OAuth, Swagger, Websockets, XML and many, many more. Its modular nature allows us to add functionality by applying dependencies as needed, and due to its simple base types, it is highly extensible. Http4k is a toolset that allows us to write applications with quick startup times which also makes it a valid alternative when it comes to FaaS and Serverless computing. As if this wasn’t enough, the toolset also includes sophisticated means for writing HTTP clients, which we learned about in the last section. Overall, http4k is a promising technology that you should definitely consider when choosing your next HTTP toolset.

If you want to learn more about Kotlin and its fantastic language features, please have a look at my talk “Diving into advanced language features”.

The post Server as a function with Kotlin – http4k appeared first on Kotlin Expertise Blog.

Continue ReadingServer as a function with Kotlin – http4k

Server as a function with Kotlin – http4k

Server as a function with Kotlin – http4k

Have you ever heard about the concept of “Server as a Function”? The idea is that we write our server application based on just ordinary functions, which is based on a concept outlined in the paper Your Server as a Function written and published by Twitter/Marius Eriksen. In the Kotlin world, the most prominent implementation of this concept is http4k, which the maintainers describe as an “HTTP toolset written in Kotlin with a focus on creating simple, testable APIs”. The best part about it is that http4k applications are just Kotlin functions that we can test straightforwardly. Take a look at this first example:

First http4k server example

val app: HttpHandler = { request: Request -> Response(OK).body(request.body) }
val server = app.asServer(SunHttp(8000)).start()

This code shows a fully functional http4k application consisting of a single Kotlin function app which we embedded into a SunHttp server, one example of available server implementations we may choose from. Note the type HttpHandler here, which represents one of the two essential concepts in the idea of “Server as a Function”:

  • HttpHandler ((Request) -> Response): abstraction to process HTTP requests into responses by mapping the first into the latter
  • Filter (HttpHandler -> HttpHandler): abstraction to add pre and post-processing like caching, debugging, authentication handling, and more to an HttpHandler. Filters are composable/stackable

Every http4k application can be composed of HttpHandlers in combination with Filters, both of which are simple type aliases for ordinary Kotlin function types. Http4k comes with zero dependencies if we don’t count the Kotlin standard library as one. Since http4k applications, in their pure form, only entail some nested Kotlin functions; there is no reflection or annotation processing involved. As a result, http4k applications can start and stop super quickly which also makes them a reasonable candidate to be deployed on Function-as-a-Service environments (as opposed to e.g., Spring Boot applications).

More advanced http4k application

Let’s take a look at a more advanced example of an http4k server.

val pingPongHandler: HttpHandler = { _ -> Response(OK).body("pong!") }

val greetHandler: HttpHandler = { req: Request ->
    val name: String? = req.query("name")
    Response(OK).body("hello ${name ?: "unknown!"}")
}

val routing: RoutingHttpHandler = routes(
     "/ping" bind GET to pingPongHandler,
     "/greet" bind GET to greetHandler
)

val requestTimeLogger: Filter = Filter { next: HttpHandler ->
     { request: Request ->
         val start = clock.millis()
         val response = next(request)
         val latency = clock.millis() - start
         logger { "Request to ${request.uri} took ${latency}ms" }
         response
     }
}

val app: HttpHandler =
     ResponseFilters.GZip()
     .then(requestTimeLogger)
     .then(routing)

In this snippet, we can see a few exciting things http4k applications may entail. The first two expressions are definitions of HttpHandlers, in which the first one takes any response and maps it to an OK response containing “pong” in its body. The second handler takes a request, extracts a name, and greets the caller. In the next step, we apply routing to the handlers by assigning one particular route to each handler. As we can see, the pingPongHandler is used to serve a client who invokes /ping, while the greetHandler is used to cover /greet.

Routing

Routing in http4k works with arbitrary levels of nesting, which works flawlessly since routing itself results in a new HttpHandler (strictly speaking, a special kind of type RoutingHttpHandler), just like the original ones.

Filters

As mentioned before, the other important concept we want to look at is Filters. For starters, we create a requestTimeLogger that intercepts each incoming request by measuring its processing time and logging the elapsed time. Filters can be combined using the then method, which allows us to define chains of filters. The corresponding API looks like this:

fun Filter.then(next: Filter): Filter

In the example application above, we add our custom filter to one of the default filters called GZip. Once we have combined all our filters, we want to add an HttpHandler to our filter chain. Again, there’s a then function we can use to do so:

fun Filter.then(next: HttpHandler): HttpHandler

As we can see, this again results in an HttpHandler. You all probably got the idea by now – It only needs two simple types to express how an HTTP server should operate.

The shown GZip filter is just one of many default filters we may choose from. Others cover concerns like caching, CORS, basic authentication or cookie handling and can be found in the org.http4k.filter package.

Calling HttpHandlers

So what did we get out of that nesting which resulted in yet another HttpHandler called app? Well, this itself does not entail running an actual server yet. However, it describes how requests are handled. We can use this object, as well as other separate HttpHandlers and Filters, and invoke it directly (e.g. in our tests). No HTTP required. Let’s see this in action:

//call handler directly
val handlerResponse: Response = pingPongHandler(Request(GET, "/any"))

//call handler through routing
val routingCallResponse: Response = app(Request(GET, "/ping").header("accept-encoding", "gzip"))

app.asServer(Jetty(9000)).start()

Http4k comes with its own implementations of a Request and a Response, first of which can be used to invoke an HttpHandler. Calling the unattractive pingPongHandler yields something similar to HTTP/1.1 200 OK pong! while calling the final app handler gives us a gzipped response due to the applied GZip filter. This call also implies a log informing about the duration of the request: 2019-09-20T21:22:55.300768Z LOG - Request to /ping took 3ms. Please note that, while it was fine to call pingPongHandler with a random URI (/any), we had to use the designated /ping URI when invoking the routing-backed app.
Last, but not least, we start our very own http4k HttpHandler as a server on a Jetty with port 9000. Find a list of available server implementations here.

Lenses

One of the things a sophisticated HTTP app has to deal with is taking stuff out and also putting stuff into HTTP messages. When we take parameters out of requests, we also care about validating these values. Http4k comes with a fascinating concept that helps us deal with the stated concerns: Lenses.

Basic Definition

Lenses, according to multiple resources, were first used in the Haskell world and are a functional concept that may appear slightly hard to understand. Let me try to describe it in a shallow, understandable manner. Let’s say we have a class Whole which comes with different fields part1, part2, and so on. A lens basically composes a getter and a setter focusing on precisely one part of Whole. A Part1Lens lens getter would take an instance of Whole to return the part it is focused on, i.e., part1. The lens setter, on the other hand, takes a Whole along with a value to set the focused part to and then returns a new Whole with the updated part. Remember that a lens can be used to both get and set a part of a whole object. Now, let’s learn how this concept helps us with handling HTTP messages.

Lenses in http4k

Following the basic idea of a lens, http4k lenses are bi-directional entities which can be used to either get or set a particular value from/onto an HTTP message. The corresponding API to describe lenses comes in the form of a DSL which also lets us define the requirement (optional vs. mandatory) of the HTTP part we are mounting a lens on. Since HTTP messages are a rather complex container, we can have lenses focusing on different areas of the messages: Query, Header, Path, FormField, Body. Let’s see some examples of how lenses can be created:

// lens focusing on the path variable name
val nameLens = Path.string().of("name")

// lens focusing on a required query parameter city
val requiredQuery = Query.required("city")

// lens focusing on a required and non empty string city 
val nonEmptyQuery = Query.nonEmptyString().required("city")

// lens focusing on an optional header Content-Length with type int 
val optionalHeader = Header.int().optional("Content-Length")

// lens focusing on text body
val responseBody = Body.string(ContentType.TEXT_PLAIN).toLens()

So far, the API for creating lenses looks more or less straightforward but what about using them on a target? Here’s the pseudo code syntax for
a) Retrieving a value: <lens>.extract(<target>), or <lens>(<target>)
b) Setting a value: <lens>.inject(<value>, <target>), or <lens>(<value>, <target>)

Use Lens to Retrieve value from HTTP Request

Reusing the greet sample from earlier, let’s modify our code to make use of lenses when retrieving a value:

val nameLens: BiDiLens<Request, String> =
    Query.nonEmptyString().required("name")

val greetHandler: HttpHandler = { req: Request ->
     val name: String = nameLens.extract(req) //or nameLens(req)
     Response(OK).body("hello $name")
}

We create a bidirectional lens focusing on the query part of our message to extract a required and non-empty name from it. Now, if a client happens to call the endpoint without providing a name query parameter, the lens automatically returns an error since it was defined as “required” and “nonEmpty”. Please note that, by default, the application exposes much detail to the client announcing the error as org.http4k.lens.LensFailure: query 'name' must be string including a detailed stack trace. Rather than that, we want to map all lens errors to HTTP 400 responses which implies that the client provided invalid data. Therefore, http4k offers a ServerFilters.CatchLensFailure filter which we can easily activate in our filter chain:

// gzip omitted
val app: HttpHandler = ServerFilters.CatchLensFailure
 .then(requestTimeLogger)
 .then(routing)

Use Lens to Set value in HTTP Request

After looking into extracting values from HTTP messages, how can we use the nameLens to set a value in an HTTP request?

val req = Request(GET, "/greet/{name}")
val reqWithName = nameLens.inject("kotlin", req)
// alternatively, http4k offers a with function that can apply multiple lenses at once
val reqWithName = Request(GET, "/greet/{name}").with(
    nameLens of "simon" //, more lenses
)

The example shows how we create an instance of Request and inject a value via one or many lenses. We can use the Lens::inject function to specify the value we want to set into an arbitrary instance of Request. Now that we saw a basic example of a string lens, we want to dig into handling some more advanced JSON content.

JSON handling

We can choose from several JSON implementations, including e.g., the common Gson and Jackson library. I personally prefer Jackson as it comes with a great Kotlin module (Kudos to my friend Jayson Minard 😉). After adding a JSON format module to our application, we can start marshaling objects to and from HTTP messages using lenses. Let’s consider a partially complete REST API that manages persons:

[...]
import org.http4k.format.Jackson.auto

class PersonHandlerProvider(private val service: PersonService) {
    private val personLens: BiDiBodyLens<Person> = Body.auto<Person>().toLens()
    private val personListLens: BiDiBodyLens<List<Person>> = Body.auto<List<Person>>().toLens()

     fun getAllHandler(): HttpHandler = {
             Response(OK).with( 
                 personListLens of service.findAll()
             )
        }

     fun postHandler(): HttpHandler = { req ->
             val personToAdd = personLens.extract(req)
             service.add(personToAdd)
             Response(OK)
         }

     //...more
}

In this example, we see a class that provides two handlers representing common actions you would expect from a REST API. The getAllHandler fetches all currently stored entities and returns them to the client. We make use of a BiDiBodyLens<List<Person>> (BiDirectional) that we created via the org.http4k.format.Jackson.auto extension for Jackson. As noted in the http4k documentation, “the auto() method needs to be manually imported as IntelliJ won’t pick it up automatically”. We can use the resulting lens like already shown earlier by providing a value of type List<Person> and inject it into an HTTP Response as shown in the getAllHandler implementation.
The postHandler, on the other hand, provides an implementation of an HttpHandler, that extracts a Person entity from the request and adds it to the storage. Again, we use a lens to extract that JSON entity from the request easily.

This already concludes our sneak peek on lenses. As we saw, lenses are a fantastic tool that lets us extract and inject parts of an HTTP message and also provides simple means of validating those parts. Now, that we have seen the most fundamental concepts of the http4k toolset, let’s consider how we can test such applications.

Testing

Most of the time, when we consider testing applications that sit on top of a web framework, we have to worry about details of that framework which can make testing harder than it should be. Spoiler Alert: This is not quite the case with http4k 🎉

We have already learned that HttpHandlers, one of the two core concepts in the http4k toolset, are just regular Kotlin functions mapping requests to responses and even a complete http4k application again is just an HttpHandler and thus a callable function. As a result, entire and partial http4k apps can be tested easily and without additional work. Nevertheless, the makers of http4k thought that it would still be helpful to provide some additional modules which support us with testing our applications. One of these modules is http4k-testing-hamkrest, which adds a set of Hamkrest matchers, we can use to verify details of message objects more easily.

Http4k Handler Test Example

import com.natpryce.hamkrest.assertion.assertThat
import org.http4k.core.Method
import org.http4k.core.Request
import org.http4k.core.Status
import org.http4k.hamkrest.hasStatus
import org.junit.jupiter.api.Test

class PersonHandlerProviderTest {

    val systemUnderTest = PersonHandlerProvider(PersonService())

    @Test
    fun getAll_handler_can_be_invoked_as_expected(){
        val getAll: HttpHandler = systemUnderTest.getAllHandler()

        val result: Response = getAll(Request(Method.GET, "/some-uri"))

        assertThat(result, hasStatus(Status.OK))
    }
}

This snippet demonstrates a test for the PersonHandlerProvider we have worked with earlier already. As shown, it’s pretty straightforward to call an HttpHandler with a Request object and then use Hamkrest or whatever assertion library you prefer to check the resulting Response. Testing Filters, on the other hand, is “harder”. To be honest though, it’s just one tiny thing we need to do on top of what we did with handlers. Filters map one HttpHandler into another one by applying some intermediate pre or post-processing. Instead of investigating the mapping between handlers itself, it would be more convenient to again send a Request through that filter and look into the resulting Response. The good news is: It’s super easy to do just that:

Http4k Filter Test Example

val addExtraHeaderFilter = Filter { next ->
    {
        next(it).header("x-extra-header", "some value")
    }
}

@Test
fun adds_a_special_header() {
    val handler: HttpHandler = addExtraHeaderFilter.then { Response(OK) }

    val response: Response = handler(Request(GET, "/echo"))

    assertThat(response, hasStatus(OK).and(hasHeader("x-extra-header", "some value")))
}

We have a Filter called addExtraHeaderFilter that adds a custom header to a processed request and then forwards it to the next filter. The goal is to send a simple request through that filter in our test. What we can do, is making the filter a simple HttpHandler by adding a dumb { Response(OK) } handler to it via then. As a result, we can invoke the newly created handler, now containing our very own filter, and investigate whether the resulting Response object contains the new expected header. There we go – both handlers and filters got tested 🙃
To wrap up, I want to say that this was just a quick look at the happy paths of testing http4k apps with mostly familiar tools. It might become necessary to test against the actual running server and verify Responses on a lower level, e.g., comparing the resulting JSON directly. Doing that is also possible and supported via the Approval Testing module. Later in this article, we want to look at the client module of http4k, which again opens up some new possibilities.

Serverless

One of the hottest topics of our time is Serverless computing. You know, that thing where we can run our code on other people’s… servers. One part of it is known as Function as a Service, or FaaS and the most common ones include AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. The general idea is that these vendors provide a platform where we can deploy our code, and they take care of managing resources and scaling our application on demand. One of the downsides of Serverless is that our functions may be spun down by the platform if it’s not being used until someone wants to use it again, which would require a fresh startup. What does that mean for us? We need to choose target platforms and tools which allow a fast start-up of our application. Spring on the JVM in its classical form, for instance, would probably not be the best tool for that use case. However, as you can image, http4k with its small footprint and super quick start-up times is a great choice. It even comes with native support for AWS Lambda.

I won’t dive much deeper into this topic as part of this article, but I’m planning to write a much more detailed post on what we can do with http4k on a FaaS platform. Stay tuned.

Client as a Function

By now, we have learned how cool http4k is and why it’s a great tool to develop server applications. HTTP Servers don’t make much sense without clients using them, so we want to conclude this article by looking at the other side – Clients as a Function.
The http4k core library comes with everything we need to get started with clients. Clients in http4k again are just a special form of an HttpHandler, as we can see in this little snippet:

val request = Request(Method.GET, "https://kotlinexpertise.com/sitemap.xml")
val client: HttpHandler = JavaHttpClient()
val response = client(request)

The shown JavaHttpClient is the default implementation that comes with the core library. If we were to prefer OkHttp, Apache, or Jetty instead, we would find a related module to replace the default. Since we program against interfaces (clients are HttpHandlers), it’s not a big deal to swap out implementations at any time. The core library obviously comes with several default Filters we can apply to our client which can be found in the ClientFilters.kt file that contains stuff like BasicAuth, Gzip and more stuff you’d expect for a client. The fact that all concepts of http4k servers, including handlers, filters and also lenses, can be reused in http4k clients opens up quite a few possibilities so that it can make much sense to e.g., use the client module to test your servers an vice versa.

Summary and Lookout

I personally learned to appreciate http4k a lot in the last couple of weeks. Once you’ve made yourself comfortable with the basic concepts, it becomes straightforward to develop (which includes testing) server applications quickly. Http4k comes with an incredible list of supported concepts and technologies including OAuth, Swagger, Websockets, XML and many, many more. Its modular nature allows us to add functionality by applying dependencies as needed, and due to its simple base types, it is highly extensible. Http4k is a toolset that allows us to write applications with quick startup times which also makes it a valid alternative when it comes to FaaS and Serverless computing. As if this wasn’t enough, the toolset also includes sophisticated means for writing HTTP clients, which we learned about in the last section. Overall, http4k is a promising technology that you should definitely consider when choosing your next HTTP toolset.

If you want to learn more about Kotlin and its fantastic language features, please have a look at my talk “Diving into advanced language features”.

The post Server as a function with Kotlin – http4k appeared first on Kotlin Expertise Blog.

Continue ReadingServer as a function with Kotlin – http4k

Server as a function with Kotlin – http4k

Server as a function with Kotlin – http4k

Have you ever heard about the concept of “Server as a Function”? The idea is that we write our server application based on just ordinary functions, which is based on a concept outlined in the paper Your Server as a Function written and published by Twitter/Marius Eriksen. In the Kotlin world, the most prominent implementation of this concept is http4k, which the maintainers describe as an “HTTP toolset written in Kotlin with a focus on creating simple, testable APIs”. The best part about it is that http4k applications are just Kotlin functions that we can test straightforwardly. Take a look at this first example:

First http4k server example

val app: HttpHandler = { request: Request -> Response(OK).body(request.body) }
val server = app.asServer(SunHttp(8000)).start()

This code shows a fully functional http4k application consisting of a single Kotlin function app which we embedded into a SunHttp server, one example of available server implementations we may choose from. Note the type HttpHandler here, which represents one of the two essential concepts in the idea of “Server as a Function”:

  • HttpHandler ((Request) -> Response): abstraction to process HTTP requests into responses by mapping the first into the latter
  • Filter (HttpHandler -> HttpHandler): abstraction to add pre and post-processing like caching, debugging, authentication handling, and more to an HttpHandler. Filters are composable/stackable

Every http4k application can be composed of HttpHandlers in combination with Filters, both of which are simple type aliases for ordinary Kotlin function types. Http4k comes with zero dependencies if we don’t count the Kotlin standard library as one. Since http4k applications, in their pure form, only entail some nested Kotlin functions; there is no reflection or annotation processing involved. As a result, http4k applications can start and stop super quickly which also makes them a reasonable candidate to be deployed on Function-as-a-Service environments (as opposed to e.g., Spring Boot applications).

More advanced http4k application

Let’s take a look at a more advanced example of an http4k server.

val pingPongHandler: HttpHandler = { _ -> Response(OK).body("pong!") }

val greetHandler: HttpHandler = { req: Request ->
    val name: String? = req.query("name")
    Response(OK).body("hello ${name ?: "unknown!"}")
}

val routing: RoutingHttpHandler = routes(
     "/ping" bind GET to pingPongHandler,
     "/greet" bind GET to greetHandler
)

val requestTimeLogger: Filter = Filter { next: HttpHandler ->
     { request: Request ->
         val start = clock.millis()
         val response = next(request)
         val latency = clock.millis() - start
         logger { "Request to ${request.uri} took ${latency}ms" }
         response
     }
}

val app: HttpHandler =
     ResponseFilters.GZip()
     .then(requestTimeLogger)
     .then(routing)

In this snippet, we can see a few exciting things http4k applications may entail. The first two expressions are definitions of HttpHandlers, in which the first one takes any response and maps it to an OK response containing “pong” in its body. The second handler takes a request, extracts a name, and greets the caller. In the next step, we apply routing to the handlers by assigning one particular route to each handler. As we can see, the pingPongHandler is used to serve a client who invokes /ping, while the greetHandler is used to cover /greet.

Routing

Routing in http4k works with arbitrary levels of nesting, which works flawlessly since routing itself results in a new HttpHandler (strictly speaking, a special kind of type RoutingHttpHandler), just like the original ones.

Filters

As mentioned before, the other important concept we want to look at is Filters. For starters, we create a requestTimeLogger that intercepts each incoming request by measuring its processing time and logging the elapsed time. Filters can be combined using the then method, which allows us to define chains of filters. The corresponding API looks like this:

fun Filter.then(next: Filter): Filter

In the example application above, we add our custom filter to one of the default filters called GZip. Once we have combined all our filters, we want to add an HttpHandler to our filter chain. Again, there’s a then function we can use to do so:

fun Filter.then(next: HttpHandler): HttpHandler

As we can see, this again results in an HttpHandler. You all probably got the idea by now – It only needs two simple types to express how an HTTP server should operate.

The shown GZip filter is just one of many default filters we may choose from. Others cover concerns like caching, CORS, basic authentication or cookie handling and can be found in the org.http4k.filter package.

Calling HttpHandlers

So what did we get out of that nesting which resulted in yet another HttpHandler called app? Well, this itself does not entail running an actual server yet. However, it describes how requests are handled. We can use this object, as well as other separate HttpHandlers and Filters, and invoke it directly (e.g. in our tests). No HTTP required. Let’s see this in action:

//call handler directly
val handlerResponse: Response = pingPongHandler(Request(GET, "/any"))

//call handler through routing
val routingCallResponse: Response = app(Request(GET, "/ping").header("accept-encoding", "gzip"))

app.asServer(Jetty(9000)).start()

Http4k comes with its own implementations of a Request and a Response, first of which can be used to invoke an HttpHandler. Calling the unattractive pingPongHandler yields something similar to HTTP/1.1 200 OK pong! while calling the final app handler gives us a gzipped response due to the applied GZip filter. This call also implies a log informing about the duration of the request: 2019-09-20T21:22:55.300768Z LOG - Request to /ping took 3ms. Please note that, while it was fine to call pingPongHandler with a random URI (/any), we had to use the designated /ping URI when invoking the routing-backed app.
Last, but not least, we start our very own http4k HttpHandler as a server on a Jetty with port 9000. Find a list of available server implementations here.

Lenses

One of the things a sophisticated HTTP app has to deal with is taking stuff out and also putting stuff into HTTP messages. When we take parameters out of requests, we also care about validating these values. Http4k comes with a fascinating concept that helps us deal with the stated concerns: Lenses.

Basic Definition

Lenses, according to multiple resources, were first used in the Haskell world and are a functional concept that may appear slightly hard to understand. Let me try to describe it in a shallow, understandable manner. Let’s say we have a class Whole which comes with different fields part1, part2, and so on. A lens basically composes a getter and a setter focusing on precisely one part of Whole. A Part1Lens lens getter would take an instance of Whole to return the part it is focused on, i.e., part1. The lens setter, on the other hand, takes a Whole along with a value to set the focused part to and then returns a new Whole with the updated part. Remember that a lens can be used to both get and set a part of a whole object. Now, let’s learn how this concept helps us with handling HTTP messages.

Lenses in http4k

Following the basic idea of a lens, http4k lenses are bi-directional entities which can be used to either get or set a particular value from/onto an HTTP message. The corresponding API to describe lenses comes in the form of a DSL which also lets us define the requirement (optional vs. mandatory) of the HTTP part we are mounting a lens on. Since HTTP messages are a rather complex container, we can have lenses focusing on different areas of the messages: Query, Header, Path, FormField, Body. Let’s see some examples of how lenses can be created:

// lens focusing on the path variable name
val nameLens = Path.string().of("name")

// lens focusing on a required query parameter city
val requiredQuery = Query.required("city")

// lens focusing on a required and non empty string city 
val nonEmptyQuery = Query.nonEmptyString().required("city")

// lens focusing on an optional header Content-Length with type int 
val optionalHeader = Header.int().optional("Content-Length")

// lens focusing on text body
val responseBody = Body.string(ContentType.TEXT_PLAIN).toLens()

So far, the API for creating lenses looks more or less straightforward but what about using them on a target? Here’s the pseudo code syntax for
a) Retrieving a value: <lens>.extract(<target>), or <lens>(<target>)
b) Setting a value: <lens>.inject(<value>, <target>), or <lens>(<value>, <target>)

Use Lens to Retrieve value from HTTP Request

Reusing the greet sample from earlier, let’s modify our code to make use of lenses when retrieving a value:

val nameLens: BiDiLens<Request, String> =
    Query.nonEmptyString().required("name")

val greetHandler: HttpHandler = { req: Request ->
     val name: String = nameLens.extract(req) //or nameLens(req)
     Response(OK).body("hello $name")
}

We create a bidirectional lens focusing on the query part of our message to extract a required and non-empty name from it. Now, if a client happens to call the endpoint without providing a name query parameter, the lens automatically returns an error since it was defined as “required” and “nonEmpty”. Please note that, by default, the application exposes much detail to the client announcing the error as org.http4k.lens.LensFailure: query 'name' must be string including a detailed stack trace. Rather than that, we want to map all lens errors to HTTP 400 responses which implies that the client provided invalid data. Therefore, http4k offers a ServerFilters.CatchLensFailure filter which we can easily activate in our filter chain:

// gzip omitted
val app: HttpHandler = ServerFilters.CatchLensFailure
 .then(requestTimeLogger)
 .then(routing)

Use Lens to Set value in HTTP Request

After looking into extracting values from HTTP messages, how can we use the nameLens to set a value in an HTTP request?

val req = Request(GET, "/greet/{name}")
val reqWithName = nameLens.inject("kotlin", req)
// alternatively, http4k offers a with function that can apply multiple lenses at once
val reqWithName = Request(GET, "/greet/{name}").with(
    nameLens of "simon" //, more lenses
)

The example shows how we create an instance of Request and inject a value via one or many lenses. We can use the Lens::inject function to specify the value we want to set into an arbitrary instance of Request. Now that we saw a basic example of a string lens, we want to dig into handling some more advanced JSON content.

JSON handling

We can choose from several JSON implementations, including e.g., the common Gson and Jackson library. I personally prefer Jackson as it comes with a great Kotlin module (Kudos to my friend Jayson Minard 😉). After adding a JSON format module to our application, we can start marshaling objects to and from HTTP messages using lenses. Let’s consider a partially complete REST API that manages persons:

[...]
import org.http4k.format.Jackson.auto

class PersonHandlerProvider(private val service: PersonService) {
    private val personLens: BiDiBodyLens<Person> = Body.auto<Person>().toLens()
    private val personListLens: BiDiBodyLens<List<Person>> = Body.auto<List<Person>>().toLens()

     fun getAllHandler(): HttpHandler = {
             Response(OK).with( 
                 personListLens of service.findAll()
             )
        }

     fun postHandler(): HttpHandler = { req ->
             val personToAdd = personLens.extract(req)
             service.add(personToAdd)
             Response(OK)
         }

     //...more
}

In this example, we see a class that provides two handlers representing common actions you would expect from a REST API. The getAllHandler fetches all currently stored entities and returns them to the client. We make use of a BiDiBodyLens<List<Person>> (BiDirectional) that we created via the org.http4k.format.Jackson.auto extension for Jackson. As noted in the http4k documentation, “the auto() method needs to be manually imported as IntelliJ won’t pick it up automatically”. We can use the resulting lens like already shown earlier by providing a value of type List<Person> and inject it into an HTTP Response as shown in the getAllHandler implementation.
The postHandler, on the other hand, provides an implementation of an HttpHandler, that extracts a Person entity from the request and adds it to the storage. Again, we use a lens to extract that JSON entity from the request easily.

This already concludes our sneak peek on lenses. As we saw, lenses are a fantastic tool that lets us extract and inject parts of an HTTP message and also provides simple means of validating those parts. Now, that we have seen the most fundamental concepts of the http4k toolset, let’s consider how we can test such applications.

Testing

Most of the time, when we consider testing applications that sit on top of a web framework, we have to worry about details of that framework which can make testing harder than it should be. Spoiler Alert: This is not quite the case with http4k 🎉

We have already learned that HttpHandlers, one of the two core concepts in the http4k toolset, are just regular Kotlin functions mapping requests to responses and even a complete http4k application again is just an HttpHandler and thus a callable function. As a result, entire and partial http4k apps can be tested easily and without additional work. Nevertheless, the makers of http4k thought that it would still be helpful to provide some additional modules which support us with testing our applications. One of these modules is http4k-testing-hamkrest, which adds a set of Hamkrest matchers, we can use to verify details of message objects more easily.

Http4k Handler Test Example

import com.natpryce.hamkrest.assertion.assertThat
import org.http4k.core.Method
import org.http4k.core.Request
import org.http4k.core.Status
import org.http4k.hamkrest.hasStatus
import org.junit.jupiter.api.Test

class PersonHandlerProviderTest {

    val systemUnderTest = PersonHandlerProvider(PersonService())

    @Test
    fun getAll_handler_can_be_invoked_as_expected(){
        val getAll: HttpHandler = systemUnderTest.getAllHandler()

        val result: Response = getAll(Request(Method.GET, "/some-uri"))

        assertThat(result, hasStatus(Status.OK))
    }
}

This snippet demonstrates a test for the PersonHandlerProvider we have worked with earlier already. As shown, it’s pretty straightforward to call an HttpHandler with a Request object and then use Hamkrest or whatever assertion library you prefer to check the resulting Response. Testing Filters, on the other hand, is “harder”. To be honest though, it’s just one tiny thing we need to do on top of what we did with handlers. Filters map one HttpHandler into another one by applying some intermediate pre or post-processing. Instead of investigating the mapping between handlers itself, it would be more convenient to again send a Request through that filter and look into the resulting Response. The good news is: It’s super easy to do just that:

Http4k Filter Test Example

val addExtraHeaderFilter = Filter { next ->
    {
        next(it).header("x-extra-header", "some value")
    }
}

@Test
fun adds_a_special_header() {
    val handler: HttpHandler = addExtraHeaderFilter.then { Response(OK) }

    val response: Response = handler(Request(GET, "/echo"))

    assertThat(response, hasStatus(OK).and(hasHeader("x-extra-header", "some value")))
}

We have a Filter called addExtraHeaderFilter that adds a custom header to a processed request and then forwards it to the next filter. The goal is to send a simple request through that filter in our test. What we can do, is making the filter a simple HttpHandler by adding a dumb { Response(OK) } handler to it via then. As a result, we can invoke the newly created handler, now containing our very own filter, and investigate whether the resulting Response object contains the new expected header. There we go – both handlers and filters got tested 🙃
To wrap up, I want to say that this was just a quick look at the happy paths of testing http4k apps with mostly familiar tools. It might become necessary to test against the actual running server and verify Responses on a lower level, e.g., comparing the resulting JSON directly. Doing that is also possible and supported via the Approval Testing module. Later in this article, we want to look at the client module of http4k, which again opens up some new possibilities.

Serverless

One of the hottest topics of our time is Serverless computing. You know, that thing where we can run our code on other people’s… servers. One part of it is known as Function as a Service, or FaaS and the most common ones include AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. The general idea is that these vendors provide a platform where we can deploy our code, and they take care of managing resources and scaling our application on demand. One of the downsides of Serverless is that our functions may be spun down by the platform if it’s not being used until someone wants to use it again, which would require a fresh startup. What does that mean for us? We need to choose target platforms and tools which allow a fast start-up of our application. Spring on the JVM in its classical form, for instance, would probably not be the best tool for that use case. However, as you can image, http4k with its small footprint and super quick start-up times is a great choice. It even comes with native support for AWS Lambda.

I won’t dive much deeper into this topic as part of this article, but I’m planning to write a much more detailed post on what we can do with http4k on a FaaS platform. Stay tuned.

Client as a Function

By now, we have learned how cool http4k is and why it’s a great tool to develop server applications. HTTP Servers don’t make much sense without clients using them, so we want to conclude this article by looking at the other side – Clients as a Function.
The http4k core library comes with everything we need to get started with clients. Clients in http4k again are just a special form of an HttpHandler, as we can see in this little snippet:

val request = Request(Method.GET, "https://kotlinexpertise.com/sitemap.xml")
val client: HttpHandler = JavaHttpClient()
val response = client(request)

The shown JavaHttpClient is the default implementation that comes with the core library. If we were to prefer OkHttp, Apache, or Jetty instead, we would find a related module to replace the default. Since we program against interfaces (clients are HttpHandlers), it’s not a big deal to swap out implementations at any time. The core library obviously comes with several default Filters we can apply to our client which can be found in the ClientFilters.kt file that contains stuff like BasicAuth, Gzip and more stuff you’d expect for a client. The fact that all concepts of http4k servers, including handlers, filters and also lenses, can be reused in http4k clients opens up quite a few possibilities so that it can make much sense to e.g., use the client module to test your servers an vice versa.

Summary and Lookout

I personally learned to appreciate http4k a lot in the last couple of weeks. Once you’ve made yourself comfortable with the basic concepts, it becomes straightforward to develop (which includes testing) server applications quickly. Http4k comes with an incredible list of supported concepts and technologies including OAuth, Swagger, Websockets, XML and many, many more. Its modular nature allows us to add functionality by applying dependencies as needed, and due to its simple base types, it is highly extensible. Http4k is a toolset that allows us to write applications with quick startup times which also makes it a valid alternative when it comes to FaaS and Serverless computing. As if this wasn’t enough, the toolset also includes sophisticated means for writing HTTP clients, which we learned about in the last section. Overall, http4k is a promising technology that you should definitely consider when choosing your next HTTP toolset.

If you want to learn more about Kotlin and its fantastic language features, please have a look at my talk “Diving into advanced language features”.

The post Server as a function with Kotlin – http4k appeared first on Kotlin Expertise Blog.

Continue ReadingServer as a function with Kotlin – http4k

Server as a function with Kotlin – http4k

Server as a function with Kotlin – http4k

Have you ever heard about the concept of “Server as a Function”? The idea is that we write our server application based on just ordinary functions, which is based on a concept outlined in the paper Your Server as a Function written and published by Twitter/Marius Eriksen. In the Kotlin world, the most prominent implementation of this concept is http4k, which the maintainers describe as an “HTTP toolset written in Kotlin with a focus on creating simple, testable APIs”. The best part about it is that http4k applications are just Kotlin functions that we can test straightforwardly. Take a look at this first example:

First http4k server example

val app: HttpHandler = { request: Request -> Response(OK).body(request.body) }
val server = app.asServer(SunHttp(8000)).start()

This code shows a fully functional http4k application consisting of a single Kotlin function app which we embedded into a SunHttp server, one example of available server implementations we may choose from. Note the type HttpHandler here, which represents one of the two essential concepts in the idea of “Server as a Function”:

  • HttpHandler ((Request) -> Response): abstraction to process HTTP requests into responses by mapping the first into the latter
  • Filter (HttpHandler -> HttpHandler): abstraction to add pre and post-processing like caching, debugging, authentication handling, and more to an HttpHandler. Filters are composable/stackable

Every http4k application can be composed of HttpHandlers in combination with Filters, both of which are simple type aliases for ordinary Kotlin function types. Http4k comes with zero dependencies if we don’t count the Kotlin standard library as one. Since http4k applications, in their pure form, only entail some nested Kotlin functions; there is no reflection or annotation processing involved. As a result, http4k applications can start and stop super quickly which also makes them a reasonable candidate to be deployed on Function-as-a-Service environments (as opposed to e.g., Spring Boot applications).

More advanced http4k application

Let’s take a look at a more advanced example of an http4k server.

val pingPongHandler: HttpHandler = { _ -> Response(OK).body("pong!") }

val greetHandler: HttpHandler = { req: Request ->
    val name: String? = req.query("name")
    Response(OK).body("hello ${name ?: "unknown!"}")
}

val routing: RoutingHttpHandler = routes(
     "/ping" bind GET to pingPongHandler,
     "/greet" bind GET to greetHandler
)

val requestTimeLogger: Filter = Filter { next: HttpHandler ->
     { request: Request ->
         val start = clock.millis()
         val response = next(request)
         val latency = clock.millis() - start
         logger { "Request to ${request.uri} took ${latency}ms" }
         response
     }
}

val app: HttpHandler =
     ResponseFilters.GZip()
     .then(requestTimeLogger)
     .then(routing)

In this snippet, we can see a few exciting things http4k applications may entail. The first two expressions are definitions of HttpHandlers, in which the first one takes any response and maps it to an OK response containing “pong” in its body. The second handler takes a request, extracts a name, and greets the caller. In the next step, we apply routing to the handlers by assigning one particular route to each handler. As we can see, the pingPongHandler is used to serve a client who invokes /ping, while the greetHandler is used to cover /greet.

Routing

Routing in http4k works with arbitrary levels of nesting, which works flawlessly since routing itself results in a new HttpHandler (strictly speaking, a special kind of type RoutingHttpHandler), just like the original ones.

Filters

As mentioned before, the other important concept we want to look at is Filters. For starters, we create a requestTimeLogger that intercepts each incoming request by measuring its processing time and logging the elapsed time. Filters can be combined using the then method, which allows us to define chains of filters. The corresponding API looks like this:

fun Filter.then(next: Filter): Filter

In the example application above, we add our custom filter to one of the default filters called GZip. Once we have combined all our filters, we want to add an HttpHandler to our filter chain. Again, there’s a then function we can use to do so:

fun Filter.then(next: HttpHandler): HttpHandler

As we can see, this again results in an HttpHandler. You all probably got the idea by now – It only needs two simple types to express how an HTTP server should operate.

The shown GZip filter is just one of many default filters we may choose from. Others cover concerns like caching, CORS, basic authentication or cookie handling and can be found in the org.http4k.filter package.

Calling HttpHandlers

So what did we get out of that nesting which resulted in yet another HttpHandler called app? Well, this itself does not entail running an actual server yet. However, it describes how requests are handled. We can use this object, as well as other separate HttpHandlers and Filters, and invoke it directly (e.g. in our tests). No HTTP required. Let’s see this in action:

//call handler directly
val handlerResponse: Response = pingPongHandler(Request(GET, "/any"))

//call handler through routing
val routingCallResponse: Response = app(Request(GET, "/ping").header("accept-encoding", "gzip"))

app.asServer(Jetty(9000)).start()

Http4k comes with its own implementations of a Request and a Response, first of which can be used to invoke an HttpHandler. Calling the unattractive pingPongHandler yields something similar to HTTP/1.1 200 OK pong! while calling the final app handler gives us a gzipped response due to the applied GZip filter. This call also implies a log informing about the duration of the request: 2019-09-20T21:22:55.300768Z LOG - Request to /ping took 3ms. Please note that, while it was fine to call pingPongHandler with a random URI (/any), we had to use the designated /ping URI when invoking the routing-backed app.
Last, but not least, we start our very own http4k HttpHandler as a server on a Jetty with port 9000. Find a list of available server implementations here.

Lenses

One of the things a sophisticated HTTP app has to deal with is taking stuff out and also putting stuff into HTTP messages. When we take parameters out of requests, we also care about validating these values. Http4k comes with a fascinating concept that helps us deal with the stated concerns: Lenses.

Basic Definition

Lenses, according to multiple resources, were first used in the Haskell world and are a functional concept that may appear slightly hard to understand. Let me try to describe it in a shallow, understandable manner. Let’s say we have a class Whole which comes with different fields part1, part2, and so on. A lens basically composes a getter and a setter focusing on precisely one part of Whole. A Part1Lens lens getter would take an instance of Whole to return the part it is focused on, i.e., part1. The lens setter, on the other hand, takes a Whole along with a value to set the focused part to and then returns a new Whole with the updated part. Remember that a lens can be used to both get and set a part of a whole object. Now, let’s learn how this concept helps us with handling HTTP messages.

Lenses in http4k

Following the basic idea of a lens, http4k lenses are bi-directional entities which can be used to either get or set a particular value from/onto an HTTP message. The corresponding API to describe lenses comes in the form of a DSL which also lets us define the requirement (optional vs. mandatory) of the HTTP part we are mounting a lens on. Since HTTP messages are a rather complex container, we can have lenses focusing on different areas of the messages: Query, Header, Path, FormField, Body. Let’s see some examples of how lenses can be created:

// lens focusing on the path variable name
val nameLens = Path.string().of("name")

// lens focusing on a required query parameter city
val requiredQuery = Query.required("city")

// lens focusing on a required and non empty string city 
val nonEmptyQuery = Query.nonEmptyString().required("city")

// lens focusing on an optional header Content-Length with type int 
val optionalHeader = Header.int().optional("Content-Length")

// lens focusing on text body
val responseBody = Body.string(ContentType.TEXT_PLAIN).toLens()

So far, the API for creating lenses looks more or less straightforward but what about using them on a target? Here’s the pseudo code syntax for
a) Retrieving a value: <lens>.extract(<target>), or <lens>(<target>)
b) Setting a value: <lens>.inject(<value>, <target>), or <lens>(<value>, <target>)

Use Lens to Retrieve value from HTTP Request

Reusing the greet sample from earlier, let’s modify our code to make use of lenses when retrieving a value:

val nameLens: BiDiLens<Request, String> =
    Query.nonEmptyString().required("name")

val greetHandler: HttpHandler = { req: Request ->
     val name: String = nameLens.extract(req) //or nameLens(req)
     Response(OK).body("hello $name")
}

We create a bidirectional lens focusing on the query part of our message to extract a required and non-empty name from it. Now, if a client happens to call the endpoint without providing a name query parameter, the lens automatically returns an error since it was defined as “required” and “nonEmpty”. Please note that, by default, the application exposes much detail to the client announcing the error as org.http4k.lens.LensFailure: query 'name' must be string including a detailed stack trace. Rather than that, we want to map all lens errors to HTTP 400 responses which implies that the client provided invalid data. Therefore, http4k offers a ServerFilters.CatchLensFailure filter which we can easily activate in our filter chain:

// gzip omitted
val app: HttpHandler = ServerFilters.CatchLensFailure
 .then(requestTimeLogger)
 .then(routing)

Use Lens to Set value in HTTP Request

After looking into extracting values from HTTP messages, how can we use the nameLens to set a value in an HTTP request?

val req = Request(GET, "/greet/{name}")
val reqWithName = nameLens.inject("kotlin", req)
// alternatively, http4k offers a with function that can apply multiple lenses at once
val reqWithName = Request(GET, "/greet/{name}").with(
    nameLens of "simon" //, more lenses
)

The example shows how we create an instance of Request and inject a value via one or many lenses. We can use the Lens::inject function to specify the value we want to set into an arbitrary instance of Request. Now that we saw a basic example of a string lens, we want to dig into handling some more advanced JSON content.

JSON handling

We can choose from several JSON implementations, including e.g., the common Gson and Jackson library. I personally prefer Jackson as it comes with a great Kotlin module (Kudos to my friend Jayson Minard 😉). After adding a JSON format module to our application, we can start marshaling objects to and from HTTP messages using lenses. Let’s consider a partially complete REST API that manages persons:

[...]
import org.http4k.format.Jackson.auto

class PersonHandlerProvider(private val service: PersonService) {
    private val personLens: BiDiBodyLens<Person> = Body.auto<Person>().toLens()
    private val personListLens: BiDiBodyLens<List<Person>> = Body.auto<List<Person>>().toLens()

     fun getAllHandler(): HttpHandler = {
             Response(OK).with( 
                 personListLens of service.findAll()
             )
        }

     fun postHandler(): HttpHandler = { req ->
             val personToAdd = personLens.extract(req)
             service.add(personToAdd)
             Response(OK)
         }

     //...more
}

In this example, we see a class that provides two handlers representing common actions you would expect from a REST API. The getAllHandler fetches all currently stored entities and returns them to the client. We make use of a BiDiBodyLens<List<Person>> (BiDirectional) that we created via the org.http4k.format.Jackson.auto extension for Jackson. As noted in the http4k documentation, “the auto() method needs to be manually imported as IntelliJ won’t pick it up automatically”. We can use the resulting lens like already shown earlier by providing a value of type List<Person> and inject it into an HTTP Response as shown in the getAllHandler implementation.
The postHandler, on the other hand, provides an implementation of an HttpHandler, that extracts a Person entity from the request and adds it to the storage. Again, we use a lens to extract that JSON entity from the request easily.

This already concludes our sneak peek on lenses. As we saw, lenses are a fantastic tool that lets us extract and inject parts of an HTTP message and also provides simple means of validating those parts. Now, that we have seen the most fundamental concepts of the http4k toolset, let’s consider how we can test such applications.

Testing

Most of the time, when we consider testing applications that sit on top of a web framework, we have to worry about details of that framework which can make testing harder than it should be. Spoiler Alert: This is not quite the case with http4k 🎉

We have already learned that HttpHandlers, one of the two core concepts in the http4k toolset, are just regular Kotlin functions mapping requests to responses and even a complete http4k application again is just an HttpHandler and thus a callable function. As a result, entire and partial http4k apps can be tested easily and without additional work. Nevertheless, the makers of http4k thought that it would still be helpful to provide some additional modules which support us with testing our applications. One of these modules is http4k-testing-hamkrest, which adds a set of Hamkrest matchers, we can use to verify details of message objects more easily.

Http4k Handler Test Example

import com.natpryce.hamkrest.assertion.assertThat
import org.http4k.core.Method
import org.http4k.core.Request
import org.http4k.core.Status
import org.http4k.hamkrest.hasStatus
import org.junit.jupiter.api.Test

class PersonHandlerProviderTest {

    val systemUnderTest = PersonHandlerProvider(PersonService())

    @Test
    fun getAll_handler_can_be_invoked_as_expected(){
        val getAll: HttpHandler = systemUnderTest.getAllHandler()

        val result: Response = getAll(Request(Method.GET, "/some-uri"))

        assertThat(result, hasStatus(Status.OK))
    }
}

This snippet demonstrates a test for the PersonHandlerProvider we have worked with earlier already. As shown, it’s pretty straightforward to call an HttpHandler with a Request object and then use Hamkrest or whatever assertion library you prefer to check the resulting Response. Testing Filters, on the other hand, is “harder”. To be honest though, it’s just one tiny thing we need to do on top of what we did with handlers. Filters map one HttpHandler into another one by applying some intermediate pre or post-processing. Instead of investigating the mapping between handlers itself, it would be more convenient to again send a Request through that filter and look into the resulting Response. The good news is: It’s super easy to do just that:

Http4k Filter Test Example

val addExtraHeaderFilter = Filter { next ->
    {
        next(it).header("x-extra-header", "some value")
    }
}

@Test
fun adds_a_special_header() {
    val handler: HttpHandler = addExtraHeaderFilter.then { Response(OK) }

    val response: Response = handler(Request(GET, "/echo"))

    assertThat(response, hasStatus(OK).and(hasHeader("x-extra-header", "some value")))
}

We have a Filter called addExtraHeaderFilter that adds a custom header to a processed request and then forwards it to the next filter. The goal is to send a simple request through that filter in our test. What we can do, is making the filter a simple HttpHandler by adding a dumb { Response(OK) } handler to it via then. As a result, we can invoke the newly created handler, now containing our very own filter, and investigate whether the resulting Response object contains the new expected header. There we go – both handlers and filters got tested 🙃
To wrap up, I want to say that this was just a quick look at the happy paths of testing http4k apps with mostly familiar tools. It might become necessary to test against the actual running server and verify Responses on a lower level, e.g., comparing the resulting JSON directly. Doing that is also possible and supported via the Approval Testing module. Later in this article, we want to look at the client module of http4k, which again opens up some new possibilities.

Serverless

One of the hottest topics of our time is Serverless computing. You know, that thing where we can run our code on other people’s… servers. One part of it is known as Function as a Service, or FaaS and the most common ones include AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. The general idea is that these vendors provide a platform where we can deploy our code, and they take care of managing resources and scaling our application on demand. One of the downsides of Serverless is that our functions may be spun down by the platform if it’s not being used until someone wants to use it again, which would require a fresh startup. What does that mean for us? We need to choose target platforms and tools which allow a fast start-up of our application. Spring on the JVM in its classical form, for instance, would probably not be the best tool for that use case. However, as you can image, http4k with its small footprint and super quick start-up times is a great choice. It even comes with native support for AWS Lambda.

I won’t dive much deeper into this topic as part of this article, but I’m planning to write a much more detailed post on what we can do with http4k on a FaaS platform. Stay tuned.

Client as a Function

By now, we have learned how cool http4k is and why it’s a great tool to develop server applications. HTTP Servers don’t make much sense without clients using them, so we want to conclude this article by looking at the other side – Clients as a Function.
The http4k core library comes with everything we need to get started with clients. Clients in http4k again are just a special form of an HttpHandler, as we can see in this little snippet:

val request = Request(Method.GET, "https://kotlinexpertise.com/sitemap.xml")
val client: HttpHandler = JavaHttpClient()
val response = client(request)

The shown JavaHttpClient is the default implementation that comes with the core library. If we were to prefer OkHttp, Apache, or Jetty instead, we would find a related module to replace the default. Since we program against interfaces (clients are HttpHandlers), it’s not a big deal to swap out implementations at any time. The core library obviously comes with several default Filters we can apply to our client which can be found in the ClientFilters.kt file that contains stuff like BasicAuth, Gzip and more stuff you’d expect for a client. The fact that all concepts of http4k servers, including handlers, filters and also lenses, can be reused in http4k clients opens up quite a few possibilities so that it can make much sense to e.g., use the client module to test your servers an vice versa.

Summary and Lookout

I personally learned to appreciate http4k a lot in the last couple of weeks. Once you’ve made yourself comfortable with the basic concepts, it becomes straightforward to develop (which includes testing) server applications quickly. Http4k comes with an incredible list of supported concepts and technologies including OAuth, Swagger, Websockets, XML and many, many more. Its modular nature allows us to add functionality by applying dependencies as needed, and due to its simple base types, it is highly extensible. Http4k is a toolset that allows us to write applications with quick startup times which also makes it a valid alternative when it comes to FaaS and Serverless computing. As if this wasn’t enough, the toolset also includes sophisticated means for writing HTTP clients, which we learned about in the last section. Overall, http4k is a promising technology that you should definitely consider when choosing your next HTTP toolset.

If you want to learn more about Kotlin and its fantastic language features, please have a look at my talk “Diving into advanced language features”.

The post Server as a function with Kotlin – http4k appeared first on Kotlin Expertise Blog.

Continue ReadingServer as a function with Kotlin – http4k

Server as a function with Kotlin – http4k

Server as a function with Kotlin – http4k

Have you ever heard about the concept of “Server as a Function”? The idea is that we write our server application based on just ordinary functions, which is based on a concept outlined in the paper Your Server as a Function written and published by Twitter/Marius Eriksen. In the Kotlin world, the most prominent implementation of this concept is http4k, which the maintainers describe as an “HTTP toolset written in Kotlin with a focus on creating simple, testable APIs”. The best part about it is that http4k applications are just Kotlin functions that we can test straightforwardly. Take a look at this first example:

First http4k server example

val app: HttpHandler = { request: Request -> Response(OK).body(request.body) }
val server = app.asServer(SunHttp(8000)).start()

This code shows a fully functional http4k application consisting of a single Kotlin function app which we embedded into a SunHttp server, one example of available server implementations we may choose from. Note the type HttpHandler here, which represents one of the two essential concepts in the idea of “Server as a Function”:

  • HttpHandler ((Request) -> Response): abstraction to process HTTP requests into responses by mapping the first into the latter
  • Filter (HttpHandler -> HttpHandler): abstraction to add pre and post-processing like caching, debugging, authentication handling, and more to an HttpHandler. Filters are composable/stackable

Every http4k application can be composed of HttpHandlers in combination with Filters, both of which are simple type aliases for ordinary Kotlin function types. Http4k comes with zero dependencies if we don’t count the Kotlin standard library as one. Since http4k applications, in their pure form, only entail some nested Kotlin functions; there is no reflection or annotation processing involved. As a result, http4k applications can start and stop super quickly which also makes them a reasonable candidate to be deployed on Function-as-a-Service environments (as opposed to e.g., Spring Boot applications).

More advanced http4k application

Let’s take a look at a more advanced example of an http4k server.

val pingPongHandler: HttpHandler = { _ -> Response(OK).body("pong!") }

val greetHandler: HttpHandler = { req: Request ->
    val name: String? = req.query("name")
    Response(OK).body("hello ${name ?: "unknown!"}")
}

val routing: RoutingHttpHandler = routes(
     "/ping" bind GET to pingPongHandler,
     "/greet" bind GET to greetHandler
)

val requestTimeLogger: Filter = Filter { next: HttpHandler ->
     { request: Request ->
         val start = clock.millis()
         val response = next(request)
         val latency = clock.millis() - start
         logger { "Request to ${request.uri} took ${latency}ms" }
         response
     }
}

val app: HttpHandler =
     ResponseFilters.GZip()
     .then(requestTimeLogger)
     .then(routing)

In this snippet, we can see a few exciting things http4k applications may entail. The first two expressions are definitions of HttpHandlers, in which the first one takes any response and maps it to an OK response containing “pong” in its body. The second handler takes a request, extracts a name, and greets the caller. In the next step, we apply routing to the handlers by assigning one particular route to each handler. As we can see, the pingPongHandler is used to serve a client who invokes /ping, while the greetHandler is used to cover /greet.

Routing

Routing in http4k works with arbitrary levels of nesting, which works flawlessly since routing itself results in a new HttpHandler (strictly speaking, a special kind of type RoutingHttpHandler), just like the original ones.

Filters

As mentioned before, the other important concept we want to look at is Filters. For starters, we create a requestTimeLogger that intercepts each incoming request by measuring its processing time and logging the elapsed time. Filters can be combined using the then method, which allows us to define chains of filters. The corresponding API looks like this:

fun Filter.then(next: Filter): Filter

In the example application above, we add our custom filter to one of the default filters called GZip. Once we have combined all our filters, we want to add an HttpHandler to our filter chain. Again, there’s a then function we can use to do so:

fun Filter.then(next: HttpHandler): HttpHandler

As we can see, this again results in an HttpHandler. You all probably got the idea by now – It only needs two simple types to express how an HTTP server should operate.

The shown GZip filter is just one of many default filters we may choose from. Others cover concerns like caching, CORS, basic authentication or cookie handling and can be found in the org.http4k.filter package.

Calling HttpHandlers

So what did we get out of that nesting which resulted in yet another HttpHandler called app? Well, this itself does not entail running an actual server yet. However, it describes how requests are handled. We can use this object, as well as other separate HttpHandlers and Filters, and invoke it directly (e.g. in our tests). No HTTP required. Let’s see this in action:

//call handler directly
val handlerResponse: Response = pingPongHandler(Request(GET, "/any"))

//call handler through routing
val routingCallResponse: Response = app(Request(GET, "/ping").header("accept-encoding", "gzip"))

app.asServer(Jetty(9000)).start()

Http4k comes with its own implementations of a Request and a Response, first of which can be used to invoke an HttpHandler. Calling the unattractive pingPongHandler yields something similar to HTTP/1.1 200 OK pong! while calling the final app handler gives us a gzipped response due to the applied GZip filter. This call also implies a log informing about the duration of the request: 2019-09-20T21:22:55.300768Z LOG - Request to /ping took 3ms. Please note that, while it was fine to call pingPongHandler with a random URI (/any), we had to use the designated /ping URI when invoking the routing-backed app.
Last, but not least, we start our very own http4k HttpHandler as a server on a Jetty with port 9000. Find a list of available server implementations here.

Lenses

One of the things a sophisticated HTTP app has to deal with is taking stuff out and also putting stuff into HTTP messages. When we take parameters out of requests, we also care about validating these values. Http4k comes with a fascinating concept that helps us deal with the stated concerns: Lenses.

Basic Definition

Lenses, according to multiple resources, were first used in the Haskell world and are a functional concept that may appear slightly hard to understand. Let me try to describe it in a shallow, understandable manner. Let’s say we have a class Whole which comes with different fields part1, part2, and so on. A lens basically composes a getter and a setter focusing on precisely one part of Whole. A Part1Lens lens getter would take an instance of Whole to return the part it is focused on, i.e., part1. The lens setter, on the other hand, takes a Whole along with a value to set the focused part to and then returns a new Whole with the updated part. Remember that a lens can be used to both get and set a part of a whole object. Now, let’s learn how this concept helps us with handling HTTP messages.

Lenses in http4k

Following the basic idea of a lens, http4k lenses are bi-directional entities which can be used to either get or set a particular value from/onto an HTTP message. The corresponding API to describe lenses comes in the form of a DSL which also lets us define the requirement (optional vs. mandatory) of the HTTP part we are mounting a lens on. Since HTTP messages are a rather complex container, we can have lenses focusing on different areas of the messages: Query, Header, Path, FormField, Body. Let’s see some examples of how lenses can be created:

// lens focusing on the path variable name
val nameLens = Path.string().of("name")

// lens focusing on a required query parameter city
val requiredQuery = Query.required("city")

// lens focusing on a required and non empty string city 
val nonEmptyQuery = Query.nonEmptyString().required("city")

// lens focusing on an optional header Content-Length with type int 
val optionalHeader = Header.int().optional("Content-Length")

// lens focusing on text body
val responseBody = Body.string(ContentType.TEXT_PLAIN).toLens()

So far, the API for creating lenses looks more or less straightforward but what about using them on a target? Here’s the pseudo code syntax for
a) Retrieving a value: <lens>.extract(<target>), or <lens>(<target>)
b) Setting a value: <lens>.inject(<value>, <target>), or <lens>(<value>, <target>)

Use Lens to Retrieve value from HTTP Request

Reusing the greet sample from earlier, let’s modify our code to make use of lenses when retrieving a value:

val nameLens: BiDiLens<Request, String> =
    Query.nonEmptyString().required("name")

val greetHandler: HttpHandler = { req: Request ->
     val name: String = nameLens.extract(req) //or nameLens(req)
     Response(OK).body("hello $name")
}

We create a bidirectional lens focusing on the query part of our message to extract a required and non-empty name from it. Now, if a client happens to call the endpoint without providing a name query parameter, the lens automatically returns an error since it was defined as “required” and “nonEmpty”. Please note that, by default, the application exposes much detail to the client announcing the error as org.http4k.lens.LensFailure: query 'name' must be string including a detailed stack trace. Rather than that, we want to map all lens errors to HTTP 400 responses which implies that the client provided invalid data. Therefore, http4k offers a ServerFilters.CatchLensFailure filter which we can easily activate in our filter chain:

// gzip omitted
val app: HttpHandler = ServerFilters.CatchLensFailure
 .then(requestTimeLogger)
 .then(routing)

Use Lens to Set value in HTTP Request

After looking into extracting values from HTTP messages, how can we use the nameLens to set a value in an HTTP request?

val req = Request(GET, "/greet/{name}")
val reqWithName = nameLens.inject("kotlin", req)
// alternatively, http4k offers a with function that can apply multiple lenses at once
val reqWithName = Request(GET, "/greet/{name}").with(
    nameLens of "simon" //, more lenses
)

The example shows how we create an instance of Request and inject a value via one or many lenses. We can use the Lens::inject function to specify the value we want to set into an arbitrary instance of Request. Now that we saw a basic example of a string lens, we want to dig into handling some more advanced JSON content.

JSON handling

We can choose from several JSON implementations, including e.g., the common Gson and Jackson library. I personally prefer Jackson as it comes with a great Kotlin module (Kudos to my friend Jayson Minard 😉). After adding a JSON format module to our application, we can start marshaling objects to and from HTTP messages using lenses. Let’s consider a partially complete REST API that manages persons:

[...]
import org.http4k.format.Jackson.auto

class PersonHandlerProvider(private val service: PersonService) {
    private val personLens: BiDiBodyLens<Person> = Body.auto<Person>().toLens()
    private val personListLens: BiDiBodyLens<List<Person>> = Body.auto<List<Person>>().toLens()

     fun getAllHandler(): HttpHandler = {
             Response(OK).with( 
                 personListLens of service.findAll()
             )
        }

     fun postHandler(): HttpHandler = { req ->
             val personToAdd = personLens.extract(req)
             service.add(personToAdd)
             Response(OK)
         }

     //...more
}

In this example, we see a class that provides two handlers representing common actions you would expect from a REST API. The getAllHandler fetches all currently stored entities and returns them to the client. We make use of a BiDiBodyLens<List<Person>> (BiDirectional) that we created via the org.http4k.format.Jackson.auto extension for Jackson. As noted in the http4k documentation, “the auto() method needs to be manually imported as IntelliJ won’t pick it up automatically”. We can use the resulting lens like already shown earlier by providing a value of type List<Person> and inject it into an HTTP Response as shown in the getAllHandler implementation.
The postHandler, on the other hand, provides an implementation of an HttpHandler, that extracts a Person entity from the request and adds it to the storage. Again, we use a lens to extract that JSON entity from the request easily.

This already concludes our sneak peek on lenses. As we saw, lenses are a fantastic tool that lets us extract and inject parts of an HTTP message and also provides simple means of validating those parts. Now, that we have seen the most fundamental concepts of the http4k toolset, let’s consider how we can test such applications.

Testing

Most of the time, when we consider testing applications that sit on top of a web framework, we have to worry about details of that framework which can make testing harder than it should be. Spoiler Alert: This is not quite the case with http4k 🎉

We have already learned that HttpHandlers, one of the two core concepts in the http4k toolset, are just regular Kotlin functions mapping requests to responses and even a complete http4k application again is just an HttpHandler and thus a callable function. As a result, entire and partial http4k apps can be tested easily and without additional work. Nevertheless, the makers of http4k thought that it would still be helpful to provide some additional modules which support us with testing our applications. One of these modules is http4k-testing-hamkrest, which adds a set of Hamkrest matchers, we can use to verify details of message objects more easily.

Http4k Handler Test Example

import com.natpryce.hamkrest.assertion.assertThat
import org.http4k.core.Method
import org.http4k.core.Request
import org.http4k.core.Status
import org.http4k.hamkrest.hasStatus
import org.junit.jupiter.api.Test

class PersonHandlerProviderTest {

    val systemUnderTest = PersonHandlerProvider(PersonService())

    @Test
    fun getAll_handler_can_be_invoked_as_expected(){
        val getAll: HttpHandler = systemUnderTest.getAllHandler()

        val result: Response = getAll(Request(Method.GET, "/some-uri"))

        assertThat(result, hasStatus(Status.OK))
    }
}

This snippet demonstrates a test for the PersonHandlerProvider we have worked with earlier already. As shown, it’s pretty straightforward to call an HttpHandler with a Request object and then use Hamkrest or whatever assertion library you prefer to check the resulting Response. Testing Filters, on the other hand, is “harder”. To be honest though, it’s just one tiny thing we need to do on top of what we did with handlers. Filters map one HttpHandler into another one by applying some intermediate pre or post-processing. Instead of investigating the mapping between handlers itself, it would be more convenient to again send a Request through that filter and look into the resulting Response. The good news is: It’s super easy to do just that:

Http4k Filter Test Example

val addExtraHeaderFilter = Filter { next ->
    {
        next(it).header("x-extra-header", "some value")
    }
}

@Test
fun adds_a_special_header() {
    val handler: HttpHandler = addExtraHeaderFilter.then { Response(OK) }

    val response: Response = handler(Request(GET, "/echo"))

    assertThat(response, hasStatus(OK).and(hasHeader("x-extra-header", "some value")))
}

We have a Filter called addExtraHeaderFilter that adds a custom header to a processed request and then forwards it to the next filter. The goal is to send a simple request through that filter in our test. What we can do, is making the filter a simple HttpHandler by adding a dumb { Response(OK) } handler to it via then. As a result, we can invoke the newly created handler, now containing our very own filter, and investigate whether the resulting Response object contains the new expected header. There we go – both handlers and filters got tested 🙃
To wrap up, I want to say that this was just a quick look at the happy paths of testing http4k apps with mostly familiar tools. It might become necessary to test against the actual running server and verify Responses on a lower level, e.g., comparing the resulting JSON directly. Doing that is also possible and supported via the Approval Testing module. Later in this article, we want to look at the client module of http4k, which again opens up some new possibilities.

Serverless

One of the hottest topics of our time is Serverless computing. You know, that thing where we can run our code on other people’s… servers. One part of it is known as Function as a Service, or FaaS and the most common ones include AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. The general idea is that these vendors provide a platform where we can deploy our code, and they take care of managing resources and scaling our application on demand. One of the downsides of Serverless is that our functions may be spun down by the platform if it’s not being used until someone wants to use it again, which would require a fresh startup. What does that mean for us? We need to choose target platforms and tools which allow a fast start-up of our application. Spring on the JVM in its classical form, for instance, would probably not be the best tool for that use case. However, as you can image, http4k with its small footprint and super quick start-up times is a great choice. It even comes with native support for AWS Lambda.

I won’t dive much deeper into this topic as part of this article, but I’m planning to write a much more detailed post on what we can do with http4k on a FaaS platform. Stay tuned.

Client as a Function

By now, we have learned how cool http4k is and why it’s a great tool to develop server applications. HTTP Servers don’t make much sense without clients using them, so we want to conclude this article by looking at the other side – Clients as a Function.
The http4k core library comes with everything we need to get started with clients. Clients in http4k again are just a special form of an HttpHandler, as we can see in this little snippet:

val request = Request(Method.GET, "https://kotlinexpertise.com/sitemap.xml")
val client: HttpHandler = JavaHttpClient()
val response = client(request)

The shown JavaHttpClient is the default implementation that comes with the core library. If we were to prefer OkHttp, Apache, or Jetty instead, we would find a related module to replace the default. Since we program against interfaces (clients are HttpHandlers), it’s not a big deal to swap out implementations at any time. The core library obviously comes with several default Filters we can apply to our client which can be found in the ClientFilters.kt file that contains stuff like BasicAuth, Gzip and more stuff you’d expect for a client. The fact that all concepts of http4k servers, including handlers, filters and also lenses, can be reused in http4k clients opens up quite a few possibilities so that it can make much sense to e.g., use the client module to test your servers an vice versa.

Summary and Lookout

I personally learned to appreciate http4k a lot in the last couple of weeks. Once you’ve made yourself comfortable with the basic concepts, it becomes straightforward to develop (which includes testing) server applications quickly. Http4k comes with an incredible list of supported concepts and technologies including OAuth, Swagger, Websockets, XML and many, many more. Its modular nature allows us to add functionality by applying dependencies as needed, and due to its simple base types, it is highly extensible. Http4k is a toolset that allows us to write applications with quick startup times which also makes it a valid alternative when it comes to FaaS and Serverless computing. As if this wasn’t enough, the toolset also includes sophisticated means for writing HTTP clients, which we learned about in the last section. Overall, http4k is a promising technology that you should definitely consider when choosing your next HTTP toolset.

If you want to learn more about Kotlin and its fantastic language features, please have a look at my talk “Diving into advanced language features”.

The post Server as a function with Kotlin – http4k appeared first on Kotlin Expertise Blog.

Continue ReadingServer as a function with Kotlin – http4k

End of content

No more pages to load