4

我正在尝试在播放框架中的 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 范围”的方式访问它,即每个请求单独存储它们的会话,但所有需要会话的服务都可以在公共中找到它每个请求分开的范围。

4

1 回答 1

1

我认为问题在于您将 Java API 与 Scala 控制器一起使用。Http.Context仅当您使用 Java 控制器时才设置。你考虑过使用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

于 2012-08-12T03:16:48.827 回答