paint-brush
TODO Application using Finch and TwitterServer.by@anicolaspp
953 reads
953 reads

TODO Application using Finch and TwitterServer.

by Nicolas A PerezOctober 19th, 2017
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Last week <em>ScalaTimes</em> presented <a href="https://scalatimes.us2.list-manage.com/track/click?u=ba834c562d82d9aba5eaf90ba&amp;id=11f7ed2c12&amp;e=c3a14fe549" target="_blank"><em>Creating a TODO application using Akka HTTP and Slick</em></a><strong>, </strong>which encouraged myself to do the same type of starting tutorial in Finch.

Company Mentioned

Mention Thumbnail
featured image - TODO Application using Finch and TwitterServer.
Nicolas A Perez HackerNoon profile picture

Last week ScalaTimes presented Creating a TODO application using Akka HTTP and Slick, which encouraged myself to do the same type of starting tutorial in Finch.

Finch is a project written by people working mostly on Twitter and it is a TypeLevel incubator. What I like the most about Finch is its simplicity by using pure functional programming constructs and highly efficient libraries underneath.

Personally, I have used Finch in various small projects and once in a very serious project / environment. I always found it very easy and simplistic even though it is a very capable library.

Finch is fast, just look at How Fast is Finch? You will discover that it is the second faster HTTP library written in Scala.

Let’s focus now how to create a simple Rest API using Finch.

Our build.sbt file looks like follow:

We are only adding the the Finch libraries and Circe for JSON serialization/deserialization.

Now, we need to create our first endpoint to be served.

Let’s start by something very simplistic and then grow from there. First, we can define a hello endpoint.

In here, Endpoint is, in my opinion, the most important construct we are going to find in Finch.

The idea behind Endpoint is that it represent a serie of transformations as follows:

We get a Request and transform it into some type A. Then we apply some business logic to the input in an asynchronous matter just to finalize with another transformation into the desired Response.

In our example, our Endpoint is a get which URL is hello and the business logic to be applied is just returning hello to you!.

Now, we need to run the server and expose the hello to be used.

We have only created an application that we can be executed, and we have create a server to connect to localhost:8080 then it serves the hello Endpoint as a Finagle Service.

We can run the application by doing sbt run or java -jar <the application.jar>. Once running we can send a request to the endpoint using our terminal: http localhost:8080/hello and we will get back:

Our Storage Service

For this example, we are going to use a storage abstraction that can be implemented in multiple ways, in particular we can create one that talks to an in-memory datastore.

Item is the type of objects we are going to be sending and receiving to our API and Storage is the one in charge of saving / retrieving them.

Our in-memory implementation is as simple as this.

Defining TODO Endpoints

1. GET- TODOS

Our first endpoint will be todos that retrieves all items available in the storage.

We can see how simple that is! It just does a storage.getAll call. This endpoint will respond to GET /todos URL in our server.

2. POST -TODO

Now we can define a new endpoint to add todos that will respond at POST /todo

This one is a little more interesting to look at. Because it is a POST we need to extract the Item from the body of the message. However, there is a gotcha, the Item cannot be created without an UUID and that is what the postTodo function does. In other words, we extract the taskName from the POST message body and create an Item object with it and a random UUID.

The idea is that you don’t need to have a different Item model without the id to be sent on the requests.

Then function storage.add(item) does not really care about the id, it just add a new Item to the storage and returns the recently created one (it has its own new id).

Once the Item has been added, we return the recently created one.

We can test it from our terminal by doing

which returns

3. GET -TODO

Retrieving a particular Item is an easy task. We only need the id and then we can ask for the storage to get it for us.

We can test it by doing:

Which returns the same todo we inserted before.

Notice that if the item is not in the storage, .fold will return NotFound HTTP message back to the client.

4. DELETE-TODO

In the same way we can do deleteTodo

We look for the Item with the given id. If it exists then we delete it. Then we return accordingly using .fold.

TodoService

The entire TodoService code looks like this.

Putting Everything Together

We need to expose all these Endpoints from our application. Finch uses Shapeless to compose Endpoints and taking a closer look to the TodoService we can see that this composition is happening in the TodoService.api.

Let’s look how our application can be rewritten to serve the TodoService.

Notice that .api is the combination of every single Endpoint.

This composition is done using Shapeless and it is basically saying that the incoming request must match one of the endpoints.

Conclusions

Finch is an HTTP library that presents an easy way to define endpoints and to compose them into a more complex API. Finch allows us to write purely functional code for the web that is able to server request at hight rates.