package com.alexshabanov.kotwebdemo.service.radio | |
import java.util.Collections | |
import java.util.ArrayList | |
// prototype of non-AOP based approach to service exposure | |
// | |
// Public API | |
// | |
trait Result | |
trait Request | |
trait Response<TResult> { | |
fun get(): TResult | |
} | |
trait ResponseCreator { | |
fun create<TRequest, TResult>(request : TRequest, calcFun: (TRequest) -> TResult) : Response<TResult> | |
} | |
// Framework Support | |
/** | |
* Sample response, in real applications may use Futures with the default service SLA timeouts/retries | |
*/ | |
class ImmediateResponse<TResult>(val result : TResult) : Response<TResult> { | |
override fun get(): TResult = result | |
} | |
/** | |
* Sample response creator | |
*/ | |
class ImmediateResponseCreator : ResponseCreator { | |
override fun create<TRequest, TResult>(request: TRequest, | |
calcFun: (TRequest) -> TResult): Response<TResult> { | |
// [1] log request | |
println(" > request = ${request}") | |
// [2] start measuring time | |
val startTime = System.currentTimeMillis() | |
try { | |
val result = calcFun(request) | |
// [3] stop measuring time | |
val timeDelta = System.currentTimeMillis() - startTime | |
// [4] log result and execution time | |
println(" > result = ${result}, timeDelta = ${timeDelta}") | |
return ImmediateResponse(result) | |
} catch (e : Exception) { | |
// [3] stop measuring time | |
val timeDelta = System.currentTimeMillis() - startTime | |
// [4] log exception and execution time | |
println(" > error = ${e.getMessage()}, timeDelta = ${timeDelta}") | |
throw e // rethrow an exception | |
} | |
} | |
} | |
// | |
// Sample Service API | |
// | |
trait GetUserProfilesRequest : Request { | |
val userIds : List<Long> | |
} | |
trait UserProfile { | |
val id : Long? | |
val name : String | |
val avatarUrl : String | |
} | |
trait GetUserProfileResult : Result { | |
val profiles : List<UserProfile> | |
} | |
trait UserService { | |
fun getUserProfiles(request : GetUserProfilesRequest) : Response<GetUserProfileResult> | |
} | |
// | |
// Sample Service Impl | |
// | |
data class UserProfileImpl(override val id : Long?, | |
override val name : String, | |
override val avatarUrl : String) : UserProfile | |
data class GetUserProfileResultImpl(override val profiles : List<UserProfile>) : GetUserProfileResult | |
data class GetUserProfileRequestImpl(override val userIds : List<Long>) : GetUserProfilesRequest | |
class UserServiceImpl(val responseCreator : ResponseCreator) : UserService { | |
override fun getUserProfiles(request: GetUserProfilesRequest): Response<GetUserProfileResult> { | |
return responseCreator.create(request, { (r) -> /* hey mom, look at this amazing type inference! */ | |
val result = ArrayList<UserProfile>(r.userIds.size) | |
for (id in r.userIds) { | |
result.add(UserProfileImpl(id = id, name = "user#${id}", avatarUrl = "http://avatarUrl_${id}")) | |
} | |
GetUserProfileResultImpl(profiles = result) | |
}) | |
} | |
} | |
// | |
// Demo | |
// | |
fun main(args: Array<String>) { | |
// [1] "DI container" initialization | |
val responseCreator = ImmediateResponseCreator() // will be shared across different services | |
// [2] User Service | |
val userService = UserServiceImpl(responseCreator = responseCreator) | |
// [3] Usage... | |
println("Before using userService...") | |
val response = userService.getUserProfiles(GetUserProfileRequestImpl(userIds = listOf(1L, 2L, 3L))) | |
println("After using userService, result = ${response.get()}") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Sample output: