Creating a Reactive CRUD todo app with Kotlin, MongoDB, Panache and Quarkus

David
Geek Culture

--

Kotlin is a very popular programming language that targets the JVM (amongst other environments). Kotlin has experienced a surge in popularity the last few years making it the most popular JVM language, except for Java of course. Having Kotlin in a Quarkus based project can give us more benefits whilst still having the possibility of using other extensions from the Quarkus ecosystem.

kotlinlang.org

Quarkus provides excellent support for using Kotlin together with a MongoDB Panache Kotlin extension which gives users some of the familiarity when working seamlessly with reactive Panache entities in a reactive manner. This guide provides a brief hands on experience working with this extension.

code.quarkus.io

Prerequisites

  • Docker
  • Java 8+
  • Maven ≥ 3.6.2
  • Kotlin ≥ 1.5.21

Quarkus extensions

$ ./mvnw quarkus:add-extension -Dextensions="quarkus-mongodb-panache-kotlin,quarkus-resteasy-reactive-jackson,quarkus-resteasy-reactive"

Minimal configuration with Dev Services

Dev Services start the required containers automatically when you are developing or testing your application. In our case it will spin MongoDB database out of the box. Only configuration needed in the application.properties file.

quarkus.mongodb.database = todos

That’s it! When running the Dev services will spin up the specific database with Testcontainers according to what extension has been provided.

Panache and Kotlin

In the MongoDB Panache guides there a brief mentioning of two design pattern approaches, the active record pattern and repository pattern. Using Kotlin, we can choose one of the two with some variation. In the Kotlin version, the active record pattern is provided using a companion object.

The companion object holds all the methods not related to a specific instance allowing for general management and querying bound to a specific type. There are options, but for now it’s the lateinit approach. This allows us to declare these fields as non-null knowing they will be properly assigned either by the constructor (not shown) or by the MongoDB POJO codec loading data from the database.

Kotlin and Jackson

In this guide we will be using the rest-easy-jackson extension. If the com.fasterxml.jackson.module:jackson-module-kotlin dependency and the quarkus-jackson extension (or the quarkus-resteasy-jackson extension) have been added to the project, then Quarkus automatically registers the KotlinModule to the ObjectMapper bean (see this guide for more details).

Reactive Entities and Repositories

MongoDB with Panache allows using reactive style implementation for both entities and repositories. For this, you need to use the Reactive variants when defining your entities : ReactivePanacheMongoEntity or ReactivePanacheMongoEntityBase, and when defining your repositories: ReactivePanacheMongoRepository or ReactivePanacheMongoRepositoryBase.

The reactive API of the MongoDB with Panache uses Mutiny reactive types. If you are not familiar with Mutiny, check Mutiny — an intuitive reactive programming library.

Problem Domain

In this scenario we will be using the active record pattern containing our entity methods. It will be a typical todo list application having todo lists containing todo items. Nothing really fancy and more just to give an idea on where to start and how to model the different entities and their operations.

TodoList Reactive Panache MongoDB Entity

Here is our TodoList entity with its companion objects containing the different reactive methods provided by smallrye-mutiny. Mixing the two worlds of conscise Kotlin code and elegant stream processing using smallrye mutiny provides several benefits.

Todo Entity

Todo List API Resouce

All our defined supported API calls available.

Running the application

From here on, its just a matter of running the quarkus application with live coding preview.

$ ./mvnw compile quarkus:dev

API Calls

Below are the following API calls we can make to our reactive API endpoints.

Create a Todo List

$ curl -X POST "localhost:8080/v1/todos"{"name":"Travel"}

Get all Todo Lists

$ curl "localhost:8080/v1/todos"

Add a Todo to a Todo List

$ curl -X PUT "localhost:8080/v1/todos/61054ea7c547c3533bc06a25"

{
{"title":"Hotelbooking","description":"Somewhere to stay"}
}

Complete a Todo item by Todo List id and Todo Id

$ curl -X PUT "localhost:8080/v1/todos/610547059137493daac0367a/3b955596-442d-481a-947b-396d06bdd7b4/complete"

Delete Todo List by id

$ curl -X DELETE "localhost:8080/v1/todos/60db4b085d2d613300cc136b"

Example Response

Get all Todo Lists

[
{
"id":"61054ea1c547c3533bc06a24",
"name":"Groceries",
"todos":[
{
"title":"Avocado",
"description":"Something Interesting",
"created":"2021-07-31",
"id":"3acf9399-55cc-4418-af07-4b194ef37b8b",
"completed":true
},
{
"title":"Bananas",
"description":"Something nice",
"created":"2021-07-31",
"id":"ea1ebf70-62df-47a6-b5e4-f4a4c73c9eb1",
"completed":false
}
]
},
{
"id":"61054ea7c547c3533bc06a25",
"name":"Travel",
"todos":[
{
"title":"Hotelbooking",
"description":"Somewhere to stay",
"created":"2021-07-31",
"id":"3be2f3cc-32ea-4553-b099-45f6a3a440e0",
"completed":false
}
]
}
]

Kotlin coroutines and Mutiny

Kotlin coroutines provide a imperative programming model that actually gets executed in an asynchronous, reactive manner. If you want to delve more into Quarkus and Kotlin, specifically the coroutines. There is a module io.smallrye.reactive:mutiny-kotlin, described here.

If you want to see the full source code for this project, you can find it on GitHub.

Find the GitHub source project here

Additional useful resources can be found in the links below.

Good luck!

--

--