Skip to content

Instantly share code, notes, and snippets.

@avshabanov
Created November 30, 2014 21:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save avshabanov/d274e503ccfbf140206d to your computer and use it in GitHub Desktop.
Save avshabanov/d274e503ccfbf140206d to your computer and use it in GitHub Desktop.
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()}")
}
@avshabanov
Copy link
Author

Sample output:

Before using userService...
 > request = GetUserProfileRequestImpl(userIds=[1, 2, 3])
 > result = GetUserProfileResultImpl(profiles=[UserProfileImpl(id=1, name=user#1, avatarUrl=http://avatarUrl_1), UserProfileImpl(id=2, name=user#2, avatarUrl=http://avatarUrl_2), UserProfileImpl(id=3, name=user#3, avatarUrl=http://avatarUrl_3)]), timeDelta = 2
After using userService, result = GetUserProfileResultImpl(profiles=[UserProfileImpl(id=1, name=user#1, avatarUrl=http://avatarUrl_1), UserProfileImpl(id=2, name=user#2, avatarUrl=http://avatarUrl_2), UserProfileImpl(id=3, name=user#3, avatarUrl=http://avatarUrl_3)])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment