ほぼ参考にしたここのままなので原文を読んだ方が早いです。
CustomExecutionContextを定義
原文のままだとコンパイルできなかったので、SimpleResult -> Result, Map[_, _] -> Map[String, String]に変えています。
package concurrent
import org.slf4j.MDC
import scala.concurrent.{ ExecutionContextExecutor, ExecutionContext }
/**
* slf4j provides a MDC [[http://logback.qos.ch/manual/mdc.html Mapped Diagnostic Context]]
* based on a [[ThreadLocal]]. In an asynchronous environment, the callbacks can be called
* in another thread, where the local thread variable does not exist anymore.
*
* This execution context fixes this problem:
* it propagates the MDC from the caller's thread to the callee's one.
*/
object MDCHttpExecutionContext {
/**
* Create an MDCHttpExecutionContext with values from the current thread.
*/
def fromThread(delegate: ExecutionContext): ExecutionContextExecutor =
new MDCHttpExecutionContext(MDC.getCopyOfContextMap, delegate)
}
/**
* Manages execution to ensure that the given MDC context are set correctly
* in the current thread. Actual execution is performed by a delegate ExecutionContext.
*/
class MDCHttpExecutionContext(mdcContext: java.util.Map[String, String], delegate: ExecutionContext) extends ExecutionContextExecutor {
def execute(runnable: Runnable) = delegate.execute(new Runnable {
def run() {
val oldMDCContext = MDC.getCopyOfContextMap
setContextMap(mdcContext)
try {
runnable.run()
} finally {
setContextMap(oldMDCContext)
}
}
})
private[this] def setContextMap(context: java.util.Map[String, String]) {
if (context == null) {
MDC.clear()
} else {
MDC.setContextMap(context)
}
}
def reportFailure(t: Throwable) = delegate.reportFailure(t)
}
アプリケーションで使うデフォルトのExecutionContextを定義
package concurrent
import scala.concurrent.ExecutionContext
/**
* The standard [[play.api.libs.concurrent.Execution.defaultContext]] loses the MDC context.
*
* This custom [[ExecutionContext]] propagates the MDC context, so that the request
* and the correlation IDs can be logged.
*/
object Execution {
object Implicits {
implicit def defaultContext: ExecutionContext = Execution.defaultContext
}
def defaultContext: ExecutionContext = MDCHttpExecutionContext.fromThread(play.api.libs.concurrent.Execution.defaultContext)
}
あとは
import play.api.libs.concurrent.Execution.Implicits.defaultContext
を使っているところを
import concurrent.Execution.Implicits._
に変える。
CustomExecutionContextを使うためにActionを定義
package controllers
import concurrent.Execution
import scala.concurrent.Future
import play.api.mvc.Result
import scala.concurrent.ExecutionContext
import play.api.mvc.ActionBuilder
import play.api.mvc.Request
object Action extends ActionBuilder[Request] {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
block(request)
}
/**
* The standard [[play.api.mvc.Action]] loses the MDC context.
*
* This action builder sets the [[ExecutionContext]] so that the
* MDC context is propagated.
* With this custom [[ExecutionContext]], the request and the correlation IDs
* can be logged.
*/
override def executionContext: ExecutionContext = Execution.defaultContext
}
あとはこのActionを使ってControllerを記述する。