Play framework 2.0: Store values in Http.Context

喜欢而已 提交于 2019-12-13 13:31:18

问题


I'm trying to implement "request based" sessions in scalaquery in the play framework. I create a session using scalaquery and attempt to store it in the current http context, as follows:

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")
       }
   }
}

then i wrap my actions in my controllers like:

withTransaction(parse.anyContent) {
    Action {
       //code that produces a result here
    }
}

However, it crashes in the following line saying:

val context = Http.Context.current() 
[RuntimeException: There is no HTTP Context available from here.] 

So, why is the context not available? This code is called directly by the framework, so shouldn't the context be set by the time this code executes? Or am i using the wrong way for accessing the context?

EDIT: The "session" is of type org.scalaquery.session.Session. The reason why i want to set it in the HttpContext is so that the wrapped actions can access it in an "http scoped" fashion, i.e. That each request stores their session separately, yet all services that need a session can find it in a public scope that is separated per request.


回答1:


I think the problem is you're using the Java API with the Scala controller. Http.Context is only set if you're using the Java controller. Have you considered using the Scala Session API?

Also, another question is, why do you need to store the session in the context? I see you just remove it at the end anyway. If what you need is for the sub-actions to be able to access the session, you could just pass it in the function.

I'm just going to assume session is of type 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()
       }
   }
}

and your sub-actions would be

withTransaction(parse.anyContent) { session => request =>
    //code that produces a result here
}

you don't need to wrap this in Action anymore since it's already wrapped by withTransaction



来源:https://stackoverflow.com/questions/11918562/play-framework-2-0-store-values-in-http-context

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!