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

HttpHandler

s in combination with

Filter

s, 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

HttpHandler

s, 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

Filter

s. 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

HttpHandler

s and

Filter

s, 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

Filter

s, 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

HttpHandler

s), it’s not a big deal to swap out implementations at any time. The

core

library obviously comes with several default

Filter

s 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 Reading Server 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

HttpHandler

s in combination with

Filter

s, 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

HttpHandler

s, 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

Filter

s. 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

HttpHandler

s and

Filter

s, 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

Filter

s, 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

HttpHandler

s), it’s not a big deal to swap out implementations at any time. The

core

library obviously comes with several default

Filter

s 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 Reading Server 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

HttpHandler

s in combination with

Filter

s, 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

HttpHandler

s, 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

Filter

s. 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

HttpHandler

s and

Filter

s, 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

Filter

s, 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

HttpHandler

s), it’s not a big deal to swap out implementations at any time. The

core

library obviously comes with several default

Filter

s 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 Reading Server 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

HttpHandler

s in combination with

Filter

s, 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

HttpHandler

s, 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

Filter

s. 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

HttpHandler

s and

Filter

s, 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

Filter

s, 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

HttpHandler

s), it’s not a big deal to swap out implementations at any time. The

core

library obviously comes with several default

Filter

s 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 Reading Server 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

HttpHandler

s in combination with

Filter

s, 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

HttpHandler

s, 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

Filter

s. 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

HttpHandler

s and

Filter

s, 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

Filter

s, 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

HttpHandler

s), it’s not a big deal to swap out implementations at any time. The

core

library obviously comes with several default

Filter

s 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 Reading Server 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

HttpHandler

s in combination with

Filter

s, 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

HttpHandler

s, 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

Filter

s. 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

HttpHandler

s and

Filter

s, 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

Filter

s, 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

HttpHandler

s), it’s not a big deal to swap out implementations at any time. The

core

library obviously comes with several default

Filter

s 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 Reading Server 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

HttpHandler

s in combination with

Filter

s, 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

HttpHandler

s, 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

Filter

s. 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

HttpHandler

s and

Filter

s, 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

Filter

s, 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

HttpHandler

s), it’s not a big deal to swap out implementations at any time. The

core

library obviously comes with several default

Filter

s 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 Reading Server as a function with Kotlin – http4k

How Kotlin makes me a more productive software developer

How Kotlin makes me a more productive software developer

I’ve been writing JVM code for more than seven years now, and I did so mainly using Java. This changed about two years ago when I picked up Kotlin. By now, I managed to drop the Java language more-or-less entirely in favor of Kotlin. I did this because I feel much more productive with the language. It lets me focus more on the business logic rather than forcing me to write boilerplate code over and over again. In this post, I tell you how Kotlin makes me a more productive developer.
I certainly know Kotlin much better than I ever knew Java. FWIW, I had been certified as a Java expert by Oracle some years back. Still, Kotlin became my native programming language, and I want to encourage you to consider it too. When I talk about my Kotlin productivity, this probably is based on personal sentiment. I’m in a particular situation as I picked up the language rather early, right before 1.0 was released, and also worked as a teacher for the language ever since. Nevertheless, I’m convinced that some of the arguments in favor of Kotlin apply to many more of you, so let’s see what I’m talking about.

My JVM background

I used Java intensively for some years and wrote much productive code with the language. Java was my first language, and I did not know other languages too well at that point. Despite not having seen many other languages, I never really felt much joy when using Java, which changed when Java 8 arrived back in 2014. I immediately fell in love with the functional aspects that were added to the language and used lambdas and streams all over our code base. There might have been some situations in which I shouldn’t have done so, but it was bleeding Java edge, and I loved it. At that time, I started looking into other JVM languages and started to learn Scala at some point. I began by reading its documentation which was fun at first but then quickly started to become scary. I never really gave it a proper chance but looking back, I don’t regret putting it away after only a few weeks.

Kotlin

I don’t quite remember where I heard about Kotlin for the first time. The only thing I do remember is that JetBrains was mentioned along with it. I’ve always been a fan of their products, and so it was clear that I had to investigate the language they created. Other than Scala, Kotlin has a very digestible documentation, and it never got scary when I read it. I remember that I binge-read it in only a few days and there were like two topics I didn’t quite understand directly and bookmarked for later. One of those topics was backing fields, and the other one was probably related to delegation support.
Another thing that made it super easy to pick up Kotlin was the excellent support in IntelliJ. I learned the language with the IDE and the documentation. Another resource I totally recommend is the book Kotlin in Action which also helped me a lot with understanding the inner workings of the language better.

