Is it gonna be your first API with Kotlin and Quarkus? Let’s see! — Part 1

Petros Kontogiannis
Dev Genius
Published in
5 min readFeb 19, 2022

--

If you‘ve ever read my articles you are already aware of my writing style. I love writing with oral style, so this is what I am gonna do again my little friend.

Let me start!

Was years ago when I started my career as a Software Engineer, back in Greece. I‘ve told you already in one of my previous articles how much I was struggling to find resources, to find what I was looking for. I am sure that with the experience I had at that time, I wasn’t really able to properly search in the crazy internet world, so I was so demotivated so many times. Year by year I became much better at searching, learning and of course along with these, I became a better Engineer. Anyway! I‘ve read so many articles but I was always hesitating to write a technical one. I was thinking of how better my article can be, what I can say differently to a person, out there, in order to help her/him. I would prefer instead writing some articles about my experience. Until recently though, when I decided to just try it out.
Push me a bit outside of my comfort zone and share some years of experience I have in software development.

Please fasten your seat belt and join me in a nice story, of making our first Rest API with Kotlin and Quarkus. In this article, I‘ll try to reply to all of the possible questions you may have as it’s a nice learning opportunity for me as well!

So in the context of this article series, I would like to introduce two people!
Our lovely youth, a young guy who recently started his career in Software development and a beautiful lady with some years of experience in the industry. Call them as you wish.

The story is about to start…

Lady: So, you already have some experience in building APIs!
Youth: Yes, yes! I‘ve built some code cases in Python but I have limited experience! I would definitely want to try something new!

L: Nice! Why don’t you try to build something in Kotlin? I might be able to help you. It’s a nice language!
Y: Hmm, Kotlin? Sounds interesting! May you have a case study for me?
L: Here you are!

Let’s take a simple example of a logistics company which needs a small API to keeping its stock of articles per store.
You can implement a CRUD API for saving, getting, changing and deleting the stock per article.
On top of that you can have a reservation functionality where a co-worker can reserve X amount of articles for a specific duration of time.
You can use any framework you want!

Y: Awesome! Let me see from where I can start!

Let’s enter the youth’s brain and see what he is thinking of!

Hmm, what is our domain? We have a store, we have articles, what else? We have reservations. We may have multiple stores and we may have also users. But let’s start simple!

Stores first. A store can have a name and an id.
More or less the same thing for the article, plus a quantity per store.
And somehow we need to keep track of the reservations.

Ok, perfect. We have our small domain model. Let’s see how we can store this data in a relational database.

Seems simple.

Entity diagram
Database tables

L: Perfect! That seems like a neat approach! Let’s dive into the code then! You can use Spring boot which is a well-established framework or any other framework you want.
Y: What about Quarkus? I’ve heard that has some nice features I want to learn!
L: Go for it then!

Our first Quarkus application!

quarkus create app org.acme:medium-store \
--extension=kotlin,resteasy-reactive-jackson,quarkus-jdbc-postgresql,quarkus-smallrye-health,quarkus-smallrye-metrics,quarkus-smallrye-jwt
Initial Project Structure

As we have a database, let’s find a nice way to communicate with it.

Y: Do you know any nice ORM I can use?
L: In Java, there are some obvious contenders, like Hibernate, iBatis, EBean, but you can take a look at some which are built for Kotlin. Exposed and Ktorm seems to be a nice choice for you.
Y: Thank you, teacher! I‘ll take a look!

Both ORMs are pretty similar so I decided to use Ktorm!
I first defined my two main objects, Article, and Store

interface Article : Entity<Article> {
companion object : Entity.Factory<Article>()

val id: Int
var uuid: UUID
var name: String
}

object Articles : Table<Article>(schema = "stock_keeping", tableName = "article") {
val id = int("id").primaryKey().bindTo { it.id }
val uuid = uuid("article_uuid").bindTo { it.uuid }
val name = varchar("name").bindTo { it.name }
}

val Database.articles get() = this.sequenceOf(Articles)
interface Store : Entity<Store> {
companion object : Entity.Factory<Store>()

val id: Int
var uuid: UUID
var name: String
}

object Stores : Table<Store>(schema = "stock_keeping", tableName = "store") {
val id = int("id").primaryKey().bindTo { it.id }
val uuid = uuid("store_uuid").bindTo { it.uuid }
val name = varchar("name").bindTo { it.name }
}

val Database.stores get() = this.sequenceOf(Stores)

And then the connection between them as long as the reservation table where we can keep the reserved articles.

interface StoreArticle : Entity<StoreArticle> {
companion object : Entity.Factory<StoreArticle>()

val articleId: Int
val storeId: Int
val availableStock: Int
}

object StoreArticles : Table<StoreArticle>(schema = "stock_keeping", tableName = "store_article") {
val articleId: Column<Int> = int("article_id").primaryKey().bindTo { it.articleId }
val storeId: Column<Int> = int("store_id").primaryKey().bindTo { it.storeId }
val availableStock = int("available_stock").bindTo { it.availableStock }
}

interface Reservation : Entity<Reservation> {
companion object : Entity.Factory<Reservation>()

val articleId: Int
val storeId: Int
val reservedStock: Int
val reservationTime: Instant
}

object Reservations : Table<Reservation>(schema = "stock_keeping", tableName = "reserved_article") {
val articleId: Column<Int> = int("article_id").primaryKey().bindTo { it.articleId }
val storeId: Column<Int> = int("store_id").primaryKey().bindTo { it.storeId }
val quantity = int("reserved_stock").bindTo { it.reservedStock }
val reservationTime = timestamp("reservation_time").bindTo { it.reservationTime }
}

Awesome!
Y: I think I want a short break! Can we continue a bit later?
L: Sure newbie, see you soon!

Twitter & Instagram & LinkedIn

--

--

If you ‘ve ever played the game “Keep talking and nobody explodes” then, yes, I am the guy who disables the bomb by collaborating and orchestrating my teams.