我正在尝试在play框架中的scalaquery中实现“基于请求”的会话。我使用scalaquery创建一个会话,并尝试将其存储在当前的http上下文中,如下所示:
def withTransaction[A](bp: BodyParser[A])(f: Request[A] => Result): Action[A] = {
Action(bp) {
request =>
val context = Http.Context.current()
val session = createSession()
session.conn.setAutoCommit(false)
context.args.put("scalaquery.session", session)
try {
val result = f(request)
session.conn.commit()
result
}
catch {
case t: Throwable =>
session.conn.rollback()
throw t
}
finally {
session.close()
context.args.remove("scalaquery.session")
}
}
}
然后我将我的动作包裹在我的控制器中,如:
withTransaction(parse.anyContent) {
Action {
//code that produces a result here
}
}
然而,它在以下行中崩溃说:
val context = Http.Context.current()
[RuntimeException: There is no HTTP Context available from here.]
那么,为什么上下文不可用?这个代码是由框架直接调用的,所以不应该在代码执行时设置上下文?或者我使用错误的方式来访问上下文?
编辑:“会话”的类型为org.scalaquery.session.Session。我想在HttpContext中设置它的原因是包装的动作可以以“http范围”方式访问它,即每个请求分别存储它们的会话,但是所有需要会话的服务都可以在公共场合找到它每个请求分隔的范围。
答案 0 :(得分:1)
我认为问题是你在Scala控制器上使用Java API。只有在使用Java控制器时才会设置Http.Context
。您是否考虑过使用Scala Session API?
另外,另一个问题是,为什么需要在上下文中存储会话?无论如何,我看到你最后将它删除了。如果您需要的是子操作能够访问会话,您可以在函数中传递它。
我只是假设session
的类型为Session
def withTransaction[A](bp: BodyParser[A])(f: Session => Request[A] => Result): Action[A] = {
Action(bp) {
request =>
val session = createSession()
session.conn.setAutoCommit(false)
try {
val result = f(session)(request)
session.conn.commit()
result
}
catch {
case t: Throwable =>
session.conn.rollback()
throw t
}
finally {
session.close()
}
}
}
你的子行动将是
withTransaction(parse.anyContent) { session => request =>
//code that produces a result here
}
你不需要在Action
包裹它,因为它已经被withTransaction
包裹了