A common task for developers new to the Scala ecosystem is to set up a REST service which interacts with an underlying
Lately, there have been a lot of libraries available that allows us to build the REST APIs, like the following:
- Akka HTTP
In today’s blog, we go through the basic steps required to get started with using Http4s, to build a REST service interacting with a
database system, using Hikari Connection Pool.
What is Http4s?
Http4s is a minimal HTTP library for Scala, for building REST services. You can think of Http4s to be Scala’s answer to Java’s Servlets.
Http4s uses Cats IO, to ensure referential transparency by encapsulating side-effects and making the code more functional. (read more on this here)
So, without wasting much time, let’s get started !!
Our service will perform simple CREATE and READ operations. To keep things simple we will use a simple entity Car:
We’ll be using HikariCP, for setting up a JDBC connection pool.
Add the following dependencies into the build.sbt of our project:
To easily set up the connection pool we’ll use an object HikariConnectionPool, to manage database connections for our server:
The object will read the Database details/credentials from System ENV variables and instantiate the connection pool.
Next, let’s set up the DAO (Data Access Object) to provide convenience methods to CREATE and READ entries from the Database.
Notice here that we have encapsulated the data-access code inside an IO. Wonder why?
Since a call to the Database is actually a side-effect, to make sure our code remains purely functional (referentially transparent), we wrap it
inside an IO.
To set up the HTTP layer add the following dependencies in your build.sbt:
Now we configure the REST endpoints and host it on a local Blaze Server:
Since Http4s uses JSON format for the request/response body, we provide implicit encoder and decoder for the object Car using circe-generic.
Circe is a JSON library for Scala powered by Cats. (more on this here)
Observe that the IO returned by the readById and create methods: IO[Option[Car]], is never forced to be evaluated using
`unsafeRunSync()` but is transformed using `flatmap` into IO[Response[_]].
Setup the DB schema and the ENV variables and let’s start the server.
I’ve used the POSTMAN client to test the server.
Let’s do a POST request to create an entry for a “Tesla Model S”.
Voila! We successfully created a DB entry using our service with the status code `201 Created`.
Now let’s do a GET request to get the Car with id = 1.
The GET request successfully queried the DB and returns the corresponding Car object, with status code `200 OK`.
So there it is, enough to get you started and build your own REST services, which is purely functional and amazing!