In one of my previous posts I described how you can bind
Futures to page elements in Lift 2.
Lift 3.0.0 that has been released two weeks ago handles this type of bindings out of the box. What’s more, it’s possible to wrap
RestHelper response in a
LAFuture to have it handled asynchronously using container continuations. One of the next milestones on a way for even better async
support in Lift is an elimination of a recurring pain point in many projects – access to container’s request and session in
LAFuture. Although some discussion on
this is still in progress, you can already incorporate this code into your projects. In this post, I’d like to give you an overview
of what you may expect in the next Lift releases about it and how to bring now session-aware futures to your Lift 3 and Lift 2 projects.
As an example, say that you want to lazily render a list of users. First, you execute database query asynchronously and get
Future[Seq[User]] as a result of this operation.
If you use Lift 2, incorporate
FutureBinds that I described in one of my previous posts or if you
use Lift3, import
net.liftweb.http._ and do:
1 2 3 4 5 6 7
As long as
Future[Seq[User]] does not complete,
.user-list-async-container shows a spinner. As soon as
Future completes, bindings get executed and spinner
is replaced with
There is one important limitation here. Since
userBindings calls are not executed in snippet’s thread, you don’t have an access to
Req from this method.
Why would you need it? Say that your user list has two columns. The first one is a username and the second one is a user role. User role string should be localized depending
on a language of the user seeing the list. The obvious choice is to use
S ? for this type of operation. Unfortunately,
S ? fails when no
Req is available in scope because it
can’t evaluate user’s locale. You can always overcome this by evaluating map of all possible roles and their names in advance, in snippet’s thread. However, what if you had
10 more columns in the user list, all requiring localized values? Here,
LAFutureWithSession come to the rescue.
The idea is that if you have
LiftSession available in scope creating or transforming
LAFuture, future execution thread and all chained transformation
methods’ threads will have an access to that
LiftSession. This works out of the box, all you need to do, is to create such a session/request-aware future. All other
futures created as a result of transformations like
flatMap will be also session/request-aware. Request and session will be also available in all
interface methods, like
recoverWith and so forth. The only requirement is that
LiftSession must be available in thread creating future or calling
these methods. For security reasons, initial
LiftSession are not automatically propagated to all threads processing given future – they must be available in calling code’s scope.
Since, as already said, this is not yet a part of Lift, you need to copy-paste
FutureWithSession to your project. You may also want to look at a specification for this class.
There is a similar class for
but you can’t manually incorporate it into your codebase since implementation required some changes in
LAFuture itself. In this case, you need to wait for next
Lift releases. The good thing is that you can easily transform
Future and the opposite way, so the lack of the
LAFutureWithSession in your project is not really a blocker.
Session-aware future can be created with
FutureWithSession.withCurrentSession. I’ve prepared a sample application on GitHub
demonstrating usage of this code:
1 2 3 4
In the exable above, we create session/request-aware
FutureWithSession.withCurrentSession. Method that is executed in a separate thread has an acceess to
Req, so it can
S ?. Also, code inside that
map method has access to
Req so it can call
S.request safely. This is all possible because
LiftSession are available within
snippet’s thread, future is created as session-aware with
map is called from
In case of
LAFuture you will most probably use (this is still upcoming in on of the next Lift releases)
LAFutureWithSession.withCurrentSession or even better just
Below you can find a source code of the
FutureWithSession. You can incorporate it into your project even today. I am not sure yet when this will be an official part of Lift together with
LAFuture equivalent – some discussion is still in progress, but this code is production – tested and can be safely used in your projects. I’ll post updates about an official
Lift support for this feature.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128