Lift is a free, open source web application development framework for building powerful, interactive, and dynamic applications using the Scala programming language. Scala is purely object-oriented, but, uniquely, it also has support for functional programming, giving you access to features such as anonymous functions, nested functions, curry functions, and higher-order functions. Scala runs in a Java Virtual Machine (JVM), making it compatible with Java applications and libraries. These traits mean that web applications powered by Lift can use both Scala and Java class libraries. In addition, Lift applications are packaged as Web Application Archive (WAR) files and can be deployed to any web application server that supports the Servlet 2.4 specification, including Apache Tomcat 5.5 and later.
As a web application framework, Lift encourages the development of applications that maintain a high level of security and scalability, providing users with rock solid performance and usability. By default, Lift applications are resistant to common web application vulnerabilities including cross-site scripting (XSS) attacks, cross-site request forgery, and hostile data injection.
Following are some of the features that Lift has to offer web app developers:
- World-class Comet support for developing real-time interactive push-enabled web applications
- Automatic Asynchronous JavaScript and XML (Ajax) request handling
- Site Map configurations that offer automated menus, pretty URLs, security and access control, and more
- Proper designer-friendly view templates—No application logic and programming code can be included in the static templates
- Lift apps can be deployed to a variety of application servers including Tomcat, Jetty, Glassfish, and JBoss—basically any Java web container that supports the Servlet 2.4 specification
- ORM and ActiveRecord persistence layers included out of the box
- Great support for internationalization through property bundles, localized templates, and customer resource bundle providers.
- Powerful JSON support including parsing, queries, validation, conversion, serialization, and other features
- Excellent form validation, with declarative logic that does not require working with HTTP requests directly (LiftScreen and Wizard)
- Lift makes it a breeze to provide RESTful web service APIs
- A growing library of widgets that let you include components like autocomplete fields, day/week/month view calendars, data grids, charts, and hierarchical tree controls
- Additional modules that extend Lift's feature set even further, including OAuth and OpenID
Although Lift is a relatively new web framework (version 1.0 was released in February 2009), it is already in use in some impressive large projects. Most notable is its use in the Foursquare location-oriented social network, which was ported to Lift and PostgreSQL from a PHP and MySQL configuration in late 2009. After the port, Rasmus Lerdorf famously tweeted: "Four stars to @foursquare — 1st site in a while I have taken a good look at that didn't have a single security issue (that I could find)."
Since porting to Lift, Foursquare has grown exponentially, with a reported 5 million users across the globe, checking in from any location worldwide. See the Resources section of this article for a link to a presentation given by Harry Heymann of Foursquare on his experience with developing using Lift and Scala.
Another widely used project that is powered by Lift is Novell's Vibe Cloud product, which provides enterprise social networking features, real-time collaboration and document editing facilities, file sharing, synchronization, and much more. Novell has cited Lift's excellent Comet support as one of the greatest benefits of using the framework (see Resources).
Other notable Lift users include Innovation Games, XMPie, Exchango, Snapshort, and No Fouls.
Exploring Lift 2.0's new features
Lift 2.0 and subsequent releases have delivered significant improvements and additional features over version 1.0. In this section, I will briefly highlight the new features the latest versions of the framework have to offer.
Lift 2.0 was announced on June 30, 2010, and is a significant upgrade from version 1.0. Some of the most notable enhancements include:
- Improved Comet support
- Declarative form validation and input using LiftScreen and Wizard
- JSON parsing, validation, conversion, and querying support
- Simple interface for deploying RESTful services
- Support for NoSQL databases out of the box—CouchDB and MongoDB
- Support for Simple Build Tool in addition to Maven
- JTA and LDAP support
- Ability to run applications outside of Servlet containers
Lift 2.1 was released on September 24, 2010, and brought with it the following improvements:
- Support for Scala 2.8
- Improvements in NoSQL database support
- Support for Squeryl, a Scala ORM and DSL for SQL databases
On December 15, 2010, the Lift team announced the second release candidate version, Lift 2.2. Following are just some of the highlights of this release:
- Support for Scala 2.8.1
- HTML5 support
- Automated update of dependent page elements through the Wiring feature
- Improvements to the LiftScreen and Wizard features
- CSS Selector Transforms in templates
- Improved internationalization
- Security enhancements
- Improved MongoDB support
- Imporved Squeryl integration
If you have developed a project using an MVC web application framework before, you will probably be familiar with the concept of templates or views, where the appearance and presentation tiers of the application are kept separate from the business logic and programming code. One of the aims of this architecture is to allow the design elements of a project to be worked on by designers, with little programming knowledge or work required on their part.
In truth, this is rarely the case, and many views or templates in an MVC application can end up containing quite a large amount of code. In many cases, to implement some conditional logic or iteration, some programming code is included in templates and views. In the CodeIgniter framework, for example, it is suggested that if you need to display the rows in an array, you use PHP's short syntax to do so in your views or templates. The obvious problem here is that the person working on the template needs to understand the syntax of these constructs in the relevant programming language. Another issue is that including programming code in these views makes it difficult to edit the template in a standard HTML editor or to validate the document using W3C validation tools.
An example of this issue can be seen in the template shown in Listing 1, which illustrates a typical template that needs to iterate over an array of objects. In this example, I've used the CodeIgniter and short PHP syntax mentioned previously.
Listing 1. Illustrating the logic inside template problem
<h1>Vegetables</h1>
<ul>
<?php foreach($vegetables as $vegetable): ?>
<li><?php echo $vegetable; ?></li>
<?php endforeach; ?>
</ul>
|
The obvious problem with the code in Listing 1 is that you are relying on the designer to be comfortable with some basic PHP code constructs. They could easily change some part of the PHP code that causes the entire template to break, and debugging issues that reside in logic inside of templates can be a nightmare.
Lift was built with the primary design goal that static templates do not contain ANY programming logic or symbols, ensuring that it is possible to edit templates in design tools like Dreamweaver, and that designers can pass their HTML code using validation tools. Listing 2 illustrates how the template created in Listing 1 might look in Lift.
Listing 2. Avoiding programming logic with Lift (the old way)
<lift:surround with="default" at="content">
<h1>Vegetables</h1>
<ul>
<lift:vegetables>
<li><vegetable:name /></li>
</lift:vegetables>
</ul>
</lift:surround>
|
An improvement, I'm sure you'll agree. First, there are no pesky PHP tags
or foreach constructs. The tag structure used
here will be much more familiar to designers. With that said, this
approach still suffers from the problem that it will not validate as valid
(X)HTML markup, as it uses custom tags in the
lift namespace. To validate correctly,
you would need to explicitly define this namespace, which is overkill when
you just want to create some HTML design templates.
As of version 2.2, Lift lets you use CSS class attribute values to
define how snippets should be invoked, so all Lift templates will validate
correctly without requiring the lift namespace
to be declared explicitly. Rather than using custom tags, you now use
regular valid HTML elements, so everything validates as HTML. This
approach to writing templates looks like Listing 3.
Listing 3. Valid (X)HTML templates with Lift 2.2
<div class="lift:surround?with=default;at=content">
<h1>Vegetables</h1>
<ul class="lift:vegetables">
<li><span class="name"></span></li>
</ul>
</div>
|
A little bit later, you will see how this new approach to defining templates makes it easier to write Scala snippets that bind to these templates.
By default, Lift outputs XHTML, and the content type of HTTP responses are "application/xhtml+xml" with a UTF-8 character set. Of course, there are many reasons why you may not be happy to use XHTML markup. With HTML5 emerging as the new defining standard for web application development, it is more important than ever to have options for how content will be sent to the browser.
Up until Lift 2.2, XHTML was the only option for output and input parsing.
This is still the default behavior in the current version, but at least
now you have the option to enable full HTML5 support in Lift. The various
properties that define how HTML is parsed and output in Lift are kept in
the HTMLProperties object. These properties are
docType, encoding,
contentType,
htmlOutputHeader,
htmlParser,
htmlWriter,
html5FormsSupport,
maxOpenRequests, and
userAgent. You can change any of these values
mid-session or mid-request using
LiftSession.sessionHtmlProperties and
LiftSession.requestHtmlProperties.
Alternatively, you can change the default setting to use HTML5 rather than
XHTML by adding the following LiftRule in Boot.scala:
LiftRules.htmlProperties.default.set((r: Req) =>new Html5Properties(r.userAgent)) |
When HTML5 support is switched on in this way, the standard DOCTYPE for
your pages will be the HTML5 declaration. Additionally, the Content-Type
of your responses will be text/html, and your HTML syntax will be parsed
using the nu.validator.htmlparser rather than
the standard Scala XML parser.
As anyone who has used Lift will know, Lift treats HTTP requests as
transformations of input to output, using
snippet functions to bind values to fields in a
template. In Lift 2.2 and later, you can bind snippets to the template
using CSS selectors. To see the advantages this offers, take a look
at an example of CSS selector transforms in action. First, take an
example that uses the old way of binding values to templates. Listing 4 shows a template to be used for old-style
binding.
Listing 4. Template for old-style binding
<div class="lift:surround?with=default;at=content">
<h2>A simple example</h2>
<span class="lift:example.hello">
<p>Hi there, <span class="person:name />!</p>
</span>
</div>
|
Listing 5 shows the snippet
for binding values to the template in Listing 4.
Listing 5. Snippet for binding values to template
class Example {
def hello(xhtml:NodeSeq) = {
bind("person", xhtml, "name" -> "Joe")
}
}
|
In Listing 5, the hello function binds to the
person:name element, replacing the contents
with value Joe. The end result would be output like that shown in Listing 6.
Listing 6. Output result from above Snippet
<div>
<h2>A simple example</h2>
<span>
<p>Hi there, Joe!</p>
</span>
</div>
|
Let's make a slight amendment to the template, this time simply giving the
value you want to replace with output an ID
attribute (see Listing 7).
Listing 7. Modified template with
ID attribute
<div class="lift:surround?with=default;at=content">
<h2>A simple example</h2>
<span class="lift:example.hello">
<p>Hi there, <span id="name" />!</p>
</span>
</div>
|
Now let's use CSS selector transforms to render my name into the element
with the ID attribute
name (see Listing 8).
Listing 8. Modified snippet using CSS ID selector transform
class Example {
def render = "#name" #> "Joe"
}
|
The result of Listing 8 should be identical to Listing 6. In this example, you are using the CSS ID selector, but you can also use various other selectors. Table 1 shows some examples.
Table 1. CSS Selector Transform examples
| Selector | Template | Output |
|---|---|---|
"#name" #> "Joe"
|
<span id="name" />
|
Joe
|
"#name *" #> "Joe"
|
<span id="name" />
|
<span id="name">Joe</span>
|
"#name [rel]" #> "friend"
|
<span rel="" id="name">Joe</span>
|
<span rel="friend" id="name">Joe</span>
|
".highlight" #> (n: NodeSeq) => n ("style", "color: red")
|
<span class="highlight">Joe</span>
|
<span class="highlight" style="color: red">Joe</span>
|
"href=# [href]" #> "about:blank"
|
<a href="#">Link</a>
|
<a href="about:blank">Link</a>
|
As you can see, the left side of the CSS selector transform defines the selector to use and the replacement rule to use. You can use any of the following CSS selectors:
- ID (for example,
#name) will select the element with the ID name - Class (for example,
.highlight) will select all elements with the class name highlight - Attribute value (for example,
href=#) will select all elements with the attributehrefset to a value #
The replacement rules tell Lift what it should replace in any matching elements. You can use any of the following options:
- Using no replacement rule will replace the entire matching elements
*will replace the inner content of the matching elements[href]will replace the value of the href attribute of the matching elements
The right side of the transform defines what values should be used when replacing the template elements. This can be one of several types:
StringconstantNodeSeqconstantNodeSeq=>NodeSeqtransform function-
Bindable StringPromotableconstantIterableConst
CSS selector transforms offer a powerful and shorthand alternative to Lift's original template binding syntax and will probably make more sense to developers who have worked with CSS selectors (for example, developers who have used JavaScript libraries such as jQuery or Dojo).
Lift 2.0 introduces LiftScreen and Wizard, two concepts that offer a radically improved method of handling web forms in terms of validation and state management. Any web developer will have experience working with traditional web form handling—you have a client-side form, perhaps with some JavaScript validation, and then you process it and validate it on the server side. If there is a problem, your application responds as such and you start again. This is quite a tedious process; primarily because of the amount of work you need to do with making and responding to HTTP requests.
LiftScreen and Wizard aim to simplify the process of form handling by providing the following features:
- Validate your forms without directly using HTTP
- Validate your forms declaratively
- Automatic state management
- Browser history management (no broken Back buttons)
- Strongly typed form elements
LiftScreen provides for single-form input handling and validation, whereas Wizard provides for multipage forms, where you might navigate between sections of a form using Next and Previous buttons, with each stage validated as you go. Lift Wizards are actually a collection of Screens, with logic to determine which order they should appear in. For example, if you wanted to have different screens display based on the user's input in one screen, you can do so using Wizards.
Let's take a quick look at a very simple LiftScreen in action in Listing 9.
Listing 9. LiftScreen basics
object WhatsMyName extends LiftScreen {
val name = field(S ? "Please enter your name", "",
valMinLen(1, "Name is a mandatory field"))
def finish() {
S.notice("Hello, "+name.is+"!")
}
}
|
You could then add the screen in Listing 9 to a Lift template as follows:
<div class="lift:WhatsMyName" /> |
The concept behind Wizards is very similar to the LiftScreen, except that you can have multiple screens. Listing 10 is an example where you have one screen to enter your name, then a second screen to enter your company.
Listing 10. Wizard basics
object PersonWizard extends Wizard {
val screen1 = new Screen {
val name = new Field with StringField {
def title = S ?? "Please enter your name"
}
}
val screen2 = new Screen {
override def screenTop = <div>Hello {page1.name}!</div>
val company = new Field with StringField {
def title = S ?? "Please enter company name"
}
}
val screen3 = new Screen {
override def screenTop = <div>Hello {page1.name} who works in
{page2.company}!</div>
}
}
|
LiftScreen and Wizard are probably the elements of Lift (well, maybe aside from Comet) that I am most excited about for the future. The Lift demos page contains some good examples of Wizards, and the Lift wiki has some detailed information about creating LiftScreens.
JSON (JavaScript Object Notation) is a lightweight data interchange format that is becoming extremely popular in modern software development, particularly in the development of web applications. With excellent cross-language implementation support and its ability to be read natively by modern web browsers, people are often turning to JSON where they may previously have used XML.
Lift 2.0 introduced lift-json, a new library for
working with JSON data. The features available in this library
include:
- JSON parsing
- LINQ-style JSON queries
- Serialization
- Pretty JSON printing
- Converting between JSON and XML
- Manipulation using XPath-style expressions
- Support for Merging and Diffing two JSON expressions
The lift-json library comes as part of the Lift
framework, but is actually a stand-alone project that can be included in
other Scala projects that don't use Lift. The project can be forked on
Github and includes an excellent readme, which explains the library in
great detail (see Resources).
Let's take a look at some examples of how
lift-json makes working with JSON data easier.
First, let's take some Scala types and create a JSON string from them:
val json = JsonAST.render(List(1, 2, 3, 4, 5)) |
This statement would result in the json value containing the following
string:
[1,2,3,4,5] |
So the Scala list has been mapped to a JSON array. What about JSON objects? Those are easy too, thanks to the ~ operator in Scala.
Listing 11. Mapping the Scala list to a JSON array
val obj = ("name" -> "Joe Lennon") ~ ("company" -> "Core International")
~ ("email": "joe@joelennon.ie")
val json = JsonAST.render(obj)
|
This time, JSON would contain the following string:
{"name":"Joe Lennon","company":"Core International","email":"joe@joelennon.ie"} |
As you can see, it's pretty easy to convert to JSON, but what about the
other way around? Let's take the first example and turn it around. Let's
say you have the string [1,2,3,4,5] and you want
to create a List from it. You can use the lift_json
parse function to do just that:
val obj = parse("""[1, 2, 3, 4, 5]""") |
This produces a JArray object, which contains a
List of the items in the given JSON array. This could be denoted as
follows:
JArray(List(JInt(1), JInt(2), JInt(3), JInt(4), JInt(5))) |
For further information on lift-json, see the Resources section to get a link to the
readme file on Github.
Lift can work with various database systems, including traditional relational DBs like PostgreSQL, MySQL, SQL Server, and Apache Derby. Lift 2.1 includes native support for Squeryl, an Object-Relational Mapping (ORM) framework for Scala, providing direct integration with Lift's Mapper and Record features.
In recent times, there has been a steady increase in interest in new database management systems that are non-relational or don't use the Structured Query Language (SQL) to interact with the database. Two of the most popular "NoSQL" databases are MongoDB and CouchDB—document-oriented databases that store data in JSON-like object constructs, with all data self-contained in the majority of cases. For more information on the benefits (and pitfalls) of these databases, see the articles "Exploring MongoDB" and "Exploring CouchDB," which provide a detailed introduction to these emerging open source projects (see Resources for links). Now take a brief look at how Lift 2.0 lets you communicate directly with a MongoDB and CouchDB database.
Lift 2.0's MongoDB support is available through two components,
lift-mongodb and lift-mongodb-record. The main code and MongoDB driver is
contained in the lift-mongodb library, which lets you directly
communicate with the database at a low level, providing for manual
document and database creation and management. The lift-mongodb-record
provides an implementation of the Record framework for the MongoDB
database. Let's take a look at some basic commands to work with the
MongoDB driver.
To define a default database to use, you can use the following command:
MongoDB.defineDb(DefaultMongoIdentifier, MongoAddress(MongoHost("localhost", 27017), "my_database"))
Next, let's connect to this database; create a document and save it in a collection (see Listing 12).
Listing 12. Working with MongoDB
MongoDB.use(DefaultMongoIdentifier) ( db => {
val doc = new BasicDBObject
doc.put("name", "Joe Lennon")
doc.put("company", "Core Intrernational")
doc.put("email", "joe@joelennon.ie")
val coll = db.getCollection("people")
coll.save(doc)
})
|
You can use the MongoDocument library to create object classes that will be saved as documents in the database. First, you need to define the class, as shown in Listing 13.
Listing 13. Defining the Person record structure
case Class Person(_id: String, name: String, company: String,
email: String) extends MongoDocument[Person] {
def meta = Person
}
object Person extends MongoDocumentMeta[Person] {
override def mongoIdentifier = DefaultMongoIdentifier
override def collectionName = "people"
}
|
Now, you can create a document of this type, as shown in Listing 14.
Listing 14. Creating a person document
val person1 = Person(
ObjectId.get.toString,
"Joe Lennon",
"Core International",
"joe@joelennon.ie"
)
|
To save the document, simply call the save function:
person1.save |
You can retrieve documents from the database using the find function. To retrieve the above document, you could use:
val person1Copy = Person.find(person1._id) |
To delete the document, you can use the following command:
person1.delete |
For more information on working with MongoDB documents and for details on
how to work with the lift-mongodb-record
component, refer to the Lift documentation (see Resources).
Lift's CouchDB support comes through a driver that automatically handles the HTTP requests and responses required to interact with CouchDB's RESTful interface. Let's get started and take a look at how you can connect to a CouchDB database (see Listing 15).
Listing 15. Connecting to a CouchDB database
val db = new Database("my_database")
db createIfNotCreated(new Http())
CouchDB.defaultDatabase = db
|
Listing 15 creates a CouchDB database object, and creates the physical
database itself if it doesn't exist. It then tells CouchDB to use this
database. Next, define a record structure for the
Person object, like you did in the section on
MongoDB (see Listing 16).
Listing 16. Defining the Person record structure
class Person extends CouchRecord[Person] {
def meta = Person
object name extends StringField(this, 100)
object company extends StringField(this, 200)
object email extends StringField(this, 255)
}
object Person extends Person with CouchMetaRecord[Person] {
def createRecord = new Person
}
|
You can now create a person object, give it values for the three properties
(name, company, and
email), and save it to the database, as shown in
Listing 17.
Listing 17. Using the
Person structure to save data to CouchDB
val person1 = Person.createRecord.name("Joe Lennon")
.company("Core International").email("joe@joelennon.ie")
person1 save
|
You can easily change an attribute's value on the fly. For example, if I
wanted to set the name of person1 to
Joseph Lennon, I could use the code shown
in Listing 18.
Listing 18. Setting an attribute's value on the fly
person1.name.set("Joseph Lennon")
person1 save
|
Querying data in CouchDB works in quite a unique way, basically using a set
of permanent Map/Reduce view functions stored
in design documents in the database itself (ad-hoc querying is possible,
but is much slower). My book, Beginning CouchDB features a
detailed overview of Map/Reduce and CouchDB views (see Resources for a link). Let's use Lift to create
a design document for querying the documents now (see Listing 19).
Listing 19. Creating a CouchDB view design document
val design_doc: JObject =
("language" -> "javascript") ~
("views" -> (("all_people"-> ("map" -> "function(doc)
{ if(doc.type === 'Person') { emit(doc._id, doc); } }"))))
Http(database.design("my_design_doc") put design_doc)
|
The code in Listing 19 will basically create a CouchDB view that returns all documents
with the type attribute value Person, indexed
by the _id attribute. This view will be kept in
the design document named my_design_doc. You can then use this view as
follows:
val results = Person.queryView("my_design_doc", "all_people") |
For information on setting up your Lift application to use the CouchDB driver, and for more detailed instructions on its use, refer to the Lift wiki.
This article outlined the new features and enhancements in version 2.0 of the Lift web application development framework. First, you learned what Lift is and the general features that it provides. You then discovered the new features specific to versions 2.0, 2.1, and 2.2-RC1 of Lift. Finally, the article provided detailed analysis of some of these new features, including the improvements to the template system; inclusion of support for HTML5, JSON, and NoSQL databases; and other features like LiftScreen, Wizard, and Wiring. Hopefully, the article has inspired you to go further and learn more about this brilliant open source web framework.
Learn
- Visit the official site for Lift.
-
"Build Comet applications using Scala, Lift, and jQuery"
(developerWorks, March 2009) explains how to build a real-time web
auction using these technologies.
-
"Give Apache Geronimo a Lift" (developerWorks, July
2008) shows how to create a web application using Lift and deploy it to
Geronimo.
-
"The busy Java developer's guide to Scala: Functional programming for
the object oriented" (developerWorks, January 2008) provides
details about Scala.
-
"Scala and
XML" (developerWorks, April 2008) explains how to use
Scala to navigate and process parsed XML.
- Read Exploring
Lift by Derek Chen-Becker, Marius Danciu and Tyler Weir from the
Lift site.
- Visit the Lift wiki.
-
It's Chat App Time: Learn
how to create a Comet-enabled chat application using Lift.
- Learn about the new features in Lift 2.2-RC2.
- Learn about Scala Lift
from David Pollak, author of Beginning Scala.
- See a slide presentation on foursquare.com's use of Scala and Lift.
-
Novell's Vibe cloud
service was also created using Scala/Lift.
- Visit the official MongoDB site.
- Learn more about the MongoDB Map/Reduce
functions.
- The MongoDB Cookbook provides
guidance on all the common ways of using MongoDB.
- The
lift-jsonlibrary comes as part of the Lift framework, but is actually a stand-alone project that can be included in other Scala projects that don't use Lift. The project can be forked on Github and includes an excellent readme, which explains the library in great detail. -
"Exploring CouchDB" (developerWorks, March 2009) explains how
Apache's open source CouchDB offers a new method of storing data, in what
is referred to as a schema-free document-oriented database model.
- The developerWorks Web Development zone
specializes in articles covering various web-based solutions.
Get products and technologies
- Get Lift.
Discuss
- Create your developerWorks profile today and set up a watchlist on Lift.
Get connected and stay connected with developerWorks community.
- Find other developerWorks members interested in web development.
- Share what you know: Join one of our developerWorks groups focused on web topics.
- Roland Barcia talks about Web 2.0 and middleware in his blog.
- Follow developerWorks' members' shared bookmarks on web topics.
- Get answers quickly: Visit the Web 2.0 Apps forum.
- Get answers quickly: Visit the Ajax forum.

Joe Lennon is a 25-year-old mobile and web application developer from Cork, Ireland. Joe works for Core International, where he leads the development of Core's mobile HR self service solutions. Joe is also a keen technical writer, having written many articles and tutorials for IBM developerWorks on topics such as DB2 pureXML, Flex, JavaScript, Adobe AIR, .NET, PHP, Python and much more. Joe's first book, Beginning CouchDB was published in late 2009 by Apress. In his spare time, Joe enjoys travelling, reading and video games.




