Skip to content

Commit 8bc370c

Browse files
committed
KTOR-3419 DB Connection created on the top and passed in routing as argument; postgres keys moved to separate file for using both in application and docker-compose; added specific exception for database call
1 parent 3f6a1af commit 8bc370c

File tree

10 files changed

+48
-58
lines changed

10 files changed

+48
-58
lines changed

postgres/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ An application for creating, editing and deleting articles that uses Postgres da
66

77
1. Execute gradle task `databaseInstance` and wait until Docker Compose builds image and starts container
88

9-
2. Run the sample to create database table
9+
2. Execute this command to run the sample:
10+
11+
```bash
12+
./gradlew run
13+
```
1014

1115
Then, you can open [http://localhost:8080/](http://localhost:8080/) in a browser to create, edit, and delete articles.

postgres/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ dependencies {
3434

3535
tasks.register("databaseInstance") {
3636
doLast {
37-
val command = arrayOf("docker-compose","up")
37+
val command = arrayOf("docker-compose", "up")
3838
Runtime.getRuntime().exec(command)
3939
}
4040
}

postgres/docker-compose.yaml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
version: '3'
22
services:
3-
postgres:
3+
db:
44
image: postgres:13.2-alpine
5-
environment:
6-
POSTGRES_USER: "user"
7-
POSTGRES_PASSWORD: "password"
8-
POSTGRES_DB: "articles"
95
ports:
10-
- 5432:5432
6+
- 5432:5432
7+
extends:
8+
file: postgres.yaml
9+
service: postgres

postgres/postgres.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
version: '3'
2+
services:
3+
postgres:
4+
environment:
5+
POSTGRES_USER: "user"
6+
POSTGRES_PASSWORD: "password"
7+
POSTGRES_DB: "articles"

postgres/settings.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
rootProject.name = "postgres"
1+
rootProject.name = "ktor-postgres"

postgres/src/main/kotlin/com/example/Application.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ fun main(args: Array<String>): Unit =
99
@Suppress("unused") // application.conf references the main function. This annotation prevents the IDE from marking it as unused.
1010
fun Application.module() {
1111
configureSerialization()
12-
configureRouting()
12+
configureRouting(dbConnection = connectToPostgres(embedded = false))
1313
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package com.example.exceptions
2+
3+
class DbElementNotFoundException(message: String? = null, throwable: Throwable? = null) : Throwable(message, throwable)
Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
package com.example.plugins
22

3+
import com.example.exceptions.DbElementNotFoundException
34
import com.example.models.Article
45
import com.example.service.ArticleService
56
import io.ktor.http.*
67
import io.ktor.server.application.*
8+
import io.ktor.server.config.yaml.*
79
import io.ktor.server.request.*
810
import io.ktor.server.response.*
911
import io.ktor.server.routing.*
10-
import kotlinx.coroutines.*
1112
import java.sql.*
1213

13-
fun Application.configureRouting() {
14-
val dbConnection: Connection = connectToPostgres(embedded = false)
14+
fun Application.configureRouting(dbConnection: Connection) {
1515
val articleService = ArticleService(dbConnection)
1616
routing {
1717
// Create new Article
@@ -22,60 +22,48 @@ fun Application.configureRouting() {
2222
}
2323
// Read an Article
2424
get("/articles/{id}") {
25-
val id = call.parameters["id"]?.toInt() ?: throw IllegalArgumentException("Invalid ID")
25+
val id = call.parameters["id"]?.toInt() ?: throw DbElementNotFoundException("Invalid article ID")
2626
try {
2727
val article = articleService.read(id)
2828
call.respond(HttpStatusCode.OK, article)
29-
} catch (e: Exception) {
29+
} catch (cause: DbElementNotFoundException) {
3030
call.respond(HttpStatusCode.NotFound)
3131
}
3232
}
3333
// Update an Article
3434
put("/articles/{id}") {
35-
val id = call.parameters["id"]?.toInt() ?: throw IllegalArgumentException("Invalid ID")
36-
val article = call.receive<Article>()
37-
articleService.update(id, article)
38-
call.respond(HttpStatusCode.OK)
35+
val id = call.parameters["id"]?.toInt() ?: throw DbElementNotFoundException("Invalid article ID")
36+
try {
37+
val article = call.receive<Article>()
38+
articleService.update(id, article)
39+
call.respond(HttpStatusCode.OK)
40+
} catch (cause: DbElementNotFoundException) {
41+
call.respond(HttpStatusCode.NotFound)
42+
}
3943
}
4044
// Delete an Article
4145
delete("/articles/{id}") {
42-
val id = call.parameters["id"]?.toInt() ?: throw IllegalArgumentException("Invalid ID")
43-
articleService.delete(id)
44-
call.respond(HttpStatusCode.OK)
46+
val id = call.parameters["id"]?.toInt() ?: throw DbElementNotFoundException("Invalid article ID")
47+
try {
48+
articleService.delete(id)
49+
call.respond(HttpStatusCode.OK)
50+
} catch (cause: DbElementNotFoundException) {
51+
call.respond(HttpStatusCode.NotFound)
52+
}
4553
}
4654
}
4755
}
4856

49-
/**
50-
* Makes a connection to a Postgres database.
51-
*
52-
* In order to connect to your running Postgres process,
53-
* please specify the following parameters in your configuration file:
54-
* - postgres.url -- Url of your running database process.
55-
* - postgres.user -- Username for database connection
56-
* - postgres.password -- Password for database connection
57-
*
58-
* If you don't have a database process running yet, you may need to [download]((https://www.postgresql.org/download/))
59-
* and install Postgres and follow the instructions [here](https://postgresapp.com/).
60-
* Then, you would be edit your url, which is usually "jdbc:postgresql://host:port/database", as well as
61-
* user and password values.
62-
*
63-
*
64-
* @param embedded -- if [true] defaults to an embedded database for tests that runs locally in the same process.
65-
* In this case you don't have to provide any parameters in configuration file, and you don't have to run a process.
66-
*
67-
* @return [Connection] that represent connection to the database. Please, don't forget to close this connection when
68-
* your application shuts down by calling [Connection.close]
69-
* */
7057
fun Application.connectToPostgres(embedded: Boolean): Connection {
7158
Class.forName("org.postgresql.Driver")
7259
if (embedded) {
7360
return DriverManager.getConnection("jdbc:postgresql://localhost/test;DB_CLOSE_DELAY=-1", "root", "")
7461
} else {
75-
val url = environment.config.property("postgres.url").getString()
76-
val user = environment.config.property("postgres.user").getString()
77-
val password = environment.config.property("postgres.password").getString()
78-
62+
val configs = YamlConfig("postgres.yaml")
63+
val url = "jdbc:postgresql://localhost:5432/" +
64+
configs?.property("services.postgres.environment.POSTGRES_DB")?.getString()
65+
val user = configs?.property("services.postgres.environment.POSTGRES_USER")?.getString()
66+
val password = configs?.property("services.postgres.environment.POSTGRES_PASSWORD")?.getString()
7967
return DriverManager.getConnection(url, user, password)
8068
}
8169
}

postgres/src/main/kotlin/com/example/plugins/Serialization.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,10 @@ package com.example.plugins
22

33
import io.ktor.serialization.kotlinx.json.*
44
import io.ktor.server.plugins.contentnegotiation.*
5-
import io.ktor.server.response.*
65
import io.ktor.server.application.*
7-
import io.ktor.server.routing.*
86

97
fun Application.configureSerialization() {
108
install(ContentNegotiation) {
119
json()
1210
}
13-
routing {
14-
get("/json/kotlinx-serialization") {
15-
call.respond(mapOf("hello" to "world"))
16-
}
17-
}
1811
}

postgres/src/main/resources/application.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,3 @@ ktor:
44
- com.example.ApplicationKt.module
55
deployment:
66
port: 8080
7-
postgres:
8-
url: "jdbc:postgresql://localhost:5432/articles"
9-
user: "user"
10-
password: "password"

0 commit comments

Comments
 (0)