Standard Library

Kotlin has a fantastic standard library. If you think that Java also does, I can assure you that it is much weaker than Kotlin’s. You won’t need external libraries for everyday tasks like checking whether a

String

is blank or copying streams around. Kotlin provides all that and much more. It comes with an extremely sophisticated collections API, defines commonly needed extension functions on default types and finally gives the developer the option to add their own functions via extensions. You can find an excellent article on a bunch of standard functions here for example.

Feature-rich language

This one should be obvious. Especially when you’re coming from a language like Java, you will be blessed by the crisp features Kotlin provides. Think about null-safety, extension functions, easier generics or its catchy concurrency means provided by coroutines for instance – they all make us more productive and make the language more enjoyable.

Kotlin is intuitive

As a result of the fantastic standard library and the rich feature set, Kotlin is a very intuitive language. Frequently, you may try to perform some action on a given type and see what existing functions the IDE suggests. It then often happens that you find the function you were looking for already defined. Examples of this would be String::substringBefore, File::extension or Iterable::toSet.

Functional Style

When we talk about the standard library and also how intuitive the language is by itself, we also want to mention the functional aspects of the language. In this part, I particularly want to focus on functions. As you might already know, functions are first class citizens in Kotlin. You can declare variables holding them, pass them around and even return functions from other functions. You find lambdas (undeclared and directly passed functions) in every Kotlin code base. They are heavily used in the Kotlin standard library too. One example of this is the very helpful set of scope functions, which you can learn about here. Of course, lambdas are a vital ingredient to the collections API, i.e., stuff defined in

kotlin.collections

, as well. I can’t even tell how many times I use these functions in my day to day work. It somewhat gives me the creeps when I think about transforming collections within traditional

for

loops and how difficult it was to perform similar tasks in Java, especially before Java 8. Let’s see an example in action. Let’s assume we have some table/grid data modeled as follows:

Example


data class Grid(val rows: List<Row>)
data class Row(val data: List<Column<*>>)
data class Column<T>(val name: String, val value: T)

A

Grid

has multiple

Row

s which consists of multiple

Column

s. The task would be to calculate the totals for every given column identified by its

name

:


fun calculateTotals(data: Grid) = data.rows
    .flatMap(Row::data)
    .groupingBy(Column<*>::name)
    .fold(0.0) { accumulator, (_, value) ->
        accumulator + when (value) {
            is Number -> value.toDouble()
            else -> 0.0
        }
    }

Using functions from the Kotlin standard library, we can do the following:
1. collect all columns from all rows in a single collection using

flatMap

2. group these columns by their name using

groupingBy

3. accumulate the grouped columns by summing up their values

The above is just a single straightforward example that nicely demonstrates what you can do with the given collection functions. As I said earlier, I make use of these functions every day, I use it extensively, and I don’t want to miss it anymore.

You need to write less code

One of the most significant advantages of the functional programming style is the fact that you have to write less code overall. You make use of so-called internal iterations rather than specifying how to iterate a given collection explicitly. Loops sound easy at the beginning, and everybody should be able to apply them correctly. Still, they can easily cause hard-to-find bugs, which is a common problem of boilerplate code. The idea of functional APIs is that you can focus on the what instead of the how and thus don’t iterate collections explicitly but rather use functions like

map

,

filter

etc. which handle the iteration for you.

Less Boilerplate – Fewer errors in general

Boilerplate code can be the source of errors; naturally, the more code you need to write, the more potential bugs can be created. Since Kotlin removes the necessity for a lot of tedious boilerplate codes, the language makes you introduce fewer logic errors in general. An excellent example of this is the singleton pattern. Implementing it correctly is not as simple as you might think. You have to handle simultaneous access to singletons, which makes it hard to implement the initialization code of such an object. There are different approaches to this issue, all of which can cause potential issues if written manually. Kotlin, through its

object

construct, abstracts this for the developer and does not require you to write the recurring code every time.

Easier to debug and maintain

While in Java you have to spend much time reading and understanding boilerplate code, this is not that much of an issue in Kotlin for the same reasons already mentioned: a sophisticated set of features and a more concise language in general. Moving an existing Java code base to Kotlin reduces the code size by ~40% if done correctly. This, of course, makes Kotlin code much easier to read, debug and also maintain. To be fair, a rich feature set can easily be abused and may lead to hard-to-read code if used without care. So don’t write the code for you but the people who have to maintain it in the future.

It’s fun

All the reasons mentioned above make Kotlin a language that is fun. A pragmatic, concise and intuitive language is the best tool a programmer can think of, and you should not be using anything else. Having fun automatically leads to more productivity as well.

What you should do before calling yourself a Kotlin developer

I want to note that I consider it extremely helpful to know your toolset accurately. I took much time to learn Kotlin, primarily how it works and what features it provides, which everyone should do before writing serious Kotlin code. As a Java developer, you can quickly write compiling Kotlin code, but that’s still different from writing idiomatic Kotlin code. It won’t be sufficient to google for StackOverflow posts all the time. You should incorporate some fundamental techniques before getting started. I recommend studying the complete Kotlin documentation, which you can do in only a few days. On top of that, the book Kotlin in Action is the best resource you can find, and I highly recommend it.

Conclusion

Putting away Java in favor of Kotlin improved my programming skills and made me much more productive in general. I feel more joy, introduce fewer errors and feel less bugged than I did with Java. I don’t want to say that only Kotlin can do this for you too. However, maybe it’s time to get started with a more contemporary language to broaden your horizon and become more productive on the side.

The post How Kotlin makes me a more productive software developer appeared first on Kotlin Expertise Blog.

Continue Reading How Kotlin makes me a more productive software developer

How Kotlin makes me a more productive software developer

How Kotlin makes me a more productive software developer

I’ve been writing JVM code for more than seven years now, and I did so mainly using Java. This changed about two years ago when I picked up Kotlin. By now, I managed to drop the Java language more-or-less entirely in favor of Kotlin. I did this because I feel much more productive with the language. It lets me focus more on the business logic rather than forcing me to write boilerplate code over and over again. In this post, I tell you how Kotlin makes me a more productive developer.
I certainly know Kotlin much better than I ever knew Java. FWIW, I had been certified as a Java expert by Oracle some years back. Still, Kotlin became my native programming language, and I want to encourage you to consider it too. When I talk about my Kotlin productivity, this probably is based on personal sentiment. I’m in a particular situation as I picked up the language rather early, right before 1.0 was released, and also worked as a teacher for the language ever since. Nevertheless, I’m convinced that some of the arguments in favor of Kotlin apply to many more of you, so let’s see what I’m talking about.

My JVM background

I used Java intensively for some years and wrote much productive code with the language. Java was my first language, and I did not know other languages too well at that point. Despite not having seen many other languages, I never really felt much joy when using Java, which changed when Java 8 arrived back in 2014. I immediately fell in love with the functional aspects that were added to the language and used lambdas and streams all over our code base. There might have been some situations in which I shouldn’t have done so, but it was bleeding Java edge, and I loved it. At that time, I started looking into other JVM languages and started to learn Scala at some point. I began by reading its documentation which was fun at first but then quickly started to become scary. I never really gave it a proper chance but looking back, I don’t regret putting it away after only a few weeks.

Kotlin

I don’t quite remember where I heard about Kotlin for the first time. The only thing I do remember is that JetBrains was mentioned along with it. I’ve always been a fan of their products, and so it was clear that I had to investigate the language they created. Other than Scala, Kotlin has a very digestible documentation, and it never got scary when I read it. I remember that I binge-read it in only a few days and there were like two topics I didn’t quite understand directly and bookmarked for later. One of those topics was backing fields, and the other one was probably related to delegation support.
Another thing that made it super easy to pick up Kotlin was the excellent support in IntelliJ. I learned the language with the IDE and the documentation. Another resource I totally recommend is the book Kotlin in Action which also helped me a lot with understanding the inner workings of the language better.

Standard Library

Kotlin has a fantastic standard library. If you think that Java also does, I can assure you that it is much weaker than Kotlin’s. You won’t need external libraries for everyday tasks like checking whether a

String

is blank or copying streams around. Kotlin provides all that and much more. It comes with an extremely sophisticated collections API, defines commonly needed extension functions on default types and finally gives the developer the option to add their own functions via extensions. You can find an excellent article on a bunch of standard functions here for example.

Feature-rich language

This one should be obvious. Especially when you’re coming from a language like Java, you will be blessed by the crisp features Kotlin provides. Think about null-safety, extension functions, easier generics or its catchy concurrency means provided by coroutines for instance – they all make us more productive and make the language more enjoyable.

Kotlin is intuitive

As a result of the fantastic standard library and the rich feature set, Kotlin is a very intuitive language. Frequently, you may try to perform some action on a given type and see what existing functions the IDE suggests. It then often happens that you find the function you were looking for already defined. Examples of this would be String::substringBefore, File::extension or Iterable::toSet.

Functional Style

When we talk about the standard library and also how intuitive the language is by itself, we also want to mention the functional aspects of the language. In this part, I particularly want to focus on functions. As you might already know, functions are first class citizens in Kotlin. You can declare variables holding them, pass them around and even return functions from other functions. You find lambdas (undeclared and directly passed functions) in every Kotlin code base. They are heavily used in the Kotlin standard library too. One example of this is the very helpful set of scope functions, which you can learn about here. Of course, lambdas are a vital ingredient to the collections API, i.e., stuff defined in

kotlin.collections

, as well. I can’t even tell how many times I use these functions in my day to day work. It somewhat gives me the creeps when I think about transforming collections within traditional

for

loops and how difficult it was to perform similar tasks in Java, especially before Java 8. Let’s see an example in action. Let’s assume we have some table/grid data modeled as follows:

Example


data class Grid(val rows: List<Row>)
data class Row(val data: List<Column<*>>)
data class Column<T>(val name: String, val value: T)

A

Grid

has multiple

Row

s which consists of multiple

Column

s. The task would be to calculate the totals for every given column identified by its

name

:


fun calculateTotals(data: Grid) = data.rows
    .flatMap(Row::data)
    .groupingBy(Column<*>::name)
    .fold(0.0) { accumulator, (_, value) ->
        accumulator + when (value) {
            is Number -> value.toDouble()
            else -> 0.0
        }
    }

Using functions from the Kotlin standard library, we can do the following:
1. collect all columns from all rows in a single collection using

flatMap

2. group these columns by their name using

groupingBy

3. accumulate the grouped columns by summing up their values

The above is just a single straightforward example that nicely demonstrates what you can do with the given collection functions. As I said earlier, I make use of these functions every day, I use it extensively, and I don’t want to miss it anymore.

You need to write less code

One of the most significant advantages of the functional programming style is the fact that you have to write less code overall. You make use of so-called internal iterations rather than specifying how to iterate a given collection explicitly. Loops sound easy at the beginning, and everybody should be able to apply them correctly. Still, they can easily cause hard-to-find bugs, which is a common problem of boilerplate code. The idea of functional APIs is that you can focus on the what instead of the how and thus don’t iterate collections explicitly but rather use functions like

map

,

filter

etc. which handle the iteration for you.

Less Boilerplate – Fewer errors in general

Boilerplate code can be the source of errors; naturally, the more code you need to write, the more potential bugs can be created. Since Kotlin removes the necessity for a lot of tedious boilerplate codes, the language makes you introduce fewer logic errors in general. An excellent example of this is the singleton pattern. Implementing it correctly is not as simple as you might think. You have to handle simultaneous access to singletons, which makes it hard to implement the initialization code of such an object. There are different approaches to this issue, all of which can cause potential issues if written manually. Kotlin, through its

object

construct, abstracts this for the developer and does not require you to write the recurring code every time.

Easier to debug and maintain

While in Java you have to spend much time reading and understanding boilerplate code, this is not that much of an issue in Kotlin for the same reasons already mentioned: a sophisticated set of features and a more concise language in general. Moving an existing Java code base to Kotlin reduces the code size by ~40% if done correctly. This, of course, makes Kotlin code much easier to read, debug and also maintain. To be fair, a rich feature set can easily be abused and may lead to hard-to-read code if used without care. So don’t write the code for you but the people who have to maintain it in the future.

It’s fun

All the reasons mentioned above make Kotlin a language that is fun. A pragmatic, concise and intuitive language is the best tool a programmer can think of, and you should not be using anything else. Having fun automatically leads to more productivity as well.

What you should do before calling yourself a Kotlin developer

