Kotlin API — Spring Boot + PostgreSQL
By: Matheus Garcia
Tags: Postgres, Gradle, Spring Boot, Kotlin, Rest Api

Purpose of this article

To develop REST API using Kotlin with Spring Boot 2.3.1 and PostgreSQL.

Prerequisites

For this project, we are going to use IntelliJ CE, JVM 11 and docker.

Create the project

First of all, you need to install the spring initializr plugin on IntelliJ.

Creation of the project using spring initializr

Attention to project type and Language

Use HATEOAS and PostgreSQL dependencies

Import Gradle to IntelliJ

To import, you need to right-click the build.gradle.kts and then “Import Gradle project”.

Gradle file with dependencies

This Gradle file includes the exposed dependency and GSON, used to manipulate database data and to manipulate JSON, respectively.

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins {

id("org.springframework.boot") version "2.3.1.RELEASE"

id("io.spring.dependency-management") version "1.0.9.RELEASE"

kotlin("jvm") version "1.3.72"

kotlin("plugin.spring") version "1.3.72"

} group = "com.example"

version = "0.0.1-SNAPSHOT"

java.sourceCompatibility = JavaVersion.VERSION_11 repositories {

jcenter()

mavenCentral()

} dependencies { implementation("com.google.code.gson:gson:2.8.6")

implementation("org.springframework.boot:spring-boot-starter-hateoas")

implementation("org.jetbrains.kotlin:kotlin-reflect")

implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")

runtimeOnly("org.postgresql:postgresql") implementation("org.jetbrains.exposed:exposed-core:0.24.1")

implementation("org.jetbrains.exposed:exposed-dao:0.24.1")

implementation("org.jetbrains.exposed:exposed-jdbc:0.24.1") testImplementation("org.springframework.boot:spring-boot-starter-test") {

exclude(group = "org.junit.vintage", module = "junit-vintage-engine")

}

} tasks.withType<Test> {

useJUnitPlatform()

} tasks.withType<KotlinCompile> {

kotlinOptions {

freeCompilerArgs = listOf("-Xjsr305=strict")

jvmTarget = "11"

}

} springBoot {

mainClassName = "com.example.demo.DemoApplicationKt"

}

Create the controller

package com.example.demo.controller import org.springframework.hateoas.MediaTypes

import org.springframework.http.HttpStatus

import org.springframework.http.MediaType

import org.springframework.http.ResponseEntity

import org.springframework.web.bind.annotation.* @CrossOrigin(maxAge = 3600)

@RestController

class AppsController(

) {

@GetMapping("/", produces = [MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE])

@ResponseBody

fun helloWorld(): ResponseEntity<Any?> { return ResponseEntity("Hello World", HttpStatus.OK)

}

}

Run the application

After importing the grade, on the left side of your IntelliJ, in the Gradle tab, your project will be loaded and can be run using this task:

In your postman, you can do a request to your endpoint:

Let’s set up our PostgreSQL

Create a docker-compose.yml for your project:

# -------------------------- DEPENDENCIES ------------------ postgres: &POSTGRES

image: postgres:10.4 # ------------------------- DEV ---------------------------- postgres-dev:

<<: *POSTGRES

ports:

- 5432:5432

volumes:

- ./db/dev/databases.sql:/docker-entrypoint-initdb.d/1-dev-database.sql

- ./db/dev/roles.sql:/docker-entrypoint-initdb.d/2-dev-roles.sql

We are using two volumes: one for the database itself and another one for the roles.

databases.sql

CREATE DATABASE demo_db;

roles.sql

CREATE ROLE demo_dev_rw WITH LOGIN PASSWORD 'dev_database_passwd'; GRANT ALL PRIVILEGES ON DATABASE demo_db TO demo_dev_rw;

Run PostgreSQL:

docker-compose up postgres-dev

Create your table dto file

package com.example.demo.database import org.jetbrains.exposed.sql.Table object Demo : Table() {

val id = integer("id").autoIncrement()

val name = varchar("name", 50)

}

In my case, I put this in a package called database.

Connect your application with PostgreSQL

package com.example.demo import org.springframework.boot.autoconfigure.SpringBootApplication

import com.example.demo.database.*

import org.jetbrains.exposed.sql.Database

import org.jetbrains.exposed.sql.transactions.transaction

import org.springframework.boot.runApplication

import org.jetbrains.exposed.sql.* @SpringBootApplication

class DemoApplication fun main(args: Array<String>) { val dbUrl = "jdbc:postgresql://localhost:5432/demo_db"

val dbUser = "demo_dev_rw"

val dbPass = "dev_database_passwd" Database.connect(dbUrl, driver = "org.postgresql.Driver", user = dbUser, password = dbPass) transaction {

addLogger(StdOutSqlLogger) SchemaUtils.drop (Demo)

SchemaUtils.create (Demo) } runApplication<DemoApplication>(*args)

}

We are connecting to the database, dropping (to clean on each run) and creating the table.

Add mock data

Still, in your application file, let’s create some mock data.

package com.example.demo import org.springframework.boot.autoconfigure.SpringBootApplication

import com.example.demo.database.*

import org.jetbrains.exposed.sql.Database

import org.jetbrains.exposed.sql.transactions.transaction

import org.springframework.boot.runApplication

import org.jetbrains.exposed.sql.* @SpringBootApplication

class DemoApplication fun main(args: Array<String>) { val dbUrl = "jdbc:postgresql://localhost:5432/demo_db"

val dbUser = "demo_dev_rw"

val dbPass = "dev_database_passwd" Database.connect(dbUrl, driver = "org.postgresql.Driver", user = dbUser, password = dbPass) transaction {

addLogger(StdOutSqlLogger) SchemaUtils.drop (Demo)

SchemaUtils.create (Demo) Demo.insert {

it[name] = "Teste 1"

} Demo.insert {

it[name] = "Teste 2"

}

} runApplication<DemoApplication>(*args)

}

Create a list method on dto

package com.example.demo.database import org.jetbrains.exposed.sql.Table

import org.jetbrains.exposed.sql.selectAll

import org.jetbrains.exposed.sql.transactions.transaction object Demo : Table() {

val id = integer("id").autoIncrement()

val name = varchar("name", 50) fun getAll(): List<Any> = transaction {

Demo.selectAll().map { it[name] }

} }

List data on endpoint

fun helloWorld(): ResponseEntity<Any?> { val list = Demo.getAll()

return ResponseEntity(Gson().toJson(list), HttpStatus.OK)

}

That’s it!

You’ve made the basis of an API using Kotlin with Gradle, spring-boot and PostgreSQL.

Next steps

You can try to create the /:id endpoint and try to get the data using the id of the table.

Good Luck and Have Fun!