Kotlin API — Spring Boot + PostgreSQL
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.
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.KotlinCompileplugins {
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_11repositories {
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.controllerimport 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.databaseimport org.jetbrains.exposed.sql.Tableobject 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.demoimport 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 DemoApplicationfun 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.demoimport 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 DemoApplicationfun 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.databaseimport org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transactionobject 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!