Version 7, last updated by dph01 at 23 May 11:58 UTC
Managing State
Lift has several ‘XVar’ classes for managing server-side state: ContainerVar, RequestVar, ScreenVar, SessionVar, TransientRequestVar, WizardVar.
They are all similar in their how they are used, and the mechanism by which data is held within them. They differ primarily by the lifetime of the data they contain.
Using ’XVar’s
To define, say, a SessionVar, create a singleton that extends SessionVar:
object myData extends SessionVar[String]("Default")In this case myData is strongly typed as a String. Only a String may be put in or taken out. The expression "Default" is the default value for the given SessionVar. The expression is a passed “By Name” and is only evaluated whenever the SessionVar is read before it is set.
To set the data: myData.set("foo")
To access the data: myData.is
A common pattern is to put the variable in a Box within the X Var, e.g:
object myModel extends SessionVar[Box[Model]](Empty)This pattern allows you to avoid null testing, and instead use for comprehensions to traverse Box and Option constructs. See DPP’s Blog on the subject.
Storage Mechanism
All XVar objects act as indices into a backing datastore. When you set, say, a RequestVar with something like nameRV(“Jo”), the set method creates an entry in a map, where the ‘key’ is based on the name of the variable (in this case, something like liftsvcode.snippet.NameSnippet$nameRV$), and ‘value’ is what we’re setting the RequestVar to (in this case ‘Jo’).
The backing datastores are global objects, and so are shared across all page requests, snippets, Ajax calls etc. So, if you have two XVar objects with the same name, in different scopes, they are in fact just acting as indices into the same datastore value (unless you have overridden the namesalt). So, in this sense, XVar objects appear to transcend the normal scope boundaries.
ContainerVar
ContainerVars hold data with a lifetime nominally equivalent to the lifetime of HttpSession attributes. This alternative to SessionVar keeps data in the container’s session and must be serializable to support session migration. Use SessionVars unless you are using MigratoryLiftSessions.
RequestVar
RequestVars hold data with a lifetime nominally equivalent to the lifetime of a page rendered by an HTTP request. RequestVars maintain their value throughout the duration of the current HTTP request and any callbacks for servicing AJAX calls associated with the rendered page. RequestVar instances have no value at the beginning of request servicing (excluding AJAX callbacks) and their value is discarded at the end of request processing.
They are commonly used to share values across many snippets and to share data across successive page requests.
For more information on RequestVars see the blogpost: Understanding Lift’s RequestVar
ScreenVar
tbc
SessionVar
A sessionVar holds data lifetime nominally equivalent to the lifetime of HttpSession attributes.
A typical use of a SessionVar in Lift is to manage the User session, so repeated requests from the same browser will be associated with the same data. This allows the primary key to the User object to be associated with user’s perception of a session so that once the user has logged in, they do not need to re-authenticate for each HTTP request.
Sessions are typically bound between the browser and the server via a cookie which contains a session identifier… a random number.
TransientRequestVar
A TransientRequestVar holds data with a lifetime strictly equal to the processing of a single HTTP request. Unlike ordinary RequestVar instances, TransientRequestVars will not maintain data for servicing of AJAX callbacks from a rendered page. This is useful in cases where the value stored within the RequestVar cannot safely be used across multiple requests; an example of such a value is a JTA UserTransaction which has a lifecycle strictly coupled to the actul HTTP request handling by the enclosing container.
Wizard Var
tbc