This commit is contained in:
pavel 2026-02-05 01:12:17 +01:00
commit 3f9345b064
19 changed files with 710 additions and 0 deletions

View file

@ -0,0 +1,14 @@
package cz.flegr
import io.ktor.server.application.*
fun main(args: Array<String>) {
io.ktor.server.netty.EngineMain.main(args)
}
fun Application.module() {
configureSerialization()
configureDatabases()
configureMonitoring()
configureRouting()
}

View file

@ -0,0 +1,55 @@
package cz.flegr
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import org.flywaydb.core.Flyway
import org.jetbrains.exposed.sql.Database
fun Application.configureDatabases() {
val dbConnection = connectToPostgres()
val taskService = TaskService()
routing {
// Create city
post("/tasks") {
val task = call.receive<Task>()
val id = taskService.create(task)
call.respond(HttpStatusCode.Created, id)
}
// Read city
get("/cities/{id}") {
val id = call.parameters["id"]?.toInt() ?: throw IllegalArgumentException("Invalid ID")
try {
val task = taskService.find(id)
call.respond(HttpStatusCode.OK, task)
} catch (e: Exception) {
call.respond(HttpStatusCode.NotFound)
}
}
// Delete city
delete("/cities/{id}") {
val id = call.parameters["id"]?.toInt() ?: throw IllegalArgumentException("Invalid ID")
taskService.delete(id)
call.respond(HttpStatusCode.OK)
}
}
}
fun Application.connectToPostgres(): Database {
val url = environment.config.property("postgres.url").getString()
log.info("Connecting to postgres database at $url")
val user = environment.config.property("postgres.user").getString()
val password = environment.config.property("postgres.password").getString()
Flyway.configure().dataSource(url, user, password).load().migrate()
return Database.connect(url, "org.postgresql.Driver", user, password)
}

View file

@ -0,0 +1,21 @@
package cz.flegr
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.plugins.calllogging.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import java.sql.Connection
import java.sql.DriverManager
import org.jetbrains.exposed.sql.*
import org.slf4j.event.*
fun Application.configureMonitoring() {
install(CallLogging) {
level = Level.INFO
filter { call -> call.request.path().startsWith("/") }
}
}

View file

@ -0,0 +1,22 @@
package cz.flegr
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.plugins.calllogging.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import java.sql.Connection
import java.sql.DriverManager
import org.jetbrains.exposed.sql.*
import org.slf4j.event.*
fun Application.configureRouting() {
routing {
get("/") {
call.respondText("Hello World!")
}
}
}

View file

@ -0,0 +1,22 @@
package cz.flegr
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.plugins.calllogging.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import java.sql.Connection
import java.sql.DriverManager
import org.jetbrains.exposed.sql.*
import org.slf4j.event.*
fun Application.configureSerialization() {
routing {
get("/json/kotlinx-serialization") {
call.respond(mapOf("hello" to "world"))
}
}
}

View file

@ -0,0 +1,44 @@
package cz.flegr
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.insert
import java.sql.Connection
import java.sql.Statement
@Serializable
data class Task(val id: Int = 0, val name: String, val completed: Boolean) {
}
object Tasks : Table("tasks") {
val id = integer("id").autoIncrement()
val name = varchar("name", 100)
val completed = bool("completed").default(false)
}
class TaskService {
fun create(task: Task): Int {
return Tasks.insert {
it[name] = task.name
it[completed] = task.completed
} get Tasks.id
}
fun find(id: Int): Task {
return Tasks.select(Tasks.id, Tasks.name, Tasks.completed)
.where {
Tasks.id eq id
}.map {
Task(it[Tasks.id], it[Tasks.name], it[Tasks.completed])
}.single()
}
fun delete(id: Int) {
Tasks.deleteWhere { Tasks.id eq id }
}
}

View file

@ -0,0 +1,10 @@
ktor:
application:
modules:
- cz.flegr.ApplicationKt.module
deployment:
port: 8080
postgres:
url: "jdbc:postgresql://localhost:5432/todo"
user: postgres
password: postgres

View file

@ -0,0 +1,12 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
<logger name="org.eclipse.jetty" level="INFO"/>
<logger name="io.netty" level="INFO"/>
</configuration>