import Helpers._
10
11
// our snippet
12
object TimeNow {
13
// create a function (NodeSeq => NodeSeq)
14
// that puts the current time into the
15
// body of the incoming Elem
16
def render = "* *" #> now.toString
17
}
This snippet must be in the snippet package so Lift knows how to find it by convention.
It is an object which is a singleton because the snippet has no state.
Lift calls the render method on a snippet unless you specify another method when you invoke
your snippet.
The snippet generates a function, NodeSeq => NodeSeq, that uses Lift’s CSS Selector Trans-
forms (See 7.10 on page 85) to insert the current time into the body of all HTML Elements: def
render = "* *" #> now.toString
13.5
Getting Ajaxy
The ClickMe snippet is a little more complex, but it demonstrates, especially on the “Second
Page” the power of Lift’s View First in which no particular component on the page is the dominant
component. Here’s the ClickMe code:
Listing 13.3: ClickMe.scala
1
// make sure this is the snippet package so Lift
2
// can find the snippet
3
package code
114
CHAPTER 13. FROM MVC
4
package snippet
5
6
// some inputs
7
import net.liftweb._
8
import util._
9
import Helpers._
10
import http._
11
import js.JsCmds._
12
13
// our snippet
14
object ClickMe {
15
// variables associated with the request
16
private object pos extends RequestVar(0)
17
private object cnt extends RequestVar(0)
18
19
// create a function (NodeSeq => NodeSeq)
20
// set the onClick method of the button
21
def render = {
22
// capture our position on the page
23
val posOnPage = pos.set(pos.is + 1)
24
25
"button [onclick]" #>
26
SHtml.ajaxInvoke(() => {
27
cnt.set(cnt.is + 1) // increment the click count
28
Alert("Thanks pos: "+posOnPage+
29
" click count "+cnt)
30
})
31
}
32
}
We define two RequestVars that hold request-scoped values. For Lift, the scope of a request is
the initial full HTML page load plus any Ajax requests associated with that page.
When the snippet’s render method is called, we capture the current value for the pos Request-
Var.
The snippet associates the invocation of an Ajax call with the button’s onclick method. When
the button is clicked, the function is invoked.
The function closed over the scope of the position of the button on the page. The buttons all share
the cnt RequestVar and thus for a single page load, the number of button-presses are counted.
If you have 5 different browser tabs open to the same page, each tab will have a unique page
count.
This demonstrates the component nature of Lift and why having complex items on a page means
not having a front-controller, but having lots of behaviors associated with lots of HTML elements.
13.6
Next Steps
If you want to see more of Lift’s snazzy Ajax and Comet, check out 2 on page 5. If you want to see more of the basics of SiteMap and snippets, check out 3 on page 11. If you want to see how Lift
does forms, check out 4 on page 27.
Part II
Recipes
115
Chapter 14
Dynamic html tables created from
DB.runQuery()
14.1
Problem
What I’m trying is:
1. query the SQL server via DB.runQuery()
2. put the result (multiple, rows and columns) into a Table structure like this:
1
<table>
2
<thead>
3
<tr><th></th></tr>
4
</thead>
5
<tbody>
6
<tr><td></td></tr>
7
</tbody>
8
</table>
14.2
Solution
The DB.runQuery(sql_query_string) method returns (List[String], List[List[String]]), to put that in
a table, your view looks like:
1
<table class="lift:MySnippet">
2
<thead>
3
<tr><th id="my_th">Field Name</td></tr>
4
</thead>
5
<tbody>
6
<tr id="my_tr"><td>An item</td></tr>
7
</tbody>
8
</table>
And your snippet uses CSS Selector Transforms (See Section 7.10) and looks like:
117
118
CHAPTER 14. DYNAMIC HTML TABLES CREATED FROM DB.RUNQUERY()
1
object MySnippet {
2
def render = {
3
val (fieldNames: List[String], fieldValues: List[List[String]]) = DB.runQuery(...)
4
5
"#my_th *" #> fieldNames &
6
"#my_tr *" #> fieldValues.map(values => "td *" #> values)
7
}
8
}
Chapter 15
Dynamically choosing content
15.1
Problem
I want to to keep design completely separated from logic and I am bit stuck. I have a page that
loads different pieces of html depending on some variables and it also has some ajax code so it may
load new pieces of html. So far, that page uses only one snippet that has the logic to decide what
html should be loaded. So here is the question, how should the snippet get an only-with-design
piece of html to bind data to it.
15.2
Solution
Snippets are evaluated recursively... this means that you can return markup from a snippet that
contains other snippets.
The other thing to pay attention to is the <lift:embed> snippet (See Section 9.13).
Combining the two:
Main page:
1
<html><body> Stuff here
2
<div class="lift:ChooseBehavior">Different behavior will go here</div>
3
</body></html>
The snippet:
1
object ChooseBehavior {
2
def render = someState match {
3
case ShowData => <lift:embed what="_showData" />
4
case EditData => <lift:embed what="_editData" />
5
case AjaxThing => <lift:embed what="_ajaxThing" />
6
}
7
}
Then your designer need only edit the main page and each of the templates, and then you wire
them together.
119
120
CHAPTER 15. DYNAMICALLY CHOOSING CONTENT
Chapter 16
Ajax Forms
121
122
CHAPTER 16. AJAX FORMS
Chapter 17
Protecting REST APIs
17.1
Problem
I want to expose part of my site as authenticated REST, but with custom authentication (not the
HTTP based authentication).
Right now, I’m thinking of using a custom dispatch, but that means I’ll have to check every request
in the request handler itself to see if it is authenticated, right?
Authentication is just a SessionVar on the server, so it also implies I need a way to pass the session
identifier back and forth between the REST client and the service. If it were a cookie I think it
would be transparent, but I think Lift adds te session ids to the URLs (at least that’s what I see in
my address bar).
So, assuming I have a public "login" REST call that sets a SessionVar, how do I pass this transar-
ently to the REST client? I have thought about a token system as well, but that seems like copying
the session system.
Any suggestions?
17.2
Solution
If you’ve got a:
1
object MyService extends RestHelper {
2
....
3
}
And:
1
val ensureSession: PartialFunction[Req, Unit] = {
2
case _ if isLoggedIn =>
3
}
then in Boot:
123
124
CHAPTER 17. PROTECTING REST APIS
1
import net.liftweb.util.Helpers._
2
3
LiftRules.dispatch.append(ensureSession guard MyService)
This is a simple way to compose PartialFunctions and put a guard around all the elements
of a PartialFunction.
Chapter 18
URI-based locale selection
18.1
Problem
I’m evaluating Lift and one thing I miss, or cannot see how toimplement, is the ability to have the
locale determined from an URI-pattern. In Struts2 I have:
1
namespace="/{request_locale}"
So I can have an action (restful) invoked on an URI=/no/companies/company/1 and it will call
my CompanyAction with id=1 and the locale
set to no If called from URI=/en/companies/company/1 it will callthe same CompanyAction
but the locale will be set to "en".
So my question is: Is it possible to teach Lift to retrieve the locale based on some uri-pattern, so
that it will try to resolve my *.xhtml after the /{request_locale} part?
/no/index.xhtml
/en/index.xhtml
Should then map to the same templates but with different locale.
18.2
Solution
This is an ideal use of URL rewriting.
You have to hook up the module in Boot.scala with: UrlLocalizer.init().
You can see a complete runnable example at DPP’s GitHub Starting Point.
Here’s the code:
125
126
CHAPTER 18. URI-BASED LOCALE SELECTION
1
package code
2
package lib
3
4
import net.liftweb._
5
import http._
6
import provider._
7
import common._
8
9
import java.util.Locale
10
11
object UrlLocalizer {
12
// capture the old localization function
13
val oldLocalizeFunc = LiftRules.localeCalculator
14
15
/**
16
* What are the available locales?
17
*/
18
val locales: Map[String, Locale] =
19
Map(Locale.getAvailableLocales.map(l => l.toString -> l) :_*)
20
21
object currentLocale extends RequestVar(Locale.getDefault)
22
23
/**
24
* Extract the locale
25
*/
26
def unapply(in: String): Option[Locale] =
27
if (currentLocale.set_?) None // don't duplicate
28
else locales.get(in) // if it's a valid locale, it matches
29
30
/**
31
* Calculate the Locale
32
*/
33
def calcLocale(in: Box[HTTPRequest]): Locale =
34
if (currentLocale.set_?) currentLocale.get
35
else oldLocalizeFunc(in)
36
37
/**
38
* Initialize the locale
39
*/
40
def init() {
41
// hook into Lift
42
LiftRules.localeCalculator = calcLocale
43
44
// rewrite requests with a locale at the head
45
// of the path
46
LiftRules.statelessRewrite.append {
47
case RewriteRequest(ParsePath(UrlLocalizer(locale) :: rest,
48
_, _, _), _, _) => {
49
currentLocale.set(locale)
50
RewriteResponse(rest)
51
}
52
}
53
}
54
}
Chapter 19
Embedding JavaScript in an HTML page
19.1
Problem
What am I doing wrong? I’m trying to output a javascript object into the page (so my front end
guy can do some stuff with the data without parsing it out of elements by id) but it’s replacing all
the double quotes with " (only in view source - if I inspect it then firebug converts them to
double quotes again)
I’ve copied the example from EXPLORING LIFT, but it still does the same:
1
& ".data_as_object *" #> {
2
JsCrVar("myObject", JsObj(("persons", JsArray(
3
JsObj(("name", "Thor"), ("race", "Asgard")),
4
JsObj(("name", "Todd"), ("race", "Wraith")),
5
JsObj(("name", "Rodney"), ("race", "Human"))
6
))))
Becomes:
1
<div class="data_as_object" style="display: none;">var myObject =
2
{"persons": [{"name": "Thor",
3
"race": "Asgard"}, {"name":
4
"Todd", "race": "Wraith"},
5
{"name": "Rodney", "race":
6
"Human"}]
7
};</div>
I’ve noticed that if what I’m outputting is a number rather than a string then it’s fine.
19.2
Solution
Try:
1
& ".data_as_object *" #> {
2
Script(JsCrVar("myObject", JsObj(("persons", JsArray(
127
128
CHAPTER 19. EMBEDDING JAVASCRIPT IN AN HTML PAGE
3
4
JsObj(("name", "Thor"), ("race", "Asgard")),
5
JsObj(("name", "Todd"), ("race", "Wraith")),
6
JsObj(("name", "Rodney"), ("race", "Human"))
7
)))))
JsExp are also Nodes, so they render out, but they render out escaped. Putting Script() around
them turns them into:
1
<script>
2
// <![CDATA[
3
....
4
]]>
5
</script>
Part III
Questions and Answers
129
Chapter 20
Scaling
Lift is a web framework built on the Scala programming language. Lift takes advantage of many
of Scala’s features that allow developers to very concisely code secure, scalable, highly interactive
web applications. Lift provides a full set of layered abstractions on top of HTTP and HTML from
"close to the metal" REST abstractions up to transportation agnostic server push (Comet) support.
Scala compiles to JVM byte-code and is compatible with Java libraries and the Java object model.
Lift applications are typically deployed as WAR files in J/EE web containers... Lift apps run in
Tomcat, Jetty, Glassfish, etc. just like any other J/EE web application. Lift apps can generally
be monitored and managed just like any Java web app. Web Applications, Sessions, and State.
All web applications are stateful in one way or another. Even a "static" web site is made up of
the files that are served... the application’s state is defined in those files. The site content may
be served out of a database, but the content served does not depend on identity of the user or
anything about the HTTP request except the contents of the HTTP request. These contents can
include the URI, parameters, and headers. The complete value of the response can be calculated
from the request without referencing any resources except the content resources. For the purpose
of this discussion, I will refer to these as session-less requests. News sites like the UK Guardian,
MSNBC, and others are prototypical examples of this kind of site. Sessions. Some applications
are customized on a user-by-user basis. These applications include the likes of Foursquare and
others where many HTTP requests make up a "session" in which the results of previous HTTP
requests change the behavior of future HTTP requests. Put in concrete terms, a user can log into
a site and for some duration, the responses are specific to that user. There are many mechanisms
for managing sessions, but the most common and secure method is creating a cryptographically
unique token (a session id), and putting that token in the Set-Cookie response header such that
the browser will present that Cookie in subsequent HTTP requests for a certain period of time.
The server-side state is referenced by the Cookie and the state is made available to the web appli-
cation during the scope of servicing the request and any mutations the web app makes to session
state during the request are kept on the server and are available to the application in subsequent
requests. Another available technique for managing state is to serialize application state in the
Cookie and deliver it to the browser such that the server is not responsible for managing state
across requests. As we’ve recently discovered, this is a tremendously insecure way to manage
application state. Further, for any moderately complex application, the amount of data the needs
to be transferred as part of each request and response is huge. Migratory Sessions. Many web
application managers allow for server-managed sessions to migrate across a cluster of web appli-
cation servers. In some environments such as Ruby on Rails, this is a hard requirement because
131
132
CHAPTER 20. SCALING
only one request at a time can be served per process, thus for any moderate traffic site, there
must be multiple processes serving pages. There are many strategies for migrating state across
processes: storing state on disk, in memcached, in a database (relational or NoSQL), or having
some proprietary cluster communications protocol. In any of these scenarios sessions can migrate
across the grid of processes serving requests for a given web application. Web applications that
support migratory state are often referred to as "stateless" because the session state does not re-
side in the same process as the web application. Session Affinity. Some applications require that
all requests related to a particular session are routed to the same process and that process keeps
session-related content in local memory. In a cluster, there are multiple mechanisms for achiev-
ing session affinity... the two most popular being HAProxy and Nginx. Availability, Scalability,
Security, Performance, and User Experience. There are many vectors on which to measure the
overall-quality of a web application. Let’s take a quick peek at each one. Availability. Avail-
ability of an application is the amount of time it gives a meaningful response to a request. Highly
available applications generally span multiple pieces of hardware and often multiple data centers.
Highly available applications are also typically available during upgrades of part of the system
that makes up the application. Highly available applications have very few single points of failure
and those single points of failure are usually deployed on very reliable hardware. Scalability. A
scalable application can, within certain bounds, respond with similar performance to increased
load by adding hardware to process more load. No system is infinitely or linearly scalable. How-
ever, many systems have grossly disproportionate load demands such that, for example, you can
add a lot of web application front-ends to a Rails application before there’s enough load on the
back-end RDBMS such that scaling is impaired.
Security. The Internet is a dangerous place and no request that is received from the Internet can
be trusted. Applications, frameworks, systems and everything else must be designed to be se-
cure and resist attacks. The most common attacks on web application are listed in the OWASP
Top Ten. Performance. Web application performance can be measured on two vectors: response
time to a request and system resources required to service the request. These two vectors are
inter-dependent. User Experience. The user experience of a web app is an important measure of
its quality. User experience can be measured on many different vectors including perceived re-
sponsiveness, visual design, interactivity, lack of "hicups", etc. Ultimately, because we’re building
applications for users, the user experience is very important. Lift’s trade-offs. Given the number
and complexity related to the quality of a web application, there are a lot of trade-offs, implicit
and explicit, to building a framework that allows developers and business people to deliver a
great user experience. Let’s talk for a minute about what Lift is and what it isn’t. Lift is a web
framework. It provides a set of abstractions over HTTP and HTML such that developers can write
excellent web applications. Lift is persistence agnostic. You can use Lift with relational databases,
file systems, NoSQL data stores, mule carts, etc. As long as you can materialize an object into
the JVM where Lift is running, Lift can make use of that object. Lift sits on top of the JVM. Lift
applications execute in the Java Virtual Machine. The JVM is a very high performance computing
system. There are raging debates as to the relative performance of JVM code and native machine
code. No matter which benchmarks you look at, the JVM is a very fast performer. Lift apps take
advantage of the JVM’s performance characteristics. Moderately complex Lift apps that access the
database can serve 1,000+ requests per second on quad-core Intel hardware. Even very complex
Lift apps that make many back-end calls per request can serve hundreds of requests per second on