I want to note that I consider it extremely helpful to know your toolset accurately. I took much time to learn Kotlin, primarily how it works and what features it provides, which everyone should do before writing serious Kotlin code. As a Java developer, you can quickly write compiling Kotlin code, but that’s still different from writing idiomatic Kotlin code. It won’t be sufficient to google for StackOverflow posts all the time. You should incorporate some fundamental techniques before getting started. I recommend studying the complete Kotlin documentation, which you can do in only a few days. On top of that, the book Kotlin in Action is the best resource you can find, and I highly recommend it.

Conclusion

Putting away Java in favor of Kotlin improved my programming skills and made me much more productive in general. I feel more joy, introduce fewer errors and feel less bugged than I did with Java. I don’t want to say that only Kotlin can do this for you too. However, maybe it’s time to get started with a more contemporary language to broaden your horizon and become more productive on the side.

The post How Kotlin makes me a more productive software developer appeared first on Kotlin Expertise Blog.

Continue Reading How Kotlin makes me a more productive software developer

How Kotlin makes me a more productive software developer

How Kotlin makes me a more productive software developer

I’ve been writing JVM code for more than seven years now, and I did so mainly using Java. This changed about two years ago when I picked up Kotlin. By now, I managed to drop the Java language more-or-less entirely in favor of Kotlin. I did this because I feel much more productive with the language. It lets me focus more on the business logic rather than forcing me to write boilerplate code over and over again. In this post, I tell you how Kotlin makes me a more productive developer.
I certainly know Kotlin much better than I ever knew Java. FWIW, I had been certified as a Java expert by Oracle some years back. Still, Kotlin became my native programming language, and I want to encourage you to consider it too. When I talk about my Kotlin productivity, this probably is based on personal sentiment. I’m in a particular situation as I picked up the language rather early, right before 1.0 was released, and also worked as a teacher for the language ever since. Nevertheless, I’m convinced that some of the arguments in favor of Kotlin apply to many more of you, so let’s see what I’m talking about.

My JVM background

I used Java intensively for some years and wrote much productive code with the language. Java was my first language, and I did not know other languages too well at that point. Despite not having seen many other languages, I never really felt much joy when using Java, which changed when Java 8 arrived back in 2014. I immediately fell in love with the functional aspects that were added to the language and used lambdas and streams all over our code base. There might have been some situations in which I shouldn’t have done so, but it was bleeding Java edge, and I loved it. At that time, I started looking into other JVM languages and started to learn Scala at some point. I began by reading its documentation which was fun at first but then quickly started to become scary. I never really gave it a proper chance but looking back, I don’t regret putting it away after only a few weeks.

Kotlin

I don’t quite remember where I heard about Kotlin for the first time. The only thing I do remember is that JetBrains was mentioned along with it. I’ve always been a fan of their products, and so it was clear that I had to investigate the language they created. Other than Scala, Kotlin has a very digestible documentation, and it never got scary when I read it. I remember that I binge-read it in only a few days and there were like two topics I didn’t quite understand directly and bookmarked for later. One of those topics was backing fields, and the other one was probably related to delegation support.
Another thing that made it super easy to pick up Kotlin was the excellent support in IntelliJ. I learned the language with the IDE and the documentation. Another resource I totally recommend is the book Kotlin in Action which also helped me a lot with understanding the inner workings of the language better.

Standard Library

Kotlin has a fantastic standard library. If you think that Java also does, I can assure you that it is much weaker than Kotlin’s. You won’t need external libraries for everyday tasks like checking whether a

String

is blank or copying streams around. Kotlin provides all that and much more. It comes with an extremely sophisticated collections API, defines commonly needed extension functions on default types and finally gives the developer the option to add their own functions via extensions. You can find an excellent article on a bunch of standard functions here for example.

Feature-rich language

This one should be obvious. Especially when you’re coming from a language like Java, you will be blessed by the crisp features Kotlin provides. Think about null-safety, extension functions, easier generics or its catchy concurrency means provided by coroutines for instance – they all make us more productive and make the language more enjoyable.

Kotlin is intuitive

As a result of the fantastic standard library and the rich feature set, Kotlin is a very intuitive language. Frequently, you may try to perform some action on a given type and see what existing functions the IDE suggests. It then often happens that you find the function you were looking for already defined. Examples of this would be String::substringBefore, File::extension or Iterable::toSet.

Functional Style

When we talk about the standard library and also how intuitive the language is by itself, we also want to mention the functional aspects of the language. In this part, I particularly want to focus on functions. As you might already know, functions are first class citizens in Kotlin. You can declare variables holding them, pass them around and even return functions from other functions. You find lambdas (undeclared and directly passed functions) in every Kotlin code base. They are heavily used in the Kotlin standard library too. One example of this is the very helpful set of scope functions, which you can learn about here. Of course, lambdas are a vital ingredient to the collections API, i.e., stuff defined in

kotlin.collections

, as well. I can’t even tell how many times I use these functions in my day to day work. It somewhat gives me the creeps when I think about transforming collections within traditional

for

loops and how difficult it was to perform similar tasks in Java, especially before Java 8. Let’s see an example in action. Let’s assume we have some table/grid data modeled as follows:

Example


data class Grid(val rows: List<Row>)
data class Row(val data: List<Column<*>>)
data class Column<T>(val name: String, val value: T)

A

Grid

has multiple

Row

s which consists of multiple

Column

s. The task would be to calculate the totals for every given column identified by its

name

:


fun calculateTotals(data: Grid) = data.rows
    .flatMap(Row::data)
    .groupingBy(Column<*>::name)
    .fold(0.0) { accumulator, (_, value) ->
        accumulator + when (value) {
            is Number -> value.toDouble()
            else -> 0.0
        }
    }

Using functions from the Kotlin standard library, we can do the following:
1. collect all columns from all rows in a single collection using

flatMap

2. group these columns by their name using

groupingBy

3. accumulate the grouped columns by summing up their values

The above is just a single straightforward example that nicely demonstrates what you can do with the given collection functions. As I said earlier, I make use of these functions every day, I use it extensively, and I don’t want to miss it anymore.

You need to write less code

One of the most significant advantages of the functional programming style is the fact that you have to write less code overall. You make use of so-called internal iterations rather than specifying how to iterate a given collection explicitly. Loops sound easy at the beginning, and everybody should be able to apply them correctly. Still, they can easily cause hard-to-find bugs, which is a common problem of boilerplate code. The idea of functional APIs is that you can focus on the what instead of the how and thus don’t iterate collections explicitly but rather use functions like

map

,

filter

etc. which handle the iteration for you.

Less Boilerplate – Fewer errors in general

Boilerplate code can be the source of errors; naturally, the more code you need to write, the more potential bugs can be created. Since Kotlin removes the necessity for a lot of tedious boilerplate codes, the language makes you introduce fewer logic errors in general. An excellent example of this is the singleton pattern. Implementing it correctly is not as simple as you might think. You have to handle simultaneous access to singletons, which makes it hard to implement the initialization code of such an object. There are different approaches to this issue, all of which can cause potential issues if written manually. Kotlin, through its

object

construct, abstracts this for the developer and does not require you to write the recurring code every time.

Easier to debug and maintain

While in Java you have to spend much time reading and understanding boilerplate code, this is not that much of an issue in Kotlin for the same reasons already mentioned: a sophisticated set of features and a more concise language in general. Moving an existing Java code base to Kotlin reduces the code size by ~40% if done correctly. This, of course, makes Kotlin code much easier to read, debug and also maintain. To be fair, a rich feature set can easily be abused and may lead to hard-to-read code if used without care. So don’t write the code for you but the people who have to maintain it in the future.

It’s fun

All the reasons mentioned above make Kotlin a language that is fun. A pragmatic, concise and intuitive language is the best tool a programmer can think of, and you should not be using anything else. Having fun automatically leads to more productivity as well.

What you should do before calling yourself a Kotlin developer

I want to note that I consider it extremely helpful to know your toolset accurately. I took much time to learn Kotlin, primarily how it works and what features it provides, which everyone should do before writing serious Kotlin code. As a Java developer, you can quickly write compiling Kotlin code, but that’s still different from writing idiomatic Kotlin code. It won’t be sufficient to google for StackOverflow posts all the time. You should incorporate some fundamental techniques before getting started. I recommend studying the complete Kotlin documentation, which you can do in only a few days. On top of that, the book Kotlin in Action is the best resource you can find, and I highly recommend it.

Conclusion

Putting away Java in favor of Kotlin improved my programming skills and made me much more productive in general. I feel more joy, introduce fewer errors and feel less bugged than I did with Java. I don’t want to say that only Kotlin can do this for you too. However, maybe it’s time to get started with a more contemporary language to broaden your horizon and become more productive on the side.

The post How Kotlin makes me a more productive software developer appeared first on Kotlin Expertise Blog.

Continue Reading How Kotlin makes me a more productive software developer

End of content

No more pages to load