Skip to content
Snippets Groups Projects
Commit cc0b3c17 authored by Clément CORNU's avatar Clément CORNU
Browse files

feat: better exception handling

parent 5d866514
No related branches found
No related tags found
No related merge requests found
val koin_version: String by project val koin_version: String by project
val kotlin_version: String by project val kotlin_version: String by project
val ktor_version: String by project
val logback_version: String by project val logback_version: String by project
val dynamo_version: String by project val dynamo_version: String by project
val dynamo_kt_version: String by project val dynamo_kt_version: String by project
...@@ -32,11 +33,12 @@ repositories { ...@@ -32,11 +33,12 @@ repositories {
dependencies { dependencies {
// Ktor // Ktor
implementation("io.ktor:ktor-server-core") implementation("io.ktor:ktor-server-core:$ktor_version")
implementation("io.ktor:ktor-server-auth") implementation("io.ktor:ktor-server-auth:$ktor_version")
implementation("io.ktor:ktor-server-openapi") implementation("io.ktor:ktor-server-openapi:$ktor_version")
implementation("io.ktor:ktor-server-config-yaml") implementation("io.ktor:ktor-server-config-yaml:$ktor_version")
implementation("io.ktor:ktor-server-netty") implementation("io.ktor:ktor-server-netty:$ktor_version")
implementation("io.ktor:ktor-server-status-pages:$ktor_version")
// Dependency injection // Dependency injection
implementation("io.insert-koin:koin-ktor:$koin_version") implementation("io.insert-koin:koin-ktor:$koin_version")
...@@ -52,6 +54,7 @@ dependencies { ...@@ -52,6 +54,7 @@ dependencies {
implementation("software.amazon.awssdk:dynamodb:$dynamo_version") implementation("software.amazon.awssdk:dynamodb:$dynamo_version")
implementation("dev.andrewohara:dynamokt:$dynamo_kt_version") implementation("dev.andrewohara:dynamokt:$dynamo_kt_version")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:$kotlin_reactive_version") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:$kotlin_reactive_version")
implementation("io.ktor:ktor-server-host-common:$ktor_version")
// Tests // Tests
testImplementation("io.ktor:ktor-server-test-host") testImplementation("io.ktor:ktor-server-test-host")
......
package betclic.test package betclic.test
import betclic.test.configuration.configureExceptionHandling
import betclic.test.configuration.configureKoin import betclic.test.configuration.configureKoin
import betclic.test.configuration.configureRouting import betclic.test.configuration.configureRouting
import betclic.test.configuration.configureSerialization import betclic.test.configuration.configureSerialization
...@@ -19,6 +20,7 @@ fun Application.module() { ...@@ -19,6 +20,7 @@ fun Application.module() {
fun Application.configuration() { fun Application.configuration() {
configureKoin() configureKoin()
configureSerialization() configureSerialization()
configureExceptionHandling()
configureRouting() configureRouting()
} }
......
package betclic.test.configuration
import betclic.test.player.exceptions.AlreadyExistingPlayerException
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.plugins.*
import io.ktor.server.plugins.statuspages.*
import io.ktor.server.response.*
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException
private const val SOMETHING_WENT_WRONG = "Something went wrong"
fun Application.configureExceptionHandling() {
install(StatusPages) {
exception<Throwable> { call, cause ->
when (cause) {
is NotFoundException -> call.respond(HttpStatusCode.NotFound, cause.message ?: SOMETHING_WENT_WRONG)
is DynamoDbException -> call.respond(
HttpStatusCode.InternalServerError,
cause.message ?: "$SOMETHING_WENT_WRONG with DynamoDb"
)
is AlreadyExistingPlayerException -> call.respond(
HttpStatusCode.BadRequest,
cause.message ?: SOMETHING_WENT_WRONG
)
}
call.respondText(text = "500: $cause", status = HttpStatusCode.InternalServerError)
}
}
}
\ No newline at end of file
...@@ -3,56 +3,35 @@ package betclic.test.player ...@@ -3,56 +3,35 @@ package betclic.test.player
import betclic.test.player.dtos.PlayerCreationDTO import betclic.test.player.dtos.PlayerCreationDTO
import betclic.test.player.dtos.PlayerInfoDTO import betclic.test.player.dtos.PlayerInfoDTO
import betclic.test.player.dtos.PlayerUpdateDTO import betclic.test.player.dtos.PlayerUpdateDTO
import betclic.test.player.exceptions.AlreadyExistingPlayerException
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
import io.ktor.server.plugins.*
import io.ktor.server.request.* import io.ktor.server.request.*
import io.ktor.server.response.* import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
import org.koin.ktor.ext.inject import org.koin.ktor.ext.inject
private const val SOMETHING_WENT_WRONG = "Something went wrong."
fun Routing.playerRoutes() { fun Routing.playerRoutes() {
val playerService by inject<PlayerService>() val playerService by inject<PlayerService>()
// const // const
route("/players") { route("/players") {
post { post {
val request = call.receive<PlayerCreationDTO>() val request = call.receive<PlayerCreationDTO>()
try { call.respond(HttpStatusCode.Created, playerService.createNewPlayer(request))
call.respond(HttpStatusCode.Created, playerService.createNewPlayer(request))
} catch (e: AlreadyExistingPlayerException) {
call.respond(status = HttpStatusCode.BadRequest, message = e.message ?: SOMETHING_WENT_WRONG)
}
} }
put { put {
val request = call.receive<PlayerUpdateDTO>() val request = call.receive<PlayerUpdateDTO>()
try { call.respond(HttpStatusCode.OK, playerService.updatePlayer(request))
call.respond(HttpStatusCode.OK, playerService.updatePlayer(request))
} catch (e: NotFoundException) {
call.respond(status = HttpStatusCode.NotFound, message = e.message ?: SOMETHING_WENT_WRONG)
}
} }
get("/{pseudo}") { get("/{pseudo}") {
val pseudo = call.parameters["pseudo"] ?: return@get call.respond(HttpStatusCode.BadRequest) val pseudo = call.parameters["pseudo"] ?: return@get call.respond(HttpStatusCode.BadRequest)
try { call.respond<Player>(playerService.findPlayerByPseudo(pseudo))
call.respond<Player>(playerService.findPlayerByPseudo(pseudo))
} catch (e: NotFoundException) {
call.respond(status = HttpStatusCode.NotFound, message = e.message ?: SOMETHING_WENT_WRONG)
}
} }
get("/{pseudo}/info") { get("/{pseudo}/info") {
val pseudo = call.parameters["pseudo"] ?: return@get call.respond(HttpStatusCode.BadRequest) val pseudo = call.parameters["pseudo"] ?: return@get call.respond(HttpStatusCode.BadRequest)
try { call.respond<PlayerInfoDTO>(playerService.getPlayerInfoByPseudo(pseudo))
call.respond<PlayerInfoDTO>(playerService.getPlayerInfoByPseudo(pseudo))
} catch (e: NotFoundException) {
call.respond(status = HttpStatusCode.NotFound, message = e.message ?: SOMETHING_WENT_WRONG)
}
} }
get("/ranking") { get("/ranking") {
......
package betclic.test.player.exceptions package betclic.test.player.exceptions
class AlreadyExistingPlayerException(val pseudo: String) : class AlreadyExistingPlayerException(val pseudo: String) :
RuntimeException("$pseudo already exists. You still can update this player points") Exception("$pseudo already exists. You still can update this player points")
\ No newline at end of file \ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment