views:

696

answers:

2

Hi all-

I am trying to store a session variable and then use it to modify the menu in Boot.scala. Here is how I am storing the variable in a snippet:

object sessionUserType extends  SessionVar[String](null)
  def list (xhtml : NodeSeq) : NodeSeq = {

    Helpers.bind("sendTo", xhtml, 
                 "provider" -> SHtml.link("/providerlogin",() => sessionUserType("provider"), Text("Provider")),
        "student" -> SHtml.link("/studentlogin",() => sessionUserType("student"), Text("Student")))
    }

Then in Boot.scala I do this:

val studentSessionType = If(() => S.getSessionAttribute("sessionUserType").open_!.equals("student"),
         "not a student session")

I also tried to call the object by name (sessionUserType), but it can never find it, so I thought this might work, but I keep getting an empty box when i access it even though the actual binding and function get executed prior to the menu rendering.

Any help would be much appreciated.

Thanks

+5  A: 

In order to get a value from SessionVar or RequestVar, call is method on it, i.e. sessionUserType.is

By the way, did you read "About: Session state"?

Side note

I believe RequestVar is a better fit in your case. I am not sure I could catch your code right without the context, but it could be rewritten at least like:

case class LoginType
case object StudentLogin extends LoginType
case object ProviderLogin extends LoginType

object loginType extends RequestVar[Box[LoginType]](Empty)
// RequestVar is a storage with request-level scope

...
"provider" -> SHtml.link("/providerlogin",() => loginType(Full(ProviderLogin)), Text("Provider")),
// `SHtml.link` works in this way. Your closure will be called after a user
// transition, that is when /providerlogin is loading.
...

val studentSessionType = If(() => { loginType.is map {_ == StudentLogin} openOr false },
                "not a student session")
// As a result, this test will be true if our RequestVar holds StudentLogin,
// but it will be so for one page only (/studentlogin I guess). If you want
// scope to be session-wide, use SessionVar
Alexander Azarov
Alexander-Thanks for this. Unfortunately, I think I need to use a SessionVar as I will be modifying the menu and the view accordingly throughout the user's session depending on what type of user they are. The problem I am having is when I try to access the SessionVar, say StudentLogin in Boot.scala, the compiler can't find it. That is why I resorted to using the S object in the first place. Is there some trick (outside of importing the class, which I've tried) to get the SessionVar which is in snippets.LoginType (for instance) within the scope of Boot.scala? Thanks
I think I've got it. The object needed to be outside of the class definition of the snippet. Thanks!
Yes, Lift creates snippet instances, so any object declared in the snippet class will live as long as snippet instances lives, which is not what you want for session-scope storage.
Alexander Azarov
Is there a default place to declare all session variables? Like Boot.scala? And if so, will other snippets, models, etc, be able access them just by calling VariableName...?
You can declare them on the top level (package) or in an object if appropriate
Alexander Azarov
A: 

I think the disconnect is that you are assuming that the a Session Attribute is going to match your SessionVar, and that is not the case. Lift is a very secure framework, and one if its features is that Lift creates opaque GUIDs to refer to components on the server side.

If you want getSessionAttribute to return something, think about how you can call setSessionAttribute.

AWhitford