Search code examples
javascalaplayframeworkplayframework-2.1

Using scala and java in play framework 2.1 : Session usage


I'm currently using the session() of play framework in my template :

@if(session().get("email")==null){
    <li><a href="@controllers.routes.General.login">Login</a></li>
}else{
    <li><a href="@controllers.routes.General.logout">Logout</a></li>
}

This template is used in all of my views. Some of these views are controlled by a Java controller, and some are with a Scala controller.

When I click on links that lead to Java controllers, I have no problems, the links for login and logout are correctly handled.

When I click on links that lead to Scala controllers, I get a [RuntimeException: There is no HTTP Context available from here.]

From what I read in here about scala controllers, I understood that they didn't return the http context when rendering a page, but I really want to be able to use the session in my template.

I thought about using an argument session() in my view, templates and controllers, but I believe that there will be a conflict between the java session (play.mvc.http.session) and the scala session (play.api.mvc.session) when play will compile the html pages.

Am I stuck? Is there a possibility to force scala controllers to give back the http context ?


Solution

  • The root cause maybe the Java controllers and Scala controllers are handled differently. I have my project in Java first, and then try to add more Scala controllers. I also came across this problem (BTW, I am using Play 2.3.2).

    I tried to fix this by setting my own Http.Context in the TheadLocal variable using my own ActionBuilder.

    import play.api.mvc._
    import scala.concurrent.Future
    import play.mvc.Http.Context
    import play.core.j.JavaHelpers
    
    object ContextAction extends ActionBuilder[Request] {
    
      def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
        Context.current.set(JavaHelpers.createJavaContext(request))
        block(request)
      }
    }
    

    Then my Scala controller actions simply use this ContextAction instead:

    class TestController extends Controller {
      def test = ContextAction { implicit request =>
        Ok(views.html.index())
      }
    }
    

    And this way the index template can access all request() / session() / etc.