Created
November 30, 2014 21:57
-
-
Save avshabanov/d274e503ccfbf140206d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
Sample output: