0
votes

I am developing an application using Play Framework 2.4 with Scala. In my application, I want to retrieve menus based on the URL. Therefore, I need to pass either session object (preferably) or a request object to a trait.

I know, how to access session in a controller method or a view template but I need to access session outside controller methods.

My sample code is as below:

trait SomeTrait{

  var webID: String 

  implicit def getMenus(wID: Long): GlobalData = {
    val menus = someDao.getActiveMenus(wID)
 }
}

class Application  extends Controller with SomeTrait{
    val someForm = Form(
                        mapping(
                          "field1" -> longNumber,
                          "field2" -> nonEmptyText
                        )(SomeClass.apply)(SomeClass.unapply))
   def otherDao = new OtherDAO

   // ================= this will refresh menus ================
   val tempCall = getMenus(request.session.get("wID").getOrElse("-1").toLong) //Here I need to access session variable
   // ========================================================== 

   def someDef = IsAuthenticatedAsync {user => implicit request =>
     val wid = request.session.get("wID").getOrElse("-1").toLong //this works perfectly fine
     Future.successful(Ok(views.html.some.someView(wid, someForm)))
  }
}   

Like in Play framework 1.2, it seems that it was possible to create session object: www.stackoverflow.com/questions/3654582/object-session-in-playframework https://www.playframework.com/documentation/1.2/api/play/mvc/Scope.Session.html

In fact, you can get hold of Session and request object in Play Framework JAVA apis but somehow, it's not very clear, how to do it in Play Framework Scala?

https://www.playframework.com/documentation/2.4.4/api/java/play/mvc/Http.Context.Implicit.html

In case, if it's not possible to get hold of request or session object outside method in controller in Play Framework 2.4 with Scala, can I use Play Cache? Do you see any problem with use of cache in my code? (www.playframework.com/documentation/2.4.x/ScalaCache)

In fact, I am looking at Redis Cache as well (www.redis.io/documentation)

Your help/suggestions will be highly appreciated!

=================================================================

Edit: 5th March 2016

Somehow, I am not very confident of using Cache as I am not sure in multi-user environment, how will it work?

Now, I have come up with new approach which is kind of working but only problem is, it looks like, requests are handled separately and I don't know how to pass request data from Java controller to Scala controller?

package controllers;

import play.*;
import play.mvc.*;

import views.html.*;

public class BaseJavaController extends Controller {

    private play.mvc.Http.Request rq = request();
    private String w1ID = session("wsID"); 

    protected String getW1ID() {  // define getter
    return w1ID;
    }

    protected void setW1ID(String wid) {  // define setter
        this.w1ID = wid;
    }  
}

As you can see, I am able to get hold of request and session object in Java controller and with guice injection, I am able to inject Java controller into Scala controller successfully.

But at runtime, it gives an error:

[ProvisionException: Unable to provision, see the following errors:

1) Error injecting constructor, java.lang.RuntimeException: There is no HTTP    Context available from here.
  at controllers.BaseJavaController.<init>(BaseJavaController.java:8)
  while locating controllers.BaseJavaController
    for parameter 0 at controllers.Application.<init>(Application.scala:138)
  while locating controllers.Application

1 error] 

Any help on how to fix this error will be highly appreciated!

1
Are you trying to initialize a val in the Application class based on the current request? That's not going to work. Or is val tempCall scoped within some method?lyjackal
tempCall is just a place holder and is not scoped within any method. The purpose of val tempCall is to refresh menus, just in case, they have modified or newly added. But, now, I want to refresh menus based on the session variable.User12345678

1 Answers

0
votes

Looks like you used tempCall as a cache for some complex/slow logic. And now you have a new requirement that force this logic to be dependent on wID.

So, tempCall can not be just a simple val of one element. You can not access the session or request outside of a controller method. Your options ordered from simpler to more complex

  • Transform it to a Map if there are only a few values for wID
  • Convert it to def tempCall(wID: String) and use ScalaCache or Redis

The right decision depends a lot on your requirements. Play cache module will offer you a simple yet flexible way to get started by default relying on ehCache that could be changed to use redis if that is what you need.
https://www.playframework.com/modules/redis-0.2/home