Update example application
This commit is contained in:
parent
b6bb3aafaa
commit
97d0567489
@ -7,7 +7,7 @@ plugins {
|
||||
}
|
||||
|
||||
application {
|
||||
mainClassName = "io.ktor.server.netty.DevelopmentEngine"
|
||||
mainClassName = "io.ktor.server.netty.EngineMain"
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
@ -1,2 +1,2 @@
|
||||
ktorVersion=0.9.0
|
||||
ktorVersion=1.0.0-beta-3
|
||||
logbackVersion=1.2.3
|
||||
|
@ -27,6 +27,7 @@ import com.github.michaelbull.result.mapBoth
|
||||
import com.github.michaelbull.result.mapError
|
||||
import com.github.michaelbull.result.toResultOr
|
||||
import io.ktor.application.Application
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.application.call
|
||||
import io.ktor.application.install
|
||||
import io.ktor.features.CallLogging
|
||||
@ -35,12 +36,12 @@ import io.ktor.features.ContentNegotiation
|
||||
import io.ktor.features.DefaultHeaders
|
||||
import io.ktor.gson.gson
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.Parameters
|
||||
import io.ktor.request.receive
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.routing.get
|
||||
import io.ktor.routing.post
|
||||
import io.ktor.routing.routing
|
||||
import io.ktor.util.ValuesMap
|
||||
|
||||
fun Application.main() {
|
||||
install(DefaultHeaders)
|
||||
@ -52,30 +53,35 @@ fun Application.main() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
routing {
|
||||
get("/customers/{id}") {
|
||||
readId(call.parameters)
|
||||
call.parameters.readId()
|
||||
.andThen(CustomerId.Companion::create)
|
||||
.andThen(CustomerService::getById)
|
||||
.mapError(::messageToResponse)
|
||||
.mapBoth(
|
||||
{ call.respond(HttpStatusCode.OK, CustomerDto.from(it)) },
|
||||
{ call.respond(it.first, it.second) }
|
||||
success = { customer ->
|
||||
call.respond(HttpStatusCode.OK, CustomerDto.from(customer))
|
||||
},
|
||||
failure = { (status, message) ->
|
||||
call.respond(status, message)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
post("/customers/{id}") {
|
||||
readId(call.parameters)
|
||||
.andThen {
|
||||
call.parameters.readId()
|
||||
.andThen { id ->
|
||||
val dto = call.receive<CustomerDto>()
|
||||
dto.id = it
|
||||
dto.id = id
|
||||
Ok(dto)
|
||||
}
|
||||
.andThen(Customer.Companion::from)
|
||||
.andThen(CustomerService::upsert)
|
||||
.mapError(::messageToResponse)
|
||||
.mapBoth(
|
||||
{ event ->
|
||||
success = { event ->
|
||||
if (event == null) {
|
||||
call.respond(HttpStatusCode.NotModified)
|
||||
} else {
|
||||
@ -83,15 +89,17 @@ fun Application.main() {
|
||||
call.respond(status, message)
|
||||
}
|
||||
},
|
||||
{ call.respond(it.first, it.second) }
|
||||
failure = { (status, message) ->
|
||||
call.respond(status, message)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun readId(values: ValuesMap): Result<Long, DomainMessage> {
|
||||
return values["id"]
|
||||
private fun Parameters.readId(): Result<Long, DomainMessage> {
|
||||
return this["id"]
|
||||
?.toLongOrNull()
|
||||
.toResultOr { CustomerRequired }
|
||||
}
|
||||
|
@ -2,18 +2,22 @@ package com.github.michaelbull.result.example.model.domain
|
||||
|
||||
import com.github.michaelbull.result.Err
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
|
||||
data class EmailAddress(
|
||||
val address: String
|
||||
) {
|
||||
companion object {
|
||||
private val pattern = ".+@.+\\..+".toRegex() // crude validation
|
||||
private const val MAX_LENGTH = 20
|
||||
private val PATTERN = ".+@.+\\..+".toRegex() // crude validation
|
||||
|
||||
fun create(address: String?) = when {
|
||||
address == null || address.isBlank() -> Err(EmailRequired)
|
||||
address.length > 20 -> Err(EmailTooLong)
|
||||
!address.matches(pattern) -> Err(EmailInvalid)
|
||||
else -> Ok(EmailAddress(address))
|
||||
fun create(address: String?): Result<EmailAddress, DomainMessage> {
|
||||
return when {
|
||||
address.isNullOrBlank() -> Err(EmailRequired)
|
||||
address.length > MAX_LENGTH -> Err(EmailTooLong)
|
||||
!address.matches(PATTERN) -> Err(EmailInvalid)
|
||||
else -> Ok(EmailAddress(address))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,18 +2,23 @@ package com.github.michaelbull.result.example.model.domain
|
||||
|
||||
import com.github.michaelbull.result.Err
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
|
||||
data class PersonalName(
|
||||
val first: String,
|
||||
val last: String
|
||||
) {
|
||||
companion object {
|
||||
fun create(first: String?, last: String?) = when {
|
||||
first == null || first.isBlank() -> Err(FirstNameRequired)
|
||||
last == null || last.isBlank() -> Err(LastNameRequired)
|
||||
first.length > 10 -> Err(FirstNameTooLong)
|
||||
last.length > 10 -> Err(LastNameTooLong)
|
||||
else -> Ok(PersonalName(first, last))
|
||||
private const val MAX_LENGTH = 10
|
||||
|
||||
fun create(first: String?, last: String?): Result<PersonalName, DomainMessage> {
|
||||
return when {
|
||||
first.isNullOrBlank() -> Err(FirstNameRequired)
|
||||
last.isNullOrBlank() -> Err(LastNameRequired)
|
||||
first.length > MAX_LENGTH -> Err(FirstNameTooLong)
|
||||
last.length > MAX_LENGTH -> Err(LastNameTooLong)
|
||||
else -> Ok(PersonalName(first, last))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package com.github.michaelbull.result.example.service
|
||||
|
||||
import com.github.michaelbull.result.Err
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
import com.github.michaelbull.result.andThen
|
||||
import com.github.michaelbull.result.example.model.domain.Customer
|
||||
@ -14,6 +12,7 @@ import com.github.michaelbull.result.example.model.domain.DomainMessage
|
||||
import com.github.michaelbull.result.example.model.domain.EmailAddressChanged
|
||||
import com.github.michaelbull.result.example.model.entity.CustomerEntity
|
||||
import com.github.michaelbull.result.map
|
||||
import com.github.michaelbull.result.mapAll
|
||||
import com.github.michaelbull.result.mapBoth
|
||||
import com.github.michaelbull.result.mapError
|
||||
import com.github.michaelbull.result.toResultOr
|
||||
@ -25,26 +24,18 @@ object CustomerService {
|
||||
fun getAll(): Result<Collection<Customer>, DomainMessage> {
|
||||
return Result.of(repository::findAll)
|
||||
.mapError(::exceptionToDomainMessage)
|
||||
.andThen { result: Collection<CustomerEntity> ->
|
||||
Ok(result.map {
|
||||
val customer = Customer.from(it)
|
||||
when (customer) {
|
||||
is Ok -> customer.value
|
||||
is Err -> return customer
|
||||
}
|
||||
})
|
||||
}
|
||||
.mapAll(Customer.Companion::from)
|
||||
}
|
||||
|
||||
fun getById(id: CustomerId): Result<Customer, DomainMessage> {
|
||||
return getAll().andThen { it.findCustomer(id) }
|
||||
return getAll().andThen { customers -> customers.findCustomer(id) }
|
||||
}
|
||||
|
||||
fun upsert(customer: Customer): Result<DomainMessage?, DomainMessage> {
|
||||
val entity = CustomerEntity.from(customer)
|
||||
return getById(customer.id).mapBoth(
|
||||
{ existing -> updateCustomer(entity, existing, customer) },
|
||||
{ createCustomer(entity) }
|
||||
success = { existing -> updateCustomer(entity, existing, customer) },
|
||||
failure = { createCustomer(entity) }
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
ktor {
|
||||
deployment {
|
||||
port = 9000
|
||||
port = 9090
|
||||
}
|
||||
|
||||
application {
|
||||
|
@ -35,7 +35,7 @@ inline infix fun <V, E> Result<V, E>.orElse(transform: (E) -> Result<V, E>): Res
|
||||
* otherwise this [Ok].
|
||||
*/
|
||||
inline infix fun <V, E> Result<V, E>.recover(transform: (E) -> V): Ok<V> {
|
||||
return when(this) {
|
||||
return when (this) {
|
||||
is Ok -> this
|
||||
is Err -> Ok(transform(error))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user