text:
Lift Cookbook
The Lift Cookbook is available in PDF, ePub, DAISY, and Kindle format, direct from O'Reilly, and can also be found at Amazon and other bookstores.
This is a collection of solutions to questions you might have while developing web applications with the Lift Web Framework.
The aim is to give a single, short answer to a specific question. When there are multiple approaches, or styles, we'll give you one solution, but will point you at alternatives in the discussion.
[InstallAndRunning] will get you up and running with Lift, but in other respects, this cookbook is aimed at practitioners and the questions they have asked. If this is the first time you've heard of Lift, you'll want to look at:
Torsten Uhlmann's Instant Lift Web Applications How-to (PACKT
Timothy Perrett's Lift in Action (Manning Publications)
I've mined the Lift mailing list for these recipes, but I'm not the only one. Recipes have been contributed by:
Jono Ferguson, who's a Scala consultant based in Sydney, Australia. He can be found lurking on the Lift mailing list and occasionally helps out with Lift modules. Find him at https://twitter.com/jonoabroad and http://underscoreconsulting.com.
Franz Bettag, who's been an enthusiastic Scala hacker for several years now. He joined the Lift team in January 2012 and actively tweets and blogs about his newest Scala adventures. Find him at https://twitter.com/fbettag.
Marek Żebrowski.
Peter Robinett, who's a web and mobile developer and a Lift committer. He can be found on the Web and on Twitter.
Kevin Lau, who's a founder of a few web apps with a focus in AWS cloud, iOS, and Lift.
Tony Kay.
Chenguang He.
You should join them: [AddRecipe] tells you how.
The text of this cookbook is at https://github.com/d6y/lift-cookbook.
You'll find projects for each chapter on GitHub.
Follow @LiftCookbook on Twitter.
Software Versions
Except where otherwise indicated, the examples use Lift 2.6 with SBT
0.13 and
Conventions Used in This Book
The following typographical conventions are used in this book:
- Italic
Indicates new terms, URLs, email addresses, filenames, and file extensions.
- Constant width
Used for program listings, as well as within paragraphs to refer to program elements such as variable or function names, databases, data types, environment variables, statements, and keywords.
- Constant width bold
Shows commands or other text that should be typed literally by the user.
- Constant width italic
Shows text that should be replaced with user-supplied values or by values determined by context.
This icon signifies a tip, suggestion, or general note.
This icon indicates a warning or caution.
Using Code Examples
This book is here to help you get your job done. In general, if this book includes code examples, you may use the code in this book in your programs and documentation. You do not need to contact us for permission unless you're reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing a CD-ROM of examples from O'Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product's documentation does require
We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: "Lift Cookbook by Richard Dallaway (O'Reilly). Copyright 2013 Richard Dallaway, 978-1-449-36268-3."
If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at
Safari® Books Online
Technology professionals, software developers, web designers, and business and creative professionals use Safari Books Online as their primary resource for research, problem solving, learning, and certification training.
Safari Books Online offers a range of
How to Contact Us
Please address comments and questions concerning this book to the publisher:
We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at http://oreil.ly/lift-cookbook.
To comment or ask technical questions about this book, send email to
For more information about our books, courses, conferences, and news, see our website at http://www.oreilly.com.
Find us on Facebook: http://facebook.com/oreilly
Follow us on Twitter: http://twitter.com/oreillymedia
Watch us on YouTube: http://www.youtube.com/oreillymedia
These recipes exist because of the many contributions on the Lift mailing list, where Liftafarians, as they are known, generously give their time to ask questions, put together example projects, give answers, share alternatives, and chip in with comments. Thank you.
I am indebted to the contributors who have taken the trouble to write new recipes, and to those who have provided corrections and suggestions.
You'll see I've repeatedly referenced the work of Antonio Salazar Cardozo, Diego Medina, Tim Nelson, David Pollak, and Dave Whittaker. These are fantastic communicators: thank you guys.
It's been a pleasure working with the O'Reilly team, and they have immensely improved the text. Thank you, especially Meghan Blanchette, Kara Ebrahim, and Kiel Van Horn.
Many thanks to Jono for all the encouragement and help.
To Jane, Mum, Dad: thank you. It's amazing what you can do with a supportive family.
Installing and Running Lift
This chapter covers questions regarding starting development with Lift: running a first Lift application and setting up a coding environment. You'll find answers regarding production deployment in [deployment].
Downloading and Running Lift
You want to install and run Lift on your computer.
The only prerequisite for installing and running Lift is to have Java 1.7 or later installed. Instructions for installing Java can be found at http://java.com/.
You can find out if you have Java from the shell or command prompt by asking for the version you have installed:
$ java -version java version "1.7.0_13" Java(TM) SE Runtime Environment (build 1.7.0_13-b20) Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)
Once you have Java, the following instructions will download, build, and start a basic Lift application.
For Mac and Linux
Visit http://liftweb.net/download and download the most recent Lift 2.6 ZIP file.
Unzip the file.
Start Terminal or your favourite shell tool.
Navigate into the unzipped folder and into the scala_211 subfolder and then into the lift_basic folder.
Run ./sbt.
Required libraries will be downloaded automatically.
At the SBT prompt (>), type container:start.
Open your browser and go to http://127.0.0.1:8080/.
When you're done, type exit at the SBT prompt to stop your application from running.
For Windows
Visit http://liftweb.net/download and locate the link to the most recent ZIP version of Lift 2.6 and save this to disk.
Extract the contents of the ZIP file.
Navigate in Explorer to the extracted folder, and once inside, navigate into scala_211 and then lift_basic.
Double-click sbt.bat to run the build tool; a Terminal window should open.
Some versions of windows will display a warning that the SBT "publisher could not be verified". Click "Run" if this happens.
Required libraries will be downloaded automatically.
At the SBT prompt (>), type container:start.
You may find Windows Firewall blocking Java from running. If so, opt to "allow access."
Start your browser and go to http://127.0.0.1:8080/.
When you're done, type exit at the SBT prompt to stop your application from running.
Expected result
The result of these commands should be a basic Lift application running on your computer, as shown in [LiftBasicScreenshot].
Lift isn't installed in the usual sense of "installing software." Instead, you use standard build tools, such as SBT or Maven, to assemble your application with the Lift framework. In this recipe, we downloaded a ZIP file containing four fairly minimal Lift applications, and then started one of them via the build tool.
Simple Build Tool
Typing sbt starts a Simple Build Tool used by Scala projects (it's not specific to Lift). SBT will check the project definition and download any libraries required, which will include the Lift framework.
This download happens once, and the downloaded files are stored on disk in .ivy2 under your home folder.
Your application build is configured by build.sbt. Looking inside, you'll see:
Basic information about your application, including a name and version
Resolvers, which inform SBT where to fetch dependencies from
Settings for plugins and the Scala compiler
A list of dependencies required to run your application, which will include the Lift framework
Running your application
The SBT command container:start starts the web server on the default port of 8080 and passes requests to your Lift application. The word container refers to the software you deploy your application into. There are a variety of containers (Jetty and Tomcat are probably the best known) all of which conform to a standard for deployment. The upshot is you can build your application and deploy to whichever one you prefer. The container:start command uses Jetty.
Source code
The source code of the application resides in src/main/webapp and src/main/scala. If you take a look at index.html in the webapp folder, you'll see mention of data-lift="helloWorld.howdy". That's a reference to the class defined in scala/code/snippet/HelloWorld.scala. This is a snippet invocation and an example of Lift's view first approach to web applications. That is, there's no routing set up for the index page to collect the data and forward it to the view. Instead, the view defines areas of the content that are replaced with functions, such as those functions defined in HelloWorld.scala.
Lift knows to look in the code package for snippets, because that package is declared as a location for snippets in scala/bootstrap/liftweb/Boot.scala. The Boot class is run when starting your application, and it's where you can configure the behaviour of Lift.
See Also
The Simple Build Tool documentation is at http://www.scala-sbt.org.
Tutorials for Lift can be found in Simply Lift, Instant Lift Web Applications How-to (PACKT Publishing), and in Lift in Action (Manning Publications Co.).
Creating a Lift Project from Scratch Using SBT
You want to create a Lift web project from scratch without using the ZIP files provided on the official Lift website.
You will need to configure SBT and the Lift project yourself. Luckily, only five small files are needed.
First, create an SBT plugin file at project/plugins.sbt (all filenames are given relative to the project root directory):
addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "0.7.0")
This file tells SBT that you will be using the xsbt-web-plugin. This plugin will allow you to start and stop your application.
Next, create an SBT build file, build.sbt:
organization := "org.yourorganization"
name := "liftfromscratch"
version := "0.1-SNAPSHOT"
scalaVersion := "2.11.1"
seq(webSettings :_*)
libraryDependencies ++= {
val liftVersion = "2.6-RC1"
"net.liftweb" %% "lift-webkit" % liftVersion % "compile",
"org.eclipse.jetty" % "jetty-webapp" % "8.1.7.v20120910" %
"org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" %
"container,compile" artifacts Artifact("javax.servlet", "jar", "jar")
Feel free to change the various versions, though be aware that certain versions of Lift are only built for certain versions of Scala.
Now that you have the basics of an SBT project, you can launch the sbt console. It should load all the necessary dependencies, including the proper Scala version, and bring you to a prompt.
Next, create the following file at src/main/webapp/WEB-INF/web.xml:
<!DOCTYPE web-app SYSTEM "http://java.sun.com/dtd/web-app_2_3.dtd">
<display-name>Lift Filter</display-name>
<description>The Filter that intercepts Lift calls</description>
The web.xml file tells web containers, such as Jetty as configured by xsbt-web-plugin, to pass all requests on to Lift.
Next, create a sample index.html file at src/main/webapp/index.html for our Lift app to load. For example:
<!DOCTYPE html>
<title>Lift From Scratch</title>

Welcome, you now have a working Lift installation

Finally, set up the basic Lift boot settings by creating a Boot.scala file at src/main/scala/bootstrap/Boot.scala. The following contents will be sufficient:
package bootstrap.liftweb
import net.liftweb.http.{Html5Properties, LiftRules, Req}
import net.liftweb.sitemap.{Menu, SiteMap}
* A class that's instantiated early and run. It allows the application
* to modify lift's environment
class Boot {
def boot {
// where to search snippet
// Build SiteMap
def sitemap(): SiteMap = SiteMap(
Menu.i("Home") / "index"
// Use HTML5 for rendering
LiftRules.htmlProperties.default.set((r: Req) =>
new Html5Properties(r.userAgent))
Congratulations, you now have a working Lift project!
You can verify that you have a working Lift project by launching the Jetty web container from the SBT console with the container:start command. First, the Boot.scala file should be compiled and then you should be notified that Jetty has launched and is listening at http://localhost:8080. You should be able to go to the address in your web browser and see the rendered index.html file you created earlier.
As shown previously, creating a Lift project from scratch is a relatively simple process. However, it can be a tricky one for newcomers, especially if you are not used to the Java Virtual Machine (JVM) ecosystem and its conventions for web containers. If you run into problems, make sure the files are in the correct locations and that their contents were not mistakenly modified. If all else fails, refer to the sample project next or ask for help on the Lift mailing list.
Lift projects using SBT or similar build tools follow a standard project layout, where Scala source code is in src/main/scala and web resources are in src/main/webapp. Your Scala files must be placed either directly at src/main/scala or in nested directories matching the organization and name you defined in build.sbt, in our case giving us src/main/scala/org/yourorganization/liftfromscratch/. Test files match the directory structure but are placed in src/test/ instead of src/main/. Likewise, the web.xml file must be placed in src/main/webapp/WEB-INF/ for it to be properly detected.
Given these conventions, you should have a directory structure looking quite, if not exactly, like this:
- project root directory | build.sbt - project/ | plugins.sbt - src/ - main/ - scala/ - bootstrap/ | Boot.scala - org/ - yourorganization/ - liftfromscratch/ | <your Scala code goes here> - webapp/ | index.html | <any other web resources - images, HTML, JavaScript, etc - go here> - WEB-INF/ | web.xml - test/ - scala/ - org/ - yourorganization/ - liftfromscratch/ | <your tests go here>
See Also
There is a sample project created using this method.
Developing Using a Text Editor
You want to develop your Lift application using your favourite text editor, hitting reload in your browser to see changes.
Run SBT while you are editing, and ask it to detect and compile changes to Scala files. To do that, start sbt and enter the following to the SBT prompt:
~; container:start; container:reload /
When you save a source file in your editor, SBT will detect this change, compile the file, and reload the web container.
An SBT command prefixed with ~ makes that command run when files change. The first semicolon introduces a sequence of commands, where if the first command succeeds, the second will run. The second semicolon means the reload command will run if the start command ran OK. The start command will recompile any Scala source files that have changed.
When you run SBT in this way, you'll notice the following output:
1. Waiting for source changes... (press enter to interrupt)
And indeed, if you do press Enter in the SBT window, you'll exit this triggered execution mode and SBT will no longer be looking for file changes. However, while SBT is watching for changes, the output will indicate when this happens with something that looks a little like this:
[info] Compiling 1 Scala source to target/scala-2.11/classes... [success] Total time: 1 s, completed 26-Aug-2014 17:17:47 [pool-301-thread-4] DEBUG net.liftweb.http.LiftServlet - Destroyed Lift handler. [info] stopped o.e.j.w.WebAppContext{/,[src/main/webapp/]} [info] NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet [info] started o.e.j.w.WebAppContext{/,[src/main/webapp/]} [success] Total time: 0 s, completed 26-Aug-2014 17:17:48 2. Waiting for source changes... (press enter to interrupt)
Edits to HTML files don't trigger the SBT compile and reload commands. This is because SBT's default behaviour is to look for Scala and Java source file changes, and also changes to files in src/main/resources/. This works out just fine, because Jetty will use your modified HTML file when you reload the browser page.
Restarting the web container each time you edit a Scala file isn't ideal. You can reduce the need for restarts by integrating JRebel into your development environment, as described in [jrebel].
However, if you are making a serious number of edits, you may prefer to issue a container:stop command until you're ready to run you application again with container:start. This will prevent SBT compiling and restarting your application over and over. The SBT console has a command history, and using the up and down keyboard arrows allows you to navigate to previous commands and run them by pressing the Return key. That takes some of the tedium out of these long commands.
If you are using Java before Java 8, one error you may run into is:
java.lang.OutOfMemoryError: PermGen space
The permanent generation is a Java Virtual Machine concept. It's the area of memory used for storing classes (amongst other things). It's a fixed size, and once it is full, this PermGen error appears. As you might imagine, continually restarting a container causes many classes to be loaded and unloaded, but the process is not perfect, effectively leaking memory. The best you can do is stop and then restart SBT. If you're seeing this error often, check the setting for -XX:MaxPermSize inside the sbt (or sbt.bat) script, and if you can, double it.
See Also
Triggered execution has a number of settings you can adjust, as described in the SBT documentation.
See the SBT Command Line Reference for an overview of available commands.
Commands and configuration options for the SBT web plugin are described on the GitHub wiki.
Incorporating JRebel
You want to avoid application restarts when you change a Scala source file by using JRebel.
There are three steps required: install JRebel once; each year, request the free Scala license; and configure SBT to use JRebel.
First, visit https://my.jrebel.com/plans and request the free Scala license.
Second, download the "Generic ZIP Archive" version of JRebel, unzip it to where you like. For this recipe, I've chosen to use /opt/zt/jrebel/.
When you have received your account confirmation email from JRebel, you can copy your "authentication token" from the "Active" area of ZeroTurnaround's site. To apply the token to your local install, run the JRebel configuration script:
$ /opt/zt/jrebel/bin/jrebel-config.sh
For Windows, navigate to and launch bin\jrebel-config.cmd.
In the "Activation" setting, select "I want to use myJRebel" and then in the "License" section, paste in your activation token. Click the "Activate" button, and once you see the license status change to "You have a valid myJRebel token," click "Finish."
Finally, configure SBT by modifying the sbt script to enable JRebel. This means setting the -javaagent and -noverify flags for Java, and enabling the JRebel Lift plugin.
For Mac and Linux, the script that's included with the Lift downloads would become:
java -Drebel.lift_plugin=true -noverify -javaagent:/opt/zt/jrebel/jrebel.jar \ -Xmx1024M -Xss2M -XX:MaxPermSize=512m -XX:+CMSClassUnloadingEnabled -jar \ `dirname $0`/sbt-launch-0.12.jar "$@"
For Windows, modify sbt.bat to be:
set SCRIPT_DIR=%~dp0 java -Drebel.lift_plugin=true -noverify -javaagent:c:/opt/zt/jrebel/jrebel.jar \ -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m -Xmx1024M -Xss2M \ -jar "%SCRIPT_DIR%\sbt-launch-0.12.jar" %*
There's nothing else to do to use JRebel. When you start SBT, you'll see a large banner stating something like this:
############################################################# JRebel 5.1.1 (201211271929) (c) Copyright ZeroTurnaround OU, Estonia, Tartu. Over the last 30 days JRebel prevented at least 335 redeploys/restarts saving you about 13.6 hours. ....
With JRebel installed, you can now container:start your application, modify and compile a Scala file, and reload a page in your application. You'll see a notice that the class has been reloaded:
[2012-12-16 23:15:44] JRebel: Reloading class 'code.snippet.HelloWorld'.
That change is live, without having to restart the container.
JRebel is very likely to speed up your development. It updates code in a running Java Virtual Machine, without having to stop and restart it. The effect is that, on the whole, you can compile a class, then hit reload in your browser to see the change in your Lift application.
Even with JRebel you will need to restart your applications from time to time, but JRebel usually reduces the number of restarts. For example, Boot.scala is run when your application starts, so if you modify something in your Boot.scala, you'll need to stop and start your application. JRebel can't help with that.
But there are also other situations that JRebel cannot help with, such as when a superclass changes. Generally, JRebel will emit a warning about this in the console window. If that happens, stop and start your application.
The -Drebel.lift_plugin=true setting adds Lift-specific functionality to JRebel. Specifically, it allows JRebel to reload changes to LiftScreen, Wizard, and RestHelper. This means you can change fields or screens, and change REST serve code.
Purchased licenses
This recipe uses a free Scala license for a service called myJRebel. This communicates with JRebel servers via the activation code. If you have purchased a license from ZeroTurnaround, the situation is slightly different. In this case, you will have a license key that you store in a file called jrebel.lic. You can place the file in a .jrebel folder in your home directory, or alongside jrebel.jar (e.g., in the /opt/zt/jrebel/ folder, if that's where you installed JRebel), or you can specify some other location. For the latter option, modify the sbt script and specify the location of the file by adding another Java setting:
See Also
Details about how JRebel works can be found in the ZeroTurnaround FAQ.
The Lift support was announced in a blog post in 2012, where you'll find more about the capabilities of the plugin.
Developing Using Eclipse
You want to develop your Lift application using the Eclipse IDE, hitting reload in your browser to see changes.
Use the "Scala IDE for Eclipse" plugin to Eclipse, and the sbteclipse plugin for SBT. This will give Eclipse the ability to understand Scala, and SBT the ability to create project files that Eclipse can load.
The instructions for the Eclipse plugin are given at http://scala-ide.org. There are a number of options to be aware of when picking an update site to use: there are different sites for Scala 2.9 and 2.10, and for different versions of Eclipse. Start with the stable version of the plugin rather than a nightly or milestone version. This will give you an Eclipse perspective that knows about Scala.
Once the Eclipse plugin is installed and restarted, you need to create the project files to allow Eclipse to load your Lift project. Install sbteclipse by adding the following to projects/plugins.sbt in your Lift project:
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.5.0")
You can then create Eclipse project files (.project and .classpath) by entering the following into the SBT prompt:
Open the project in Eclipse by navigating to "File → Import…" and selecting "General → Existing Projects into Workspace." Browse to and choose your Lift project. You are now set up to develop your application in Eclipse.
To see live changes as you edit and save your work, run SBT in a separate terminal window. That is, start sbt from a terminal window outside of Eclipse and enter the following:
~; container:start; container:reload /
The behaviour of this command is described in [texteditor], but if you're using JRebel (see [jrebel]), then you just need to run container:start by itself.
You can then edit in Eclipse, save to compile, and in your web browser, hit reload to see the changes.
One of the great benefits of an IDE is the ability to navigate source, by Cmd+click (Mac) or F3 (PC). You can ask the SBT eclipse command to download the Lift source and Scaladoc, allowing you to click through to the Lift source from methods and classes, which is a useful way to discover more about Lift.
To achieve this in a project, run eclipse with-source=true in SBT, but if you want this to be the default behaviour, add the following to your build.sbt file:
EclipseKeys.withSource := true
If you find yourself using the plugin frequently, you may wish to declare it in your global SBT configuration files so it applies to all projects. To do that, create a ~/.sbt/0.13/plugins/build.sbt file containing:
resolvers += Classpaths.typesafeResolver
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.5.0")
Note the blank line between the resolvers and the addSbtPlugin. In .sbt files, a blank line is required between statements.
Finally, set any global configurations (such as withSource) in ~/.sbt/0.13/global.sbt.
See Also
There are other useful settings for sbteclipse. You'll also find the latest version number for the plugin on that site.
The SBT ~/.sbt/ structure is described in the guide to using plugins and in the wiki page for global configuration.
Developing Using IntelliJ IDEA
You want to use the IntelliJ IDEA development environment when writing your Lift application.
You need the Scala plugin for IntelliJ, and an SBT plugin to generate the IDEA project files.
The IntelliJ plugin you'll need to install only once, and these instructions are for IntelliJ IDEA 13. The details may vary between releases of the IDE, but the basic idea is to find the JetBrains Scala plugin, and download and install it.
From the "Welcome to IntelliJ IDEA" or "Quick Staert" screen, select "Configure" and then "Plugins." Select "Browse repositories…" In the search box, top right, type "Scala." You'll find on the left a number of matches: select "Scala." On the right, you'll see confirmation that this is the "Plugin for Scala language support" and the vendor is JetBrains, Inc. Click the "Install Plugin" button, confirm you want to install, then "Close" the repository browser, and finally OK out of the plugins window. You'll be prompted to restart IntelliJ IDEA.
With the IDE configured, you now need to include the SBT plugin inside your Lift project by adding the following to the file projects/plugins.sbt:
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")
Start SBT, and at the SBT prompt, create the IDEA project files by typing:
This will generate the .idea and .iml files that IntelliJ uses. Inside IntelliJ you can open the project from the "File" menu, picking "Open…" and then navigating to your project and selecting the directory.
To see live changes as you edit and save your work, run SBT in a separate Terminal window. That is, start sbt from a Terminal window outside of IntelliJ and enter the following:
~; container:start; container:reload /
This behaviour of this command is described in [texteditor], but if you're using JRebel (see [jrebel]), then you just need to run container:start by itself.
Each time you compile or make the project, the container will pick up the changes, and you can see them by reloading your browser window.
By default, the gen-idea command will fetch source for dependent libraries. That means out of the box you can click through to Lift source code to explore it and learn more about the framework.
If you want to try the latest snapshot version of the plugin, you'll need to include the snapshot repository in your plugin.sbt file:
resolvers += "Sonatype snapshots" at
Setting up the SBT IDEA plugin globally, for all SBT projects, is the same pattern as described for Eclipse in [eclipse].
See Also
The sbt-idea plugin doesn't have a configuration guide yet. One way to discover the features is to browse the release notes in the notes folder of that project.
JetBrains has a blog for the Scala plugin with feature news and tips.
Viewing the lift_proto H2 Database
You're developing using the default lift_proto.db H2 database, and you would like to use a tool to look at the tables.
Use the web interface included as part of H2. Here are the steps:
Locate the H2 JAR file. For me, this was: ~/.ivy2/cache/com.h2database/h2/jars/h2-1.2.147.jar.
Start the server from a Terminal window using the JAR file: java -cp /path/to/h2-version.jar org.h2.tools.Server.
This should launch your web browser, asking you to log in.
Select "Generic H2 Server" in "Saved Settings."
Enter jdbc:h2:/path/to/youapp/lift_proto.db;AUTO_SERVER=TRUE for "JDBC URL," adjusting the path for the location of your database, and adjusting the name of the database (lift_proto.db) if different in your Boot.scala.
Press "Connect" to view and edit your database.
The default Lift projects that include a database, such as lift_basic, use the H2 relational database, as it can be included as an SBT dependency and requires no external installation or configuration. It's a fine product, although production deployments typically use standalone databases, such as PostgreSQL or MySQL.
Even if you're deploying to a non–H2 database, it may be useful to keep H2 around because it has an in-memory mode, which is great for unit tests. This means you can create a database in memory, and throw it away when your unit test ends.
If you don't like the web interface, the connection settings described in this recipe should give you the information you need to configure other SQL tools.
See Also
The H2 site lists the features and configuration options for database engine.
If you're using the console frequently, consider making it accessible from your Lift application in development node. This is described by Diego Medina in a blog post.
The example Lift project for [Squeryl] has the H2 console
Using the Latest Lift Build
You want to use the latest ("snapshot") build of Lift.
You need to make two changes to your build.sbt file. First, reference
the snapshot
resolvers += "snapshots" at
Second, change the liftVersion in your build to be the latest version. For this example, let's use the 3.0 snapshot version of Lift:
val liftVersion = "3.0-SNAPSHOT"
Restarting SBT (or issuing a reload command) will trigger a download of the latest build.
Production releases of Lift (e.g., 2.5, 2.6), as well as milestone releases (e.g., 2.6-M3) and release candidates (e.g., 2.6-RC1) are published into a releases repository. When SBT downloads them, they are downloaded once.
Snapshot releases are different: they are the result of an automated build, and change often. You can force SBT to resolve the latest versions by running the command clean and then update.
See Also
To learn the detail of snapshot versions, dig into the Maven Complete Reference.
Using a New Version of Scala
A new Scala version has just been released and you want to immediately use it in your Lift project.
Providing that the Scala version is binary compatible with the latest version used by Lift, you can change your build file to use the latest version of Scala.
For example, let's assume your build.sbt file is set up to use Lift 2.6 with Scala 2.11.1:
scalaVersion := "2.11.1"
libraryDependencies ++= {
val liftVersion = "2.6"
"net.liftweb" %% "lift-webkit" % liftVersion % "compile->default"
To use Scala 2.11.2, just change the value in scalaVersion.
Dependencies have a particular naming convention. For example, the lift-webkit library for Lift 2.6 is called lift-webkit_2.11-2.6.jar. Normally, in build.sbt we simply refer to "net.liftweb" %% "lift-webkit", and SBT turns that into the name of a file that can be downloaded.
If for any reason you need to control the dependency downloaded, you can drop the %% and use % instead:
scalaVersion := "2.11.2"
libraryDependencies ++= {
val liftVersion = "2.6"
"net.liftweb" % "lift-webkit_2.11" % liftVersion % "compile->default"
What we've done here is explicitly specified we want the 2.11 Scala version for Lift. This is the difference between using %% and % in a dependency: with %% you do not specify the Scala version, as SBT will append the scalaVersion number automatically; with % this automatic change is not made, so we have to manually specify more details for the name of the library.
Please note this only works for minor releases of Scala: major releases break compatibility. For example, Scala 2.10.1 is compatible with Scala 2.10.2 but not 2.11.
See Also
Binary compatibility in Scala is discussed on the Scala user mailing list.
The SBT Library Dependencies page describes how SBT manages version numbers.
[snapshot] describes how to use a snapshot version of Lift.
Generating HTML is often a major component of web applications. This chapter is concerned with Lift's View First approach and use of CSS Selectors. Later chapters focus more specifically on form processing, REST web services, JavaScript, Ajax, and Comet.
Code for this chapter is at https://github.com/LiftCookbook/cookbook_html.
Testing and Debugging CSS Selectors
You want to explore or debug CSS selectors interactively.
You can use the Scala REPL to run your CSS selectors.
Here's an example where we test out a CSS selector that adds an href attribute to a link. Start from within SBT and use the console command to get into the REPL:
> console [info] Starting scala interpreter... [info] Welcome to Scala version 2.9.1.final Type in expressions to have them evaluated. Type :help for more information.
scala> import net.liftweb.util.Helpers._
import net.liftweb.util.Helpers._
scala> val f = "a [href]" #> "http://example.org"
f: net.liftweb.util.CssSel =
(Full(a [href]), Full(ElemSelector(a,Full(AttrSubNode(href)))))
scala> val in = click me
in: scala.xml.Elem = click me
scala> f(in)
res0: scala.xml.NodeSeq =
NodeSeq(click me)
The Helpers._ import brings in the CSS selector functionality, which we then exercise by creating a selector, f, calling it with a very simple template, in, and observing the result, res0.
CSS selector transforms are one of the distinguishing features of Lift. They succinctly describe a node in your template (lefthand side) and give a replacement (operation, the righthand side). They do take a little while to get used to, so being able to test them at the Scala REPL is useful.
It may help to know that prior to CSS selectors, Lift snippets were typically defined in terms of a function that took a NodeSeq and returned a NodeSeq, often via a method called bind. Lift would take your template, which would be the input NodeSeq, apply the function, and return a new NodeSeq. You won't see that usage so often anymore, but the principle is the same.
The CSS selector functionality in Lift gives you a CssSel function, which is NodeSeq => NodeSeq. We exploit this in the previous example by constructing an input NodeSeq (called in), then creating a CSS function (called f). Because we know that CssSel is defined as a NodeSeq => NodeSeq, the natural way to execute the selector is to supply the in as a parameter, and this gives us the answer, res0.
If you use an IDE that supports a worksheet, which both Eclipse and IntelliJ IDEA do, then you can also run transformations in a worksheet.
See Also
The syntax for selectors is best described in Simply Lift.
Sequencing CSS Selector Operations
You want your CSS selector binding to apply to the results of earlier binding expressions.
Use andThen rather than & to compose your selector expressions.
For example, suppose we want to replace
 with
bar content
 but for some reason we need to generate the bar div as a separate step in the selector expression:
sbt> console [info] Starting scala interpreter... [info] Welcome to Scala version 2.9.1.final (Java 1.7.0_05). Type in expressions to have them evaluated. Type :help for more information.
scala> import net.liftweb.util.Helpers._
import net.liftweb.util.Helpers._
scala> def render = "#foo" #>
 andThen "#bar *" #> "bar content"
render: scala.xml.NodeSeq => scala.xml.NodeSeq
scala> render(
)
res0: scala.xml.NodeSeq = NodeSeq(
bar content
)
When using &, think of the CSS selectors as always applying to the original template, no matter what other expressions you are combining. This is because & is aggregating the selectors together before applying them. In contrast, andThen is a method of all Scala functions that composes two functions together, with the first being called before the second.
Compare the previous example if we change the andThen to &:
scala> def render = "#foo" #>
 & "#bar *" #> "bar content"
render: net.liftweb.util.CssSel
scala> render(
)
res1: scala.xml.NodeSeq = NodeSeq(

)
The second expression will not match, as it is applied to the original input of
—the selector of #bar won't match on id=foo, and so adds nothing to the results of render.
See Also
The Lift wiki page for CSS selectors also describes this use of andThen.
Setting Meta Tag Contents
You want to set the content of an HTML meta tag from a snippet.
Use the @ CSS binding name selector. For example, given:
<meta name="keywords" content="words, here, please" />
The following snippet code will update the value of the content attribute:
"@keywords [content]" #> "words, we, really, want"
The @ selector selects all elements with the given name. It's useful in this case to change the <meta name="keyword"> tag, but you may also see it used elsewhere. For example, in an HTML form, you can select input fields such as <input name="address"> with "@address".
The [content] part is an example of a replacement rule that can follow a selector. That's to say, it's not specific to the @ selector and can be used with other selectors. In this example, it replaces the value of the attribute called "content." If the meta tag had no "content" attribute, it would be added.
There are two other replacement rules useful for manipulating attributes:
[content!] to remove an attribute with a matching value.
[content+] to append to the value.
Examples of these would be:
scala> import net.liftweb.util.Helpers._
import net.liftweb.util.Helpers._
scala> val in = <meta name="keywords" content="words, here, please" />
in: scala.xml.Elem = <meta name="keywords" content="words, here, please"></meta>
scala> val remove = "@keywords [content!]" #> "words, here, please"
remove: net.liftweb.util.CssSel = CssBind(Full(@keywords [content!]),
scala> remove(in)
res0: scala.xml.NodeSeq = NodeSeq(<meta name="keywords"></meta>)
scala> val add = "@keywords [content+]" #> ", thank you"
add: net.liftweb.util.CssSel = CssBind(Full(@keywords [content+]),
scala> add(in)
res1: scala.xml.NodeSeq = NodeSeq(<meta content="words, here, please, thank you"
Appending to a class attribute
Although not directly relevant to meta tags, you should be aware that there is one convenient special case for appending to an attribute. If the attribute is class, a space is added together with your class value. As a demonstration of that, here's an example of appending a class called btn-primary to a div:
scala> def render = "div [class+]" #> "btn-primary"
render: net.liftweb.util.CssSel
scala> render(
)
res0: scala.xml.NodeSeq = NodeSeq(

)
See Also
The syntax for selectors is best described in Simply Lift.
See [TestingAndDebuggingSelectors] for how to run selectors from the REPL.
Setting the Page Title
You want to set the <title> of the page from a Lift snippet.
Select the content of the title element and replace it with the text you want:
"title *" #> "I am different"
Assuming you have a <title> tag in your template, this will result in:
<title>I am different</title>
This example uses an element selector, which picks out tags in the HTML template and replaces the content. Notice that we are using "title *" to select the content of the title tag. If we had left off the *, the entire title tag would have been replaced with text.
As an alternative, it is also possible to set the page title from the contents of SiteMap, meaning the title used will be the title you've assigned to the page in the site map. To do that, make use of Menu.title in your template directly:
<title data-lift="Menu.title"></title>
The Menu.title code appends to any existing text in the title. This means the following will have the phrase "Site Title - " in the title, followed by the page title:
<title data-lift="Menu.title">Site Title - </title>
If you need more control, you can of course bind on <title> using a regular snippet. This example uses a custom snippet to put the site title after the page title:
<title data-lift="MyTitle"></title>
object MyTitle {
def render = <title><lift:Menu.title /> - Site Title</title>
Notice that our snippet is returning another snippet, <lift:Menu.title/>. This is a perfectly normal thing to do in Lift, and snippet invocations returned from snippets will be processed by Lift as normal.
See Also
[SnippetNotFound] describes the different ways to reference a snippet, such as data-lift and <lift: ... />.
At the Assembla website, there's more about SiteMap and the Menu snippets.
HTML Conditional Comments
You want to make use of Internet Explorer HTML conditional comments in your
Put the markup in a snippet and include the snippet in your page or template.
package code.snippet
import scala.xml.Unparsed
object Html5Shiv {
def render = Unparsed("""")
It would be used like this:

A div just for IE
and produces output like this:

and supply some additional binding hints. The form is still very minimal, while being completely under the control of the designer.
The example in the solution section demonstrates the most important aspects. In particular, you should note that you must still supply a source for the template, and that you can designate alternatives for sub-portions of the template. In the example, we allow the HTML designer direct access to the field template for this screen by making it possible to put the layout in a custom template file accounts/account_edit_field.html.
The rest is very easy. You must supply a formName declaration (in Scala) for CssBoundLiftScreen, and a FieldBinding as an argument to each field. This, combined with an internal function (that you can override), will generate unique (but known) names that can be used in the template. The default pattern is: "formName_fieldName_field". So, if you name your form "myform", and bind a field to "address", then your HTML template should include a div with the ID "myform_address_field". That is all you need for normal bindings that use your field template.
To tweak the field layout for a particular field, you may specify Self in the Scala field binding. This indicates the template for that particular field should be sourced from the field's div.
If you want to get even fancier there are additional field bindings, such as Dynamic(() => NodeSeq), which uses the supplied function to generate a template for the field each time it is rendered.
See Also
Further examples can be found in:
Peter Brant's Lift Screen CSS Binding GitHub repository.
LiftScreen is described on the Lift Wiki and in Simply Lift.
This chapter looks at recipes around REST web services, via Lift's RestHelper trait. For an introduction, take a look at the Lift wiki page and Chapter 5 of Simply Lift.
The sample code from this chapter is at https://github.com/LiftCookbook/cookbook_rest.
DRY URLs
You find yourself repeating parts of URL paths in your RestHelper and you Don't want to Repeat Yourself (DRY).
Use prefix in your RestHelper:
package code.rest
import net.liftweb.http.rest.RestHelper
import net.liftweb.http.LiftRules
object IssuesService extends RestHelper {
def init() : Unit = {
serve("issues" / "by-state" prefix {
case "open" :: Nil XmlGet _ =>
None open

case "closed" :: Nil XmlGet _ =>
None closed

case "closed" :: Nil XmlDelete _ =>
All deleted

This service responds to URLs of /issues/by-state/open and /issues/by-state/closed and we have factored out the common part as a prefix.
Wire this into Boot.scala with:
import code.rest.IssuesService
We can test the service with cURL:
$ curl -H 'Content-Type: application/xml'
<?xml version="1.0" encoding="UTF-8"?>

None open

$ curl -X DELETE -H 'Content-Type: application/xml'
<?xml version="1.0" encoding="UTF-8"?>

All deleted

You can have many serve blocks in your RestHelper, which helps give your REST service structure.
In this example, we've arbitrarily decided to return XML and to match on an XML request using XmlGet and XmlDelete. The test for an XML request requires a content type of text/xml or application/xml, or a request for a path that ends with .xml. This is why the cURL request includes a header with with the -H flag. If we hadn't included that, the request would not match any of our patterns, and the result would be a 404 response.
See Also
[JSONREST] gives an example of accepting and returning JSON.
Missing File Suffix
Your RestHelper expects a filename as part of the URL, but the suffix (extension) is missing, and you need it.
Access req.path.suffix to recover the suffix.
For example, when processing /download/123.png, you want to be able to reconstruct 123.png:
package code.rest
import net.liftweb.http.rest.RestHelper
import net.liftweb.http.LiftRules
import xml.Text
object Reunite extends RestHelper {
private def reunite(name: String, suffix: String) =
if (suffix.isEmpty) name else name+"."+suffix
serve {
case "download" :: file :: Nil Get req =>
Text("You requested "+reunite(file, req.path.suffix))
def init() : Unit = {
We are matching on download but rather than using the file value directly, we pass it through the reunite function first to attach the suffix back on (if any).
Requesting this URL with a command like cURL will show you the filename as expected:
$ curl http://127.0.0.1:8080/download/123.png
<?xml version="1.0" encoding="UTF-8"?>
You requested 123.png
When Lift parses a request, it splits the request into constituent parts (e.g., turning the path into a List[String]). This includes a separation of some suffixes. This is good for pattern matching when you want to change behaviour based on the suffix, but a hindrance in this particular situation.
Only those suffixes defined in LiftRules.explicitlyParsedSuffixes are split from the filename. This includes many of the common file suffixes (such as .png, .atom, .json) and also some you may not be so familiar with, such as .com.
Note that if the suffix is not in explicitlyParsedSuffixes, the suffix will be an empty string and the name (in the previous example) will be the filename with the suffix still attached.
Depending on your needs, you could alternatively add a guard condition to check for the file suffix:
case "download" :: file :: Nil Get req if req.path.suffix == "png" =>
Text("You requested PNG file called "+file)
Or rather than simply attaching the suffix back on, you could take the opportunity to do some computation and decide what to send back. For example, if the client supports the WebP image format, you might prefer to send that:
package code.rest
import net.liftweb.http.rest.RestHelper
import net.liftweb.http.LiftRules
import xml.Text
object Reunite extends RestHelper {
def init() : Unit = {
serve {
case "negotiate" :: file :: Nil Get req =>
val toSend =
if (req.header("Accept").exists(_ == "image/webp")) file+".webp"
else file+".png"
Text("You requested "+file+", would send "+toSend)
Calling this service would check the HTTP Accept header before deciding what resource to send:
$ curl http://localhost:8080/negotiate/123
<?xml version="1.0" encoding="UTF-8"?>
You requested 123, would send 123.png
$ curl http://localhost:8080/negotiate/123 -H "Accept: image/webp"
<?xml version="1.0" encoding="UTF-8"?>
You requested 123, would send 123.webp
See Also
[MissingDotCom] shows how to remove items from explicitlyParsedSuffixes.
The source for HttpHelpers.scala contains the explicitlyParsedSuffixes list, which is the default list of suffixes that Lift parses from a URL.
Missing .com from Email Addresses
When submitting an email address to a REST service, a domain ending .com is stripped before your REST service can handle the request.
Modify LiftRules.explicitlyParsedSuffixes so that Lift doesn't change URLs that end with .com.
In Boot.scala:
import net.liftweb.util.Helpers
LiftRules.explicitlyParsedSuffixes = Helpers.knownSuffixes - "com"
By default, Lift will strip off file suffixes from URLs to make it easy to match on suffixes. An example would be needing to match on all requests ending in .xml or .pdf. However, .com is also registered as one of those suffixes, but this is inconvenient if you have URLs that end with email addresses.
Note that this doesn't impact email addresses in the middle of URLs. For example, consider the following REST service:
package code.rest
import net.liftweb.http.rest.RestHelper
import net.liftweb.http.LiftRules
import xml.Text
object Suffix extends RestHelper {
def init() : Unit = {
serve {
case "email" :: e :: "send" :: Nil Get req =>
Text("In middle: "+e)
case "email" :: e :: Nil Get req =>
Text("At end: "+e)
With this service init method called in Boot.scala, we could then make requests and observe the issue:
$ curl http://localhost:firstname.lastname@example.com/send
<?xml version="1.0" encoding="UTF-8"?>
In middle: firstname.lastname@example.com
$ curl http://localhost:firstname.lastname@example.com
<?xml version="1.0" encoding="UTF-8"?>
At end: you@example
The .com is being treated as a file suffix, which is why the solution of removing it from the list of suffixes will resolve this problem.
Note that because other top-level domains, such as .uk, .nl, .gov, are not in explicitlyParsedSuffixes, those email addresses are left untouched.
See Also
[MissingSuffix] describes the suffix processing in more detail.
Failing to Match on a File Suffix
You're trying to match on a file suffix (extension), but your match is failing.
Ensure the suffix you're matching on is included in LiftRules.explicitlyParsedSuffixes.
As an example, perhaps you want to match anything ending in .csv at your /reports/ URL:
case Req("reports" :: name :: Nil, "csv", GetRequest) =>
Text("Here's your CSV report for "+name)
You're expecting /reports/foo.csv to produce "Here's your CSV report for foo," but you get a 404.
To resolve this, include "csv" as a file suffix that Lift knows to split from URLs. In Boot.scala, call:
LiftRules.explicitlyParsedSuffixes += "csv"
The pattern will now match.
Without adding "csv" to the explicitlyParsedSuffixes, the example URL would match with:
case Req("reports" :: name :: Nil, "", GetRequest) =>
Text("Here's your CSV report for "+name)
Here we're matching on no suffix (""). In this case, name would be set to "foo.csv". This is because Lift separates file suffixes from the end of URLs only for file suffixes that are registered with explicitlyParsedSuffixes. Because "csv" is not one of the default registered suffixes, "foo.csv" is not split. That's why "csv" in the suffix position of Req pattern match won't match the request, but an empty string in that position will.
See Also
[MissingSuffix] explains more about the suffix removal in Lift.
Accept Binary Data in a REST Service
You want to accept an image upload, or other binary data, in your RESTful service.
Access the request body in your REST helper:
package code.rest
import net.liftweb.http.rest.RestHelper
import net.liftweb.http.LiftRules
object Upload extends RestHelper {
def init() : Unit = {
serve {
case "upload" :: Nil Post req =>
for {
bodyBytes <- req.body
} yield <info>Received {bodyBytes.length} bytes</info>
Wire this into your application in Boot.scala:
import code.rest.Upload
Test this service using a tool like cURL:
$ curl -X POST --data-binary "@dog.jpg" -H 'Content-Type: image/jpg'
<?xml version="1.0" encoding="UTF-8"?>
<info>Received 1365418 bytes</info>
In this example, the binary data is accessed via the req.body, which returns a Box[Array[Byte]]. We turn this into a Box[Elem] to send back to the client. Implicits in RestHelper turn this into an XmlResponse for Lift to handle.
Note that web containers, such as Jetty and Tomcat, may place limits on the size of an upload. You will recognise this situation by an error such as java.lang.IllegalStateException: Form too large705784>200000. Check with documentation for the container for changing these limits.
To restrict the type of image you accept, you could add a guard condition to the match, but you may find you have more readable code by moving the logic into an unapply method on an object. For example, to restrict an upload to just a JPEG you could say:
serve {
case "jpg" :: Nil Post JPeg(req) =>
for {
bodyBytes <- req.body
} yield <info>Jpeg Received {bodyBytes.length} bytes</info>
object JPeg {
def unapply(req: Req): Option[Req] =
req.contentType.filter(_ == "image/jpg").map(_ => req)
We have defined an extractor called JPeg that returns Some[Req] if the content type of the upload is image/jpg; otherwise, the result will be None. This is used in the REST pattern match as JPeg(req). Note that the unapply needs to return Option[Req] as this is what's expected by the Post extractor.
See Also
Odersky, et al., (2008), Programming in Scala, Chapter 24, discusses extractors in detail.
[FileUpload] describes form-based (multipart) file uploads
Serving Videos
You want to use the HTML5 video tag to serve videos.
Use a RestHelper to return a chunked StreamingResponse of a video.
A short example:
import net.liftweb.http.StreamingResponse
import net.liftweb.http.rest.RestHelper
object Streamer extends RestHelper {
serve {
case req@Req(("video" :: id :: Nil), _, _) =>
val fis = new FileInputStream(new File(id))
val size = file.length - 1
val content_type = "Content-Type" -> "video/mp4" // replace with appropriate format
val start = 0L
val end = size
val headers =
("Connection" -> "close") ::
("Transfer-Encoding" -> "chunked") ::
content_type ::
("Content-Range" -> ("bytes " + start.toString + "-" + end.toString + "/" + file.length.toString)) ::
() => StreamingResponse(
data = fis,
onEnd = fis.close,
cookies = Nil,
code = 206
The above example doesn't allow the client to skip ahead in the file. The Range header must be parsed in order to facilitate this. It specifies what part of the file the client wishes to receive. Request headers are contained within the req@Req(urlParams, _, _) pattern in the previous example. The start and end can be extracted like so:
val (start,end) =
req.header("Range") match {
case Full(r) => {
parseNumber(r.substring(r.indexOf("bytes=") + 6)),
if (r.endsWith("-"))
file.length - 1
parseNumber(r.substring(r.indexOf("-") + 1))
case _ => (0L, file.length - 1)
Next, the response must skip ahead to the location in the video where the client wishes to begin. This is done by doing the following:
val fis: FileInputStream = ... // Shown in the first example
See Also
This recipe is based on the Streaming Response wiki article.
ObeseRabbit is a small application showcasing this feature.
[RestStreamContent] describes StreamingResponse and similar types of response, such as OutputStreamResponse and InMemoryResponse.
Returning JSON
You want to return JSON from a REST call.
Use the Lift JSON domain-specific language (DSL). For example:
package code.rest
import net.liftweb.http.rest.RestHelper
import net.liftweb.http.LiftRules
import net.liftweb.json.JsonAST._
import net.liftweb.json.JsonDSL._
object QuotationsAPI extends RestHelper {
def init() : Unit = {
serve {
case "quotation" :: Nil JsonGet req =>
("text" -> "A beach house isn't just real estate. It's a state of mind.") ~
("by" -> "Douglas Adams") : JValue
Wire this into Boot.scala:
import code.rest.QuotationsAPI
Running this example produces:
$ curl -H 'Content-type: text/json' http://127.0.0.1:8080/quotation
"text":"A beach house isn't just real estate. It's a state of mind.",
"by":"Douglas Adams"
The type ascription at the end of the JSON expression (: JValue) tells the compiler that the expression is expected to be of type JValue. This is required to allow the DSL to apply. It would not be required if, for example, you were calling a function that was defined to return a JValue.
The JSON DSL allows you to create nested structures, lists, and everything else you expect of JSON.
In addition to the DSL, you can create JSON from a case class by using the Extraction.decompose method:
import net.liftweb.json.Extraction
import net.liftweb.json.DefaultFormats
case class Quote(text: String, by: String)
val quote = Quote(
"A beach house isn't just real estate. It's a state of mind.",
"Douglas Adams")
implicit val formats = DefaultFormats
val json : JValue = Extraction decompose quote
This will also produce a JValue, which when printed will be:
"text":"A beach house isn't just real estate. It's a state of mind.",
"by":"Douglas Adams"
See Also
The README file for the lift-json project is a great source of examples for using the JSON DSL.
Google Sitemap
You want to make a Google Sitemap using Lift's rendering capabilities.
Create the site map structure, and bind to it as you would for any template in Lift.
Start with a sitemap.html in your webapp folder containing valid XML-Sitemap markup:
<?xml version="1.0" encoding="utf-8" ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url data-lift="SitemapContent.base">
<url data-lift="SitemapContent.list">
Make a snippet to fill the required gaps:
package code.snippet
import org.joda.time.DateTime
import net.liftweb.util.CssSel
import net.liftweb.http.S
import net.liftweb.util.Helpers._
class SitemapContent {
case class Post(url: String, date: DateTime)
lazy val entries =
Post("/welcome", new DateTime) :: Post("/about", new DateTime) :: Nil
val siteLastUdated = new DateTime
def base: CssSel =
"loc *" #> "http://%s/".format(S.hostName) &
"lastmod *" #> siteLastUpdated.toString("yyyy-MM-dd'T'HH:mm:ss.SSSZZ")
def list: CssSel =
"url *" #> entries.map(post =>
"loc *" #> "http://%s%s".format(S.hostName, post.url) &
"lastmod *" #> post.date.toString("yyyy-MM-dd'T'HH:mm:ss.SSSZZ"))
This example is using canned data for two pages.
Apply the template and snippet in a REST service at /sitemap:
package code.rest
import net.liftweb.http._
import net.liftweb.http.rest.RestHelper
object Sitemap extends RestHelper {
serve {
case "sitemap" :: Nil Get req =>
S.render(<lift:embed what="sitemap" />, req.request).head
Wire this into your application in Boot.scala, for example:
Test this service using a tool like cURL:
$ curl http://127.0.0.1:8080/sitemap
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
You may be wondering why we've used REST here when we could have used a regular HTML template and snippet. The reason is that we want XML rather than HTML output. We use the same mechanism, but invoke it and wrap it in an XmlResponse.
The S.render method takes a NodeSeq and an HTTPRequest. The first we supply by running the sitemap.html snippet; the second is simply the current request. XmlResponse requires a Node rather than a NodeSeq, which is why we call head—as there's only one node in the response, this does what we need.
Note that Google Sitemaps needs dates to be in ISO 8601 format. The built-in java.text.SimpleDateFormat does not support this format prior to Java 7. If you are using Java 6, you need to use org.joda.time.DateTime as we are in this example.
See Also
You'll find an explanation of the Sitemap Protocol on Google's Webmaster Tools site.
Calling REST Service from a Native iOS Application
You want to make an HTTP POST from a native iOS device to a Lift REST service.
Use NSURLConnection, ensuring you set the content-type to application/json.
For example, suppose we want to call this service:
package code.rest
import net.liftweb.http.rest.RestHelper
import net.liftweb.json.JsonDSL._
import net.liftweb.json.JsonAST._
object Shouty extends RestHelper {
def greet(name: String) : JValue =
"greeting" -> ("HELLO "+name.toUpperCase)
serve {
case "shout" :: Nil JsonPost json->request =>
for { JString(name) <- (json \\ "name").toOpt }
yield greet(name)
The service expects a JSON post with a parameter of name, and it returns a greeting as a JSON object. To demonstrate the data to and from the service, we can include the service in Boot.scala:
Call it from the command line:
$ curl -d '{ "name" : "World" }' -X POST -H 'Content-type: application/json'
"greeting":"HELLO WORLD"
We can implement the POST request using NSURLConnection:
static NSString *url = @"http://localhost:8080/shout";
-(void) postAction {
// JSON data:
NSDictionary* dic = @{@"name": @"World"};
NSData* jsonData =
[NSJSONSerialization dataWithJSONObject:dic options:0 error:nil];
NSMutableURLRequest *request = [
NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
// Construct HTTP request:
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:[NSString stringWithFormat:@"%d", [jsonData length]]
[request setHTTPBody: jsonData];
// Send the request:
NSURLConnection *con = [[NSURLConnection alloc]
initWithRequest:request delegate:self];
- (void)connection:(NSURLConnection *)connection
didReceiveResponse:(NSURLResponse *)response {
// Start off with new, empty, response data
self.receivedJSONData = [NSMutableData data];
- (void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data {
// append incoming data
[self.receivedJSONData appendData:data];
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error {
NSLog(@"Error occurred ");
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSError *e = nil;
NSDictionary *JSON =
[NSJSONSerialization JSONObjectWithData: self.receivedJSONData
options: NSJSONReadingMutableContainers error: &e];
NSLog(@"Return result: %@", [JSON objectForKey:@"greeting"]);
Obviously in this example we've used hardcoded values and URLs, but this will hopefully be a starting point for use in your application.
There are many ways to do HTTP POST from iOS, and it can be confusing to identify the correct way that works, especially without the aid of an external library. The previous example uses the iOS native API.
Another way is to use AFNetworking. This is a popular external library for iOS development, can cope with many scenarios, and is simple to use:
#import "AFHTTPClient.h"
#import "AFNetworking.h"
#import "JSONKit.h"
static NSString *url = @"http://localhost:8080/shout";
-(void) postAction {
// JSON data:
NSDictionary* dic = @{@"name": @"World"};
NSData* jsonData =
[NSJSONSerialization dataWithJSONObject:dic options:0 error:nil];
// Construct HTTP request:
NSMutableURLRequest *request =
[NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:[NSString stringWithFormat:@"%d", [jsonData length]]
[request setHTTPBody: jsonData];
// Send the request:
AFJSONRequestOperation *operation =
[[AFJSONRequestOperation alloc] initWithRequest: request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation,
id responseObject)
NSString *response = [operation responseString];
// Use JSONKit to deserialize the response into NSDictionary
NSDictionary *deserializedJSON = [response objectFromJSONString];
[deserializedJSON count];
// The response object can be a NSDicionary or a NSArray:
if([deserializedJSON count]> 0) {
NSLog(@"Return value: %@",[deserializedJSON objectForKey:@"greeting"]);
else {
NSArray *deserializedJSONArray = [response objectFromJSONString];
NSLog(@"Return array value: %@", deserializedJSONArray );
}failure:^(AFHTTPRequestOperation *operation, NSError *error)
NSLog(@"Error: %@",error);
[operation start];
The NSURLConnection approach is more versatile and gives you a starting point to craft your own solution, such as by making the content type more specific. However, AFNetworking is popular and you may prefer that route.
See Also
You may find the "Complete REST Example" in Simply Lift to be a good test ground for your calls to Lift.
JavaScript, Ajax, and Comet
Lift is known for its great Ajax and Comet support, and in this chapter, we'll explore these.
For an introduction to Lift's Ajax and Comet features, see Simply Lift, Chapter 9 of Lift in Action (Perrett, 2012, Manning Publications, Co.), or watch Diego Medina's video presentation.
The source code for this chapter is at https://github.com/LiftCookbook/cookbook_ajax.
Trigger Server-Side Code from a Button
You want to trigger some server-side code when the user presses a button.
Use ajaxInvoke:
package code.snippet
import net.liftweb.util.Helpers._
import net.liftweb.http.SHtml
import net.liftweb.http.js.{JsCmd, JsCmds}
import net.liftweb.common.Loggable
object AjaxInvoke extends Loggable {
def callback() : JsCmd = {
logger.info("The button was pressed")
JsCmds.Alert("You clicked it")
def button = "button [onclick]" #> SHtml.ajaxInvoke(callback)
In this snippet, we are binding the click event of a button to an ajaxInvoke: when the button is pressed, Lift arranges for the function you gave ajaxInvoke to be executed.

<button>Click Me</button>
The signature of the function you pass to ajaxInvoke is Unit => JsCmd, meaning you can trigger a range of behaviours: from returning Noop if you want nothing to happen, through changing DOM elements, all the way up to executing arbitrary JavaScript.
The previous example uses a button but will work on any element that has an event you can bind to. We're binding to onclick but it could be any event the DOM exposes.
Related to ajaxInvoke are the following functions:
- SHtml.onEvent
Calls a function with the signature String => JsCmd because it is passed the value of the node it is attached to. In the previous example, this would be the empty string, as the button has no value.
- SHtml.ajaxCall
This is more general than onEvent, as you give it the expression you want passed to your server-side code.
- SHtml.jsonCall
This is even more general still: you give it a function that will return a JSON object when executed on the client, and this object will be passed to your server-side function.
Let's look at each of these in turn.
onEvent: receiving the value of a DOM element
You can use onEvent with any element that has a value attribute and responds to the event you choose to bind to. The function you supply to onEvent is called with the element's value. As an example, we can write a snippet that presents a challenge to the user and validates the response:
package code.snippet
import scala.util.Random
import net.liftweb.util.Helpers._
import net.liftweb.http.SHtml
import net.liftweb.http.js.JsCmds.Alert
object OnEvent {
def render = {
val x, y = Random.nextInt(10)
val sum = x + y
"p *" #> "What is %d + %d?".format(x,y) &
"input [onchange]" #> SHtml.onEvent( answer =>
if (answer == sum.toString) Alert("Correct!")
else Alert("Try again")
This snippet prompts the user to add the two random numbers presented in the
 tag, and binds a validation function to the <input> on the page:

Problem appears here

<input placeholder="Type your answer"></input>
When onchange is triggered (by pressing Return or the Tab key, for example), the text entered is sent to our onEvent function as a String. On the server-side, we check the answer and send back "Correct!" or "Try again" as a JavaScript alert.
ajaxCall: receiving an arbitrary client-side string
Where onEvent sends this.value to your server-side code, ajaxCall allows you to specify the client-side expression used to produce a value.
To demonstrate this, we can create a template that includes two elements: a button and a text field. We'll bind our function to the button, but read a value from the input field:

<input id="num" value="41"></input>
We want to arrange for the button to read the num field, increment it, and return it back to the input field:
package code.snippet
import net.liftweb.util.Helpers._
import net.liftweb.http.SHtml
import net.liftweb.http.js.JE.ValById
import net.liftweb.http.js.JsCmds._
object AjaxCall {
def increment(in: String) : String =
asInt(in).map(_ + 1).map(_.toString) openOr in
def render = "button [onclick]" #>
SHtml.ajaxCall(ValById("num"), s => SetValById("num", increment(s)) )
The first argument to ajaxCall is the expression that will produce a value for our function. It can be any JsExp, and we've used ValById, which looks up the value of an element by the ID attribute. We could have used a regular jQuery expression to achieve the same effect with JsRaw("$('#num').val()").
Our second argument to ajaxCall takes the value of the JsExp expression as a String. We're using one of Lift's JavaScript commands to replace the value with a new value. The new value is the result of incrementing the number (providing it is a number).
The end result is that you press the button and the number updates. It should go without saying that these are simple illustrations, and you probably don't want a server round-trip to add one to a number. The techniques come into their own when there is some action of value to perform on the server.
You may have guessed that onEvent is implemented as an ajaxCall for JsRaw("this.value").
jsonCall: receiving a JSON value
Both ajaxCall and onEvent end up evaluating a String => JsCmd function. By contrast, jsonCall has the signature JValue => JsCmd, meaning you can pass more complex data structures from JavaScript to your Lift application.
To demonstrate this, we'll create a template that asks for input, has a function to convert the input into JSON, and a button to send the JSON to the server:

Enter an addition question:

<input id="x"> + <input id="y"> = <input id="z">.

$(function () {
dataType: 'json',
add: function (e,data) {
$('#progress-bar').css('width', '0%');
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10) + '%';
$('#progress-bar').css('width', progress);
done: function (e, data) {
$.each(data.files, function (index, file) {
This template provides an input field for files, an area to use as a progress indicator, and configures the widget when the page loads in a jQuery $( ... ) block. This is just regular usage of the JavaScript widget, and nothing particularly Lift-specific.
The final part is to implement a Lift REST service to receive the file or files. The URL of the service, /upload, is set in data-url on the input field, and that's the address we match on:
package code.rest
import net.liftweb.http.rest.RestHelper
import net.liftweb.http.OkResponse
object AjaxFileUpload extends RestHelper {
serve {
case "upload" :: Nil Post req =>
for (file <- req.uploadedFiles) {
println("Received: "+file.fileName)
This implementation simply logs the name of the file received and acknowledges successful delivery with a 200 status code back to the widget.
As with all REST services, it needs to be registered in Boot.scala:
By default, the widget makes the whole HTML page a drop-target for files, meaning you can drag a file onto the page and it will immediately be uploaded to your Lift application.
In this recipe, we've shown just the basic integration of the widget with a Lift application. The demo site for the widget shows other capabilities, and provides documentation on how to integrate them.
In the REST service, the uploaded files are available via the uploadedFiles method on the request. When Lift receives a multipart form, it automatically extracts files as
By default, uploaded files are held in memory, but that can be changed (see [UploadToDisk] in [FileUpload]).
In this recipe, we return a 200 (OkResponse). If we wanted to signal to the widget that a file was rejected, we can return another code. For example, perhaps we want to reject all files except PNG images. On the server-side we can do that by replacing the OkResponse with a test:
import net.liftweb.http.{ResponseWithReason, BadResponse, OkResponse}
if (req.uploadedFiles.exists( _.mimeType != "image/png" ))
ResponseWithReason(BadResponse(), "Only PNGs")
We would mirror this with a fail handler in the client JavaScript:
fail: function (e, data) {
If we uploaded, say, a JPEG, the browser would show an alert dialog reporting "Only PNGs."
See Also
Diego Medina has posted a Gist of Lift REST code to integrate more fully with the image upload and image reviewing features of the widget, specifically implementing the JSON response that the widget expects for that
[FileUpload] describes the basic file upload behaviour of Lift and how to control where files are stored.
Antonio Salazar Cardozo has posted example code for performing Ajax file upload using Lift's Ajax mechanisms. This avoids external JavaScript libraries.
Format a Wired Cell
You want a wired UI element to have a different format than plain conversion to a string. For example, you'd like to display a floating-point value as a currency.
Use the WiringUI.toNode method to create a wiring node that can render the output formatted as you desire.
As an example, consider an HTML template to display the quantity of an item being purchased and the subtotal:

Quantity	?

Subtotal	?

<button id="add">Add Another One</button>
We'd like the subtotal to display as US dollars. The snippet would be:
package code.snippet
import java.text.NumberFormat
import java.util.Locale
import scala.xml.{NodeSeq, Text}
import net.liftweb.util.Helpers._
import net.liftweb.util.{Cell, ValueCell}
import net.liftweb.http.{S, WiringUI}
import net.liftweb.http.SHtml.ajaxInvoke
import net.liftweb.http.js.JsCmd
class Wiring {
val cost = ValueCell(1.99)
val quantity = ValueCell(1)
val subtotal = cost.lift(quantity)(_ * _)
val formatter = NumberFormat.getCurrencyInstance(Locale.US)
def currency(cell: Cell[Double]): NodeSeq => NodeSeq =
WiringUI.toNode(cell)((value, ns) => Text(formatter format value))
def increment(): JsCmd = {
quantity.atomicUpdate(_ + 1)
S.notice("Added One")
def render =
"#add [onclick]" #> ajaxInvoke(increment) &
"#quantity *" #> WiringUI.asText(quantity) &
"#subtotal *" #> currency(subtotal)
We have defined a currency method to format the subtotal not as a Double but as a currency amount using the Java number-formatting capabilities. This will result in values like "$19.90" being shown rather than "19.9."
The primary WiringUI class makes it easy to bind a cell as text. The asText method works by converting a value to a String and wrapping it in a Text node. This is done via toNode, however, we can use the toNode method directly to generate a transform function that is both hooked into the wiring UI and uses our code for the translation of the item.
The mechanism is type-safe. In this example, cost is a Double cell, quantity is an Int cell, and subtotal is inferred as a Cell[Double]. This is why our formatting function is passed value as a Double.
Note that the function passed to toNode must return a NodeSeq. This gives a great deal of flexibility as you can return any kind of markup in a NodeSeq. Our example complies with this signature by wrapping a text value in a Text object.
The WiringUI.toNode requires a (T, NodeSeq) => NodeSeq. In the previous example, we ignore the NodeSeq, but the value would be the contents of the element we've bound to. Given the input:
?
this would mean the NodeSeq passed to us would just be the text node representing "?". With a richer template we can use CSS selectors. For example, we can modify the
Subtotal
The value is ?
Now we can apply a CSS selector to change just the amount element:
(value, ns) => (".amount *" #> Text(formatter format value)) apply ns)
See Also
Chapter 6 of Simply Lift describes Lift's Wiring mechanism, and gives a detailed shopping example.
Request Pipeline
When a request reaches Lift, there are a number of points where you can jump in and control what Lift does, sending back a different kind of response or controlling access. This chapter looks at the pipeline through examples of different kinds of LiftResponses and configurations.
You can get a great overview of the pipeline, including diagrams, from the Lift pipeline wiki page.
See https://github.com/LiftCookbook/cookbook_pipeline for the source code that accompanies this chapter.
Debugging a Request
You want to debug a request and see what's arriving to your Lift application.
Add an onBeginServicing function in Boot.scala to log the request. For example:
LiftRules.onBeginServicing.append {
case r => println("Received: "+r)
The onBeginServicing call is called quite early in the Lift pipeline, before S is set up, and before Lift has the chance to 404 your request. The function signature it expects is Req => Unit. We're just logging, but the functions could be used for other purposes.
If you want to select only certain paths, you can. For example, to track all requests starting /paypal:
LiftRules.onBeginServicing.append {
case r @ Req("paypal" :: _), _, _) => println(r)
This pattern will match any request starting /paypal, and we're ignoring the suffix on the request, if any, and the type of request (e.g., GET, POST, or so on).
There's also LiftRules.early, which is called before onBeginServicing. It expects an HTTPRequest => Unit function, so is a little lower-level than the Req used in onBeginServicing. However, it will be called by all requests that pass through Lift. To see the difference, you could mark a request as something that the container should handle by itself:
LiftRules.liftRequest.append {
case Req("robots" :: _, _, _) => false
With this in place, a request for robots.txt will be logged by LiftRules.early but won't make it to any of the other methods described in this recipe.
If you need access to state (e.g., S), use earlyInStateful, which is based on a Box[Req] not a Req:
LiftRules.earlyInStateful.append {
case Full(r) => // access S here
case _ =>
It's possible for your earlyInStateful function to be called twice. This will happen when a new session is being set up. You can prevent this by only matching on requests in a running Lift session:
LiftRules.earlyInStateful.append {
case Full(r) if LiftRules.getLiftSession(r).running_? => // access S here
case _ =>
Finally, there's also earlyInStateless, which like earlyInStateful, works on a Box[Req] but in other respects is the same as onBeginServicing. It is triggered after early and before earlyInStateful.
As a summary, the functions described in this recipe are called in this order:
See Also
If you need to catch the end of a request, there is also an onEndServicing that can be given functions of type (Req, Box[LiftResponse]) => Unit.
[RunningStateless] describes how to force requests to be stateless.
Running Code When Sessions Are Created (or Destroyed)
You want to carry out actions when a session is created or destroyed.
Make use of the hooks in LiftSession. For example, in Boot.scala:
LiftSession.afterSessionCreate ::=
( (s:LiftSession, r:Req) => println("Session created") )
LiftSession.onBeginServicing ::=
( (s:LiftSession, r:Req) => println("Processing request") )
LiftSession.onShutdownSession ::=
( (s:LiftSession) => println("Session going away") )
If the request path is marked as being stateless via LiftRules.statelessReqTest, this example would only execute the onBeginServicing functions.
The hooks in LiftSession allow you to insert code at various points in the session life cycle: when the session is created, at the start of servicing the request, after servicing, when the session is about to shut down, at shutdown, etc. The pipeline diagrams mentioned at the start of this chapter are a useful guide to these stages.
The list of session hooks follows:
- onSetupSession
This will be the first hook called when a session is created.
- afterSessionCreate
This will be called after all onSetupSession functions have been called.
- onBeginServicing
This will be called at the start of request processing.
- onEndServicing
This will be called at the end of request processing.
- onAboutToShutdownSession
This will be called just before a session is shut down (for example, when a session expires or the Lift application is being shut down).
- onShutdownSession
This will be called after all onAboutToShutdownSession functions have been run.
If you are testing these hooks, you might want to make the session expire faster than the 30 minutes of inactivity used by default in Lift. To do this, supply a millisecond value to LiftRules.sessionInactivityTimeout:
// 30 second inactivity timeout
LiftRules.sessionInactivityTimeout.default.set(Full(1000L * 30))
There are two other hooks in LiftSession: onSessionActivate and onSessionPassivate. These may be of use if you are working with a servlet container in distributed mode and want to be notified when the servlet HTTP session is about to be serialised (passivated) and deserialised (activated) between container instances. These hooks are rarely used.
Note that the Lift session is not the same as the HTTP session. Lift bridges from the HTTP session to its own session management. This is described in some detail in Exploring Lift.
See Also
Session management is discussed in section 9.5 of Exploring Lift.
[RunningStateless] shows how to run without state.
Run Code When Lift Shuts Down
You want to have some code executed when your Lift application is shutting down.
Append to LiftRules.unloadHooks:
LiftRules.unloadHooks.append( () => println("Shutting down") )
You append functions of type () => Unit to unloadHooks, and these functions are run right at the end of the Lift handler, after sessions have been destroyed, Lift actors have been shut down, and requests have finished being handled.
This is triggered, in the words of the Java servlet specification, "by the web container to indicate to a filter that it is being taken out of service."
See Also
[RunTasksPeriodically] includes an example of using an unload hook.
Running Stateless
You want to force your application to be stateless at the HTTP level.
In Boot.scala:
LiftRules.enableContainerSessions = false
LiftRules.statelessReqTest.append { case _ => true }
All requests will now be treated as stateless. Any attempt to use state, such as via SessionVar for example, will trigger a warning in developer mode: "Access to Lift's statefull features from Stateless mode. The operation on state will not complete."
HTTP session creation is controlled via enableContainerSessions, and applies for all requests. Leaving this value at the default (true) allows more fine-grained control over which requests are stateless.
Using statelessReqTest allows you to decide, based on the StatelessReqTest case class, if a request should be stateless (true) or not (false). For example:
def asset(file: String) =
List(".js", ".gif", ".css").exists(file.endsWith)
LiftRules.statelessReqTest.append {
case StatelessReqTest("index" :: Nil, httpReq) => true
case StatelessReqTest(List(_, file), _) if asset(file) => true
This example would only make the index page and any GIFs, JavaScript, and CSS files stateless. The httpReq part is an HTTPRequest instance, allowing you to base the decision on the content of the request (cookies, user agent, etc.).
Another option is LiftRules.statelessDispatch, which allows you to register a function that returns a LiftResponse. This will be executed without a session, and is convenient for REST-based services.
If you just need to mark an entry in SiteMap as being stateless, you can:
Menu.i("Stateless Page") / "demo" >> Stateless
A request for /demo would be processed without state.
See Also
[REST] contains recipes for REST-based services in Lift.
The Lift wiki gives further details on the processing of stateless requests.
This stateless request control was introduced in Lift 2.2. The announcement on the mailing list gives more details.
Catch Any Exception
You want a wrapper around all requests to catch exceptions and display something to the user.
Declare an exception handler in Boot.scala:
LiftRules.exceptionHandler.prepend {
case (runMode, request, exception) =>
logger.error("Failed at: "+request.uri)
In this example, all exceptions for all requests at all run modes are being matched, causing an error to be logged and a 500 (internal server) error to be returned to the browser.
The partial function you add to exceptionHandler needs to return a LiftResponse (i.e., something to send to the browser). The default behaviour is to return an XhtmlResponse, which in Props.RunModes.Development gives details of the exception, and in all other run modes simply says: "Something unexpected happened."
You can return any kind of LiftResponse, including RedirectResponse, JsonResponse, XmlResponse, JavaScriptResponse, and so on.
The previous example just sends a standard 500 error. That won't be very helpful to your users. An alternative is to render a custom message but retain the 500 status code that will be useful for external site-monitoring services, if you use them:
LiftRules.exceptionHandler.prepend {
case (runMode, req, exception) =>
logger.error("Failed at: "+req.uri)
val content = S.render(<lift:embed what="500" />, req.request)
XmlResponse(content.head, 500, "text/html", req.cookies)
Here we are sending back a response with a 500 status code, but the content is the Node that results from running src/main/webapp/template-hidden/500.html. Create that file with the message you want to show to users:

Something is wrong!

It's our fault - sorry

import net.liftweb.http.js.JsCmds._
val ajax = LiftRules.ajaxPath
LiftRules.exceptionHandler.prepend {
case (mode, Req(ajax :: _, _, PostRequest), ex) =>
logger.error("Error handing ajax")
You could test out this handling code by creating an Ajax button that always produces an exception:
package code.snippet
import net.liftweb.util.Helpers._
import net.liftweb.http.SHtml
class ThrowsException {
private def fail = throw new Error("not implemented")
def render = "*" #> SHtml.ajaxButton("Press Me", () => fail)
This Ajax example will jump in before Lift's default behaviour for Ajax errors. The default is to retry the Ajax command three times (LiftRules.ajaxRetryCount), and then execute LiftRules.ajaxDefaultFailure, which will pop up a dialog saying: "The server cannot be contacted at this time."
See Also
[Custom404] describes how to create a custom 404 (not found) page.
Streaming Content
You want to stream content back to the web client.
Use OutputStreamResponse, passing it a function that will write to the OutputStream that Lift supplies.
In this example, we'll stream all the integers from one, via a REST service:
package code.rest
import net.liftweb.http.{Req,OutputStreamResponse}
import net.liftweb.http.rest._
object Numbers extends RestHelper {
// Convert a number to a String, and then to UTF-8 bytes
// to send down the output stream.
def num2bytes(x: Int) = (x + "\n") getBytes("utf-8")
// Generate numbers using a Scala stream:
def infinite = Stream.from(1).map(num2bytes)
serve {
case Req("numbers" :: Nil, _, _) =>
OutputStreamResponse( out => infinite.foreach(out.write) )
Scala's Stream class is a way to generate a sequence with lazy evaluation. The values being produced by infinite are used as example data to stream back to the client.
Wire this into Lift in Boot.scala:
Visiting http://127.0.0.1:8080/numbers will generate a 200 status code and start producing the integers from 1. The numbers are produced quite quickly, so you probably don't want to try that in your web browser, but instead from something that is easier to stop, such as cURL.
OutputStreamResponse expects a function of type OutputStream => Unit. The OutputStream argument is the output stream to the client. This means the bytes we write to the stream are written to the client. The relevant line from the example is:
OutputStreamResponse(out => infinite.foreach(out.write))
We are making use of the write(byte[]) method on out, a Java OutputStream, and sending it the Array[Byte] being generated from our infinite stream.
Be aware that OutputStreamResponse is executed outside of the scope of S. This means if you need to access anything in the session, do so outside of the function you pass to OutputStreamResponse.
For more control over status codes, headers, and cookies, there are a variety of signatures for the OutputStreamResponse object. For the most control, create an instance of the OutputStreamResponse class:
case class OutputStreamResponse(
out: (OutputStream) => Unit,
size: Long,
headers: List[(String, String)],
cookies: List[HTTPCookie],
code: Int)
Note that setting size to -1 causes the Content-Length header to be skipped.
There are two related types of response: InMemoryResponse and StreamingResponse.
InMemoryResponse is useful if you have already assembled the full content to send to the client. The signature is straightforward:
case class InMemoryResponse(
data: Array[Byte],
headers: List[(String, String)],
cookies: List[HTTPCookie],
code: Int)
As an example, we can modify the recipe and force our infinite sequence of numbers to produce the first few numbers as an Array[Byte] in memory:
import net.liftweb.util.Helpers._
serve {
case Req(AsInt(n) :: Nil, _, _) =>
InMemoryResponse(infinite.take(n).toArray.flatten, Nil, Nil, 200)
The AsInt helper in Lift matches on an integer, meaning that a request starting with a number matches, and we'll return that many numbers from the infinite sequence. We're not setting headers or cookies, and this request produces what you'd expect:
$ curl http://127.0.0.1:8080/3 1 2 3
StreamingResponse pulls bytes into the output stream. This contrasts with OutputStreamResponse, where you are pushing data to the client.
Construct this type of response by providing a class with a read method that can be read from:
case class StreamingResponse(
data: {def read(buf: Array[Byte]): Int},
onEnd: () => Unit,
size: Long,
headers: List[(String, String)],
cookies: List[HTTPCookie],
code: Int)
Notice the use of a structural type for the data parameter. Anything with a matching read method can be given here, including java.io.InputStream objects, meaning StreamingResponse can act as a pipe from input to output. Lift pulls 8 K chunks from your StreamingResponse to send to the client.
Your data read function should follow the semantics of Java IO and return "the total number of bytes read into the buffer, or –1 if there is no more data because the end of the stream has been reached."
See Also
[ServingVideo] gives an example of streaming video data via REST.
The JavaDoc for InputStream gives the full contract for the read method.
Serving a File with Access Control
You have a file on disk and you want to allow users to download it, but only if they are allowed to. If they are not allowed to, you want to explain why.
Use RestHelper to serve the file or an explanation page.
For example, suppose we have the file /tmp/important and we only want selected requests to download that file from the /download/important URL. The structure for that would be:
package code.rest
import net.liftweb.util.Helpers._
import net.liftweb.http.rest.RestHelper
import net.liftweb.http.{StreamingResponse, LiftResponse, RedirectResponse}
import net.liftweb.common.{Box, Full}
import java.io.{FileInputStream, File}
object DownloadService extends RestHelper {
// (code explained below to go here)
serve {
case "download" :: Known(fileId) :: Nil Get req =>
if (permitted) fileResponse(fileId)
else Full(RedirectResponse("/sorry"))
We are allowing users to download "known" files. That is, files we approve of for access. We do this because opening up the filesystem to any unfiltered end user input pretty much means your server will be compromised.
For our example, Known is checking a static list of names:
val knownFiles = List("important")
object Known {
def unapply(fileId: String): Option[String] = knownFiles.find(_ == fileId)
For requests to these known resources, we convert the REST request into a Box[LiftResponse]. For permitted access we serve up the file:
private def permitted = scala.math.random < 0.5d
private def fileResponse(fileId: String): Box[LiftResponse] = for {
file <- Box !! new File("/tmp/"+fileId)
input <- tryo(new FileInputStream(file))
} yield StreamingResponse(input,
() => input.close,
If no permission is given, the user is redirected to /sorry.html.
All of this is wired into Lift in Boot.scala with:
By turning the request into a Box[LiftResponse], we are able to serve up the file, send the user to a different page, and also allow Lift to handle the 404 (Empty) cases.
If we added a test to see if the file existed on disk in fileResponse, that would cause the method to evaluate to Empty for missing files, which triggers a 404. As the code stands, if the file does not exist, the tryo would give us a Failure that would turn into a 404 error with a body of "/tmp/important (No such file or directory)."
Because we are testing for known resources via the Known extractor as part of the pattern for /download/, unknown resources will not be passed through to our File access code. Again, Lift will return a 404 for these.
Guard expressions can also be useful for these kinds of situations:
serve {
case "download" :: Known(id) :: Nil Get _ if permitted => fileResponse(id)
case "download" :: _ Get req => RedirectResponse("/sorry")
You can mix and match extractors, guards, and conditions in your response to best fit the way you want the code to look and work.
See Also
Chapter 24: Extractors from Programming in Scala.
Access Restriction by HTTP Header
You need to control access to a page based on the value of an HTTP header.
Use a custom If in SiteMap:
val HeaderRequired = If(
() => S.request.map(_.header("ALLOWED") == Full("YES")) openOr false,
"Access not allowed"
// Build SiteMap
val entries = List(
Menu.i("Header Required") / "header-required" >> HeaderRequired
In this example, header-required.html can only be viewed if the request includes an HTTP header called ALLOWED with a value of YES. Any other request for the page will be redirected with a Lift error notice of "Access not allowed."
This can be tested from the command line using a tool like cURL:
$ curl http://127.0.0.1:8080/header-required.html -H "ALLOWED:YES"
The If test ensures the () => Boolean function you supply as a first argument returns true before the page it applies to is shown. In this example, we'll get true if the request contains a header called ALLOWED, and the optional value of that header is Full("YES"). This is a LocParam (location parameter) that modifies the SiteMap item. It can be appended to any menu items you want using the >> method.
Note that without the header, the test will be false. This will mean links to the page will not appear in the menu generated by Menu.builder.
The second argument to the If() is what Lift does if the test isn't true when the user tries to access the page. It's a () => LiftResponse function. This means you can return whatever you like, including redirects to other pages. In the example, we are making use of a convenient implicit conversation from a String ("Access not allowed") to a notice with a redirection that will take the user to the home page.
If you visit the page without a header, you'll see a notice saying "Access not allowed." This will be the home page of the site, but that's just the default. You can request that Lift show a different page by setting LiftRules.siteMapFailRedirectLocation in Boot.scala:
LiftRules.siteMapFailRedirectLocation = "static" :: "permission" :: Nil
If you then try to access header-required.html without the header set, you'll be redirected to /static/permission and shown the content of whatever you put in that page.
See Also
The Lift wiki gives a summary of Lift's SiteMap and the tests you can include in site map entries.
There are further details in Chapter 7 of Exploring Lift, and "SiteMap and access control," Chapter 7 of Lift in Action (Perrett, 2012, Manning Publications, Co.).
Accessing HttpServletRequest
You have an API to call that requires access to the HttpServletRequest.
Cast S.request:
import net.liftweb.http.S
import net.liftweb.http.provider.servlet.HTTPRequestServlet
import javax.servlet.http.HttpServletRequest
def servletRequest: Box[HttpServletRequest] = for {
req <- S.request
inner <- Box.asA[HTTPRequestServlet](req.request)
} yield inner.req
You can then make your API call:
servletRequest.foreach { r => yourApiCall(r) }
Lift abstracts away from the low-level HTTP request, and from the details of the servlet container your application is running in. However, it's reassuring to know, if you absolutely need it, there is a way to get back down to the low level.
Note that the results of servletRequest is a Box, because there might not be a request when you evaluate servletRequest—or you might one day port to a different deployment environment and not be running on a standard Java servlet container.
As your code will have a direct dependency on the Java Servlet API, you'll need to include this dependency in your SBT build:
"javax.servlet" % "servlet-api" % "2.5" % "provided"
Force HTTPS Requests
You want to ensure clients are using HTTPS.
Add an earlyResponse function in Boot.scala redirecting HTTP requests to HTTPS equivalents. For example:
LiftRules.earlyResponse.append { (req: Req) =>
if (req.request.scheme != "https") {
val uriAndQuery = req.uri +
(req.request.queryString.map(s => "?"+s) openOr "")
val uri = "https://%s%s".format(req.request.serverName, uriAndQuery)
Full(PermRedirectResponse(uri, req, req.cookies: _*))
else Empty
The earlyResponse call is called early on in the Lift pipeline. It is used to execute code before a request is handled and, if required, exit the pipeline and return a response. The function signature expected is Req => Box[LiftResponse].
In this example, we are testing for a request that is not "https", and then formulating a new URL that starts "https" and appends to it the rest of the original URL and any query parameters. With this created, we return a redirection to the new URL, along with any cookies that were set.
By evaluating to Empty for other requests (i.e., HTTPS requests), Lift will continue passing the request through the pipeline as usual.
The ideal method to ensure requests are served using the correct scheme would be via web server configuration, such as Apache or Nginx. This isn't possible in some cases, such as when your application is deployed to a Platform as a Service (PaaS) such as CloudBees.
Amazon Load Balancer
For Amazon Elastic Load Balancer, note that you need to use an X-Forwarded-Proto header to detect HTTPS. As mentioned in their Overview of Elastic Load Balancing document, "Your server access logs contain only the protocol used between the server and the load balancer; they contain no information about the protocol used between the client and the load balancer."
In this situation, modify the test from req.request.scheme != "https" to:
req.header("X-Forwarded-Proto") != Full("https")
Via SiteMap
So far we've looked at redirecting all requests to HTTPS. If you only have a handful of pages to worry about, you can use a custom location parameter in SiteMap as an alternative:
val entries = List(
Menu.i("Home") / "index",
Menu.i("Login") / "login" >> HttpsOnly
We have two locations and we've marked the login page as having to be over HTTPS. HttpsOnly is the location parameter. It's not built-in, but we can define it from the building blocks included with Lift and the code we've already written:
// Given a request, turn it into a redirect to the HTTPS version of the page
def redirection(req: Req) : LiftResponse = {
val uriAndQuery = req.uri +
(req.request.queryString.map(s => "?"+s) openOr "")
val uri = "https://%s%s".format(req.request.serverName, uriAndQuery)
PermRedirectResponse(uri, req, req.cookies: _*)
// If the request is HTTP, give us a redirect to HTTPS
def httpsRedirect : Box[LiftResponse] =
for {
req <- S.request
scheme <- req.header("X-Forwarded-Proto")
if scheme == "http"
} yield redirection(req)
val HttpsOnly = TestAccess( () => httpsRedirect )
A recap of what we want to happen: any menu item marked as HttpsOnly should redirect itself to HTTPS unless it already is HTTPS. We can use TestAccess to achieve this. The function given to TestAccess must evaluate to a Box[LiftResponse]: if it's Empty, the request carries on as normal; if it's Full, the request is redirected to the contents of the box.
Our HttpsOnly implementation is to call httpsRedirect, where the for comprehension picks out the request, checks the scheme and only if it is "http" does it yield a Full[LiftResponse]. That's how HTTPS requests are allowed through (httpsRedirect evaluates to Empty) but HTTP request are turned into Full[PermRedirectResponse] and TestAccess performs the redirect.
It's worth noting that this also works out conveniently for local development. If locally there's no X-Forwarded-Proto header in the request, the HTTPS redirect won't be triggered. Of course that assumes the X-Forwarded-Proto checking works for you. If instead you're using the req.request.scheme check, you might also want to make an exception for running in development mode (Props.devMode evaluates to true in development mode).
Relational Database Persistence with Record and Squeryl
Squeryl is an object-relational mapping library. It converts Scala classes into tables, rows, and columns in a relational database, and provides a way to write SQL-like queries that are type-checked by the Scala compiler. The Lift Squeryl Record module integrates Squeryl with Record, meaning your Lift application can use Squeryl to store and fetch data while making use of the features of Record, such as data validation.
The code in this chapter can be found at https://github.com/LiftCookbook/cookbook_squeryl.
Configuring Squeryl and Record
You want to configure your Lift application to use Squeryl and Record.
Include the Squeryl-Record dependency in your build, and in Boot.scala, provide a database connection function to SquerylRecord.initWithSquerylSession.
For example, to configure Squeryl with PostgreSQL, modify build.sbt to add two dependencies, one for Squeryl-Record and one for the database driver:
libraryDependencies ++= {
val liftVersion = "2.5"
"net.liftweb" %% "lift-webkit" % liftVersion,
"net.liftweb" %% "lift-squeryl-record" % liftVersion,
"postgresql" % "postgresql" % "9.1-901.jdbc4"
In Boot.scala, we define a connection and register it with Squeryl:
def connection = DriverManager.getConnection(
"username", "password")
Session.create(connection, new PostgreSqlAdapter) )
All Squeryl queries need to run in the context of a transaction. One way to provide a transaction is to configure a transaction around all HTTP requests. This is also configured in Boot.scala:
import net.liftweb.squerylrecord.RecordTypeMode._
import net.liftweb.http.S
import net.liftweb.util.LoanWrapper
S.addAround(new LoanWrapper {
override def apply[T](f: => T): T = {
val result = inTransaction {
try {
} catch {
case e: LiftFlowOfControlException => Left(e)
result match {
case Right(r) => r
case Left(exception) => throw exception
This arranges for requests to be handled in the inTransaction scope. As Lift uses an exception for redirects, we catch this exception and throw it after the transaction completes, avoiding rollbacks after an S.redirectTo or similar.
You can use any JVM persistence mechanism with Lift. What Lift Record provides is a light interface around persistence with bindings to Lift's CSS transforms, screens, and wizards. Squeryl-Record is a concrete implementation to connect Record with Squeryl. This means you can use standard Record objects, which are effectively your schema, with Squeryl and write queries that are validated at compile time.
Plugging into Squeryl means initialising Squeryl's session management, which allows us to wrap queries in Squeryl's transaction and inTransaction functions. The difference between these two calls is that inTransaction will start a new transaction if one doesn't exist, whereas transaction always creates a new transaction.
By ensuring a transaction is available for all HTTP requests via addAround, we can write queries in Lift, and for the most part, do not have to establish transactions ourselves unless we want to. For example:
import net.liftweb.squerylrecord.RecordTypeMode._
val r = myTable.insert(MyRecord.createRecord.myField(aValue))
In this recipe, the PostgreSqlAdapter is used. Squeryl also supports: OracleAdapter, MySQLInnoDBAdapter and MySQLAdapter, MSSQLServer, H2Adapter, DB2Adapter, and DerbyAdapter.
See Also
The Squeryl Getting Started Guide links to more information about session management and configuration.
See [SquerylJNDI] for configuring connections via Java Naming and Directory Interface (JNDI).
Using a JNDI DataSource
You want to use a Java Naming and Directory Interface (JNDI) data source for your Record-Squeryl Lift application.
In Boot.scala, call initWithSquerylSession with a DataSource looked up from the JNDI context:
import javax.sql.DataSource
val ds = new InitialContext().
Session.create(ds.getConnection(), new MySQLAdapter) )
Replace mydb with the name given to your database in your JNDI configuration, and replace MySQLAdapter with the appropriate adapter for the database you are using.
JNDI is a service provided by the web container (e.g., Jetty, Tomcat) that allows you to configure a database connection in the container and then refer to the connection by name in your application. One advantage of this is that you can avoid including database credentials to your Lift source base.
The configuration of JNDI is different for each container, and may vary with versions of the container you use. The "See Also" section next includes links to the documentation pages for popular containers.
Some environments may also require that you to reference the JNDI resource in your src/main/webapp/WEB-INF/web.xml file:
See Also
Resources for JNDI configuration include:
An example on the Lift wiki for Apache and Jetty configuration.
The documentation for Jetty gives examples for various databases.
For Tomcat, see the JNDI configuration guide.
One-to-Many Relationship
You want to model a one-to-many relationship, such as a satellite belonging to a single planet, but a planet possibly having many satellites.
Use Squeryl's oneToManyRelation in your schema, and on your Lift model, include a reference from the satellite to the planet.
The objective is to model the relationship as shown in [SquerylPlanetOneToManyFigure].
In code:
package code.model
import org.squeryl.Schema
import net.liftweb.record.{MetaRecord, Record}
import net.liftweb.squerylrecord.KeyedRecord
import net.liftweb.record.field.{StringField, LongField}
import net.liftweb.squerylrecord.RecordTypeMode._
object MySchema extends Schema {
val planets = table[Planet]
val satellites = table[Satellite]
val planetToSatellites = oneToManyRelation(planets, satellites).
via((p,s) => p.id === s.planetId)
on(satellites) { s =>
declare(s.planetId defineAs indexed("planet_idx"))
class Planet extends Record[Planet] with KeyedRecord[Long] {
override def meta = Planet
override val idField = new LongField(this)
val name = new StringField(this, 256)
lazy val satellites = MySchema.planetToSatellites.left(this)
object Planet extends Planet with MetaRecord[Planet]
class Satellite extends Record[Satellite] with KeyedRecord[Long] {
override def meta = Satellite
override val idField = new LongField(this)
val name = new StringField(this, 256)
val planetId = new LongField(this)
lazy val planet = MySchema.planetToSatellites.right(this)
object Satellite extends Satellite with MetaRecord[Satellite]
This schema defines the two tables based on the Record classes, as table[Planet] and table[Satellite]. It establishes a oneToManyRelation based on (via) the planetId in the satellite table.
This gives Squeryl the information it needs to produce a foreign key to constrain the planetId to reference an existing record in the planet table. This can be seen in the schema generated by Squeryl. We can print the schema in Boot.scala with:
inTransaction {
which will print:
-- table declarations :
create table Planet (
name varchar(256) not null,
idField bigint not null primary key auto_increment
create table Satellite (
name varchar(256) not null,
idField bigint not null primary key auto_increment,
planetId bigint not null
-- indexes on Satellite
create index planet_idx on Satellite (planetId);
-- foreign key constraints :
alter table Satellite add constraint SatelliteFK1 foreign key (planetId)
references Planet(idField);
An index called planet_idx is declared on the planetId field to improve query performance during joins.
Finally, we make use of the planetToSatellites.left and right methods to establish lookup queries as Planet.satellites and Satellite.planet. We can demonstrate their use by inserting example data and running the queries:
inTransaction {
import code.model.MySchema._
val earth = planets.insert(Planet.createRecord.name("Earth"))
val mars = planets.insert(Planet.createRecord.name("Mars"))
// .save as a short-hand for satellite.insert when we don't need
// to immediately reference the record (save returns Unit).
Satellite.createRecord.name("The Moon").planetId(earth.idField.is).save
val deimos = satellites.insert(
Satellite.createRecord.name("Deimos").planetId(mars.idField.is) )
println("Deimos orbits: "+deimos.planet.single.name.is)
println("Moons of Mars are: "+mars.satellites.map(_.name.is))
Running this code produces the output:
Deimos orbits: Mars Moons of Mars are: List(Phobos, Deimos)
In this example code, we're calling deimos.planet.single, which returns one result or will throw an exception if the associated planet was not found. headOption is the safer way if there's a chance the record will not be found, as it will evaluate to None or Some[Planet].
The planetToSatellites.left method is not a simple collection of Satellite objects. It's a Squeryl Query[Satellite], meaning you can treat it like any other kind of Queryable[Satellite]. For example, we could ask for those satellites of a planet that are alphabetically after "E," which for Mars would match "Phobos":
mars.satellites.where(s => s.name gt "E").map(_.name)
The left method result is also a OneToMany[Satellite] that adds the following
- assign
Adds a new relationship, but does not update the database
- associate
Similar to assign, but updates the database
- deleteAll
Removes the relationships
The assign call gives the satellite the relationship to the planet:
val express = Satellite.createRecord.name("Mars Express")
The next time we query mars.satellites, we will find the Mars Express orbiter.
A call to associate would go one step further for us, making Squeryl insert or update the satellite automatically:
val express = Satellite.createRecord.name("Mars Express")
The third method, deleteAll, does what it sounds like it should do. It would execute the following SQL and return the number of rows removed:
delete from Satellite
The right side of the one-to-many also has additional methods added by ManyToOne[Planet] of assign and delete. Be aware that to delete the "one" side of a many-to-one, anything assigned to the record will need to have been deleted already to avoid a database constraint error that would arise from, for example, leaving satellites referencing nonexistent planets.
As left and right are queries, it means each time you use them you'll be sending a new query to the database. Squeryl refers to these forms as stateless relations.
The stateful versions of left and right look like this:
class Planet extends Record[Planet] with KeyedRecord[Long] {
lazy val satellites : StatefulOneToMany[Satellite] =
class Satellite extends Record[Satellite] with KeyedRecord[Long] {
lazy val planet : StatefulManyToOne[Planet] =
This change means the results of mars.satellites will be cached. Subsequent calls on that instance of a Planet won't trigger a round trip to the database. You can still associate new records or deleteAll records, which will work as you expect, but if a relationship is added or changed elsewhere you'll need to call refresh on the relation to see the change.
Which version should you use? That will depend on your application, but you can use both in the same record if you need to.
See Also
The Squeryl Relations page provides additional details.
Many-to-Many Relationship
You want to model a many-to-many relationship, such as a planet being visited by many space probes, but a space probe also visiting many planets.
Use Squeryl's manyToManyRelation in your schema, and implement a record to hold the join between the two sides of the relationship. [SquerylPlanetManyToManyFigure] shows the structure we will create in this recipe, where Visit is the record that will connect each many to the other many.
The schema is defined in terms of two tables, one for planets and one for space probes, plus a relationship between the two based on a third class, called Visit:
package code.model
import org.squeryl.Schema
import net.liftweb.record.{MetaRecord, Record}
import net.liftweb.squerylrecord.KeyedRecord
import net.liftweb.record.field.{IntField, StringField, LongField}
import net.liftweb.squerylrecord.RecordTypeMode._
import org.squeryl.dsl.ManyToMany
object MySchema extends Schema {
val planets = table[Planet]
val probes = table[Probe]
val probeVisits = manyToManyRelation(probes, planets).via[Visit] {
(probe, planet, visit) =>
(visit.probeId === probe.id, visit.planetId === planet.id)
class Planet extends Record[Planet] with KeyedRecord[Long] {
override def meta = Planet
override val idField = new LongField(this)
val name = new StringField(this, 256)
lazy val probes : ManyToMany[Probe,Visit] =
object Planet extends Planet with MetaRecord[Planet]
class Probe extends Record[Probe] with KeyedRecord[Long] {
override def meta = Probe
override val idField = new LongField(this)
val name = new StringField(this, 256)
lazy val planets : ManyToMany[Planet,Visit] =
object Probe extends Probe with MetaRecord[Probe]
class Visit extends Record[Visit] with KeyedRecord[Long] {
override def meta = Visit
override val idField = new LongField(this)
val planetId = new LongField(this)
val probeId = new LongField(this)
object Visit extends Visit with MetaRecord[Visit]
In Boot.scala, we can print out this schema:
inTransaction {
which will produce something like this, depending on the database in use:
-- table declarations :
create table Planet (
name varchar(256) not null,
idField bigint not null primary key auto_increment
create table Probe (
name varchar(256) not null,
idField bigint not null primary key auto_increment
create table Visit (
idField bigint not null primary key auto_increment,
planetId bigint not null,
probeId bigint not null
-- foreign key constraints :
alter table Visit add constraint VisitFK1 foreign key (probeId)
references Probe(idField);
alter table Visit add constraint VisitFK2 foreign key (planetId)
references Planet(idField);
Notice that the visit table will hold a row for each relationship between a planetId and probeId.
Planet.probes and Probe.planets provide an associate method to establish a new relationship. For example, we can establish a set of planets and probes:
val jupiter = planets.insert(Planet.createRecord.name("Jupiter"))
val saturn = planets.insert(Planet.createRecord.name("Saturn"))
val juno = probes.insert(Probe.createRecord.name("Juno"))
val voyager1 = probes.insert(Probe.createRecord.name("Voyager 1"))
and then connect them:
We can also use Probe.planets and Planet.probes as a query to look up the associations. To access all the probes that had visited each planet in a snippet, we can write this:
package code.snippet
class ManyToManySnippet {
def render =
"#planet-visits" #> planets.map { planet =>
".planet-name *" #> planet.name.is &
".probe-name *" #> planet.probes.map(_.name.is)
The snippet could be combined with a template like this:

Planet facts

Name will be here was visited by:

Probe name goes here

The top half of [SquerylManyToManyScreengrab] gives an example of the output from this snippet and template.
The Squeryl DSL manyToManyRelation(probes, planets).via[Visit] is the core element here connecting our Planet, Probe, and Visit records together. It allows us to access the "left" and "right" sides of the relationship in our model as Probe.planets and Planet.probes.
As with [SquerylOneToMany] for one-to-many relationships, the left and right sides are queries. When you ask for Planet.probes, the database is queried appropriately with a join on the Visit records:
(Visit.probeId = Probe.idField) and (Visit.planetId = ?)
Also as described in [SquerylOneToMany], there are stateful variants of left and right to cache the query results.
In the data we inserted into the database, we did not have to mention Visit. The Squeryl manyToManyRelation has enough information to know how to insert a visit as the relationship. Incidentally, it doesn't matter which way round we make the calls in a many-to-many relationship. The following two expressions are equivalent and result in the same database structure:
// ..or..
You might even wonder why we had to bother with defining a Visit record at all, but there are benefits in doing so. For example, you can attach additional information onto the join table, such as the year the probe visited a planet.
To do this, we modify the record to include the additional field:
class Visit extends Record[Visit] with KeyedRecord[Long] {
override def meta = Visit
override val idField = new LongField(this)
val planetId = new LongField(this)
val probeId = new LongField(this)
val year = new IntField(this)
Visit is still a container for the planetId and probeId references, but we also have a plain integer holder for the year of the visit.
To record a visit year, we need the assign method provided by ManyToMany[T]. This will establish the relationship but not change the database. Instead, it returns the instance Visit, which we can change and then store in the database:
The return type of assign in this case is Visit, and Visit has a year field. Inserting the Visit record via probeVisits will create a row in the table for visits.
To access this extra information on the Visit object, you can make use of a couple of methods provided by ManyToMany[T]:
- associations
A query returning the Visit objects related to the Planet.probes or Probe.planets
- associationMap
A query returning pairs of (Planet,Visit) or (Probe,Visit), depending on which side of the join you call it on (probes or planets)
For example, in a snippet, we could list all the space probes and, for each probe, show the planet it visited and what year it was there. The snippet would look like this:
"#probe-visits" #> probes.map { probe =>
".probe-name *" #> probe.name.is &
".visit" #> probe.planets.associationMap.collect {
case (planet, visit) =>
".planet-name *" #> planet.name.is &
".year" #> visit.year.is
We are using collect here rather than map just to match the (Planet,Visit) tuple and give the values meaningful names. You could also use (for { (planet, visit) <- probe.planets.associationMap } yield ...) if you prefer.
The lower half of [SquerylManyToManyScreengrab] demonstrates how this snippet would render when combined with the following template:

Probe facts

Space craft name visited:

Name here in n
To remove an association, use the dissociate or dissociateAll methods on the left or right queries. To remove a single association:
val numRowsChanged = juno.planets.dissociate(jupiter)
This would be executed in SQL as:
delete from Visit
probeId = ? and planetId = ?
To remove all the associations:
val numRowsChanged = jupiter.probes.dissociateAll
The SQL for this is:
delete from Visit
Visit.planetId = ?
What you cannot do is delete a Planet or Probe if that record still has associations in the Visit relationship. What you'd get is a referential integrity exception thrown. Instead, you'll need to dissociateAll first:
However, if you do want cascading deletes, you can achieve this by overriding the default behaviour in your schema:
// To automatically remove probes when we remove planets:
probeVisits.rightForeignKeyDeclaration.constrainReference(onDelete cascade)
// To automatically remove planets when we remove probes:
probeVisits.leftForeignKeyDeclaration.constrainReference(onDelete cascade)
This is part of the schema, in that it will change the table constraints, with printDdl producing this (depending on the database you use):
alter table Visit add constraint VisitFK1 foreign key (probeId)
references Probe(idField) on delete cascade;
alter table Visit add constraint VisitFK2 foreign key (planetId)
references Planet(idField) on delete cascade;
See Also
[SquerylOneToMany], on one-to-many relationships, discusses leftStateful and rightStateful relations, which are also applicable for many-to-many relationships.
Foreign keys and cascading deletes are described on the Squeryl Relations page.
Adding Validation to a Field
You want to add validation to a field in your model, so that users are informed of missing fields or fields that aren't acceptable to your application.
Override the validations method on your field and provide one or more validation functions.
As an example, imagine we have a database of planets and we want to ensure any new planets entered by users have names of at least five characters. We add this as a validation on our record:
class Planet extends Record[Planet] with KeyedRecord[Long] {
override def meta = Planet
override val idField = new LongField(this)
val name = new StringField(this, 256) {
override def validations =
valMinLen(5, "Name too short") _ :: super.validations
To check the validation, in our snippet we call validate on the record, which will return all the errors for the record:
package code
package snippet
import net.liftweb.http.{S,SHtml}
import net.liftweb.util.Helpers._
import model.MySchema._
class ValidateSnippet {
def render = {
val newPlanet = Planet.createRecord
def validateAndSave() : Unit = newPlanet.validate match {
case Nil =>
S.notice("Planet '%s' saved" format newPlanet.name.is)
case errors =>
"#planetName" #> newPlanet.name.toForm &
"type=submit" #> SHtml.onSubmitUnit(validateAndSave)
When the snippet runs, we render the Planet.name field and wire up a submit button to call the validateAndSave method.
If the newPlanet.validate call indicates there are no errors (Nil), we can save the record and inform the user via a notice. If there are errors, we render all of them with S.error.
The corresponding template could be:
<title>Planet Name Validation</title>

Add a planet

Planet names need to be at least 5 characters long.
<form class="ValidateSnippet?form">
Planet name:
<input id="planetName" type="text"></input>

Msg to appear here
<input type="submit"></input>
In this template, the error message is shown next to the input field, styled with a CSS class of errorClass. The success notice is shown near the top of the page, just below the
 heading, using a style called noticeBox.
The built-in validations are:
- valMinLen
Validates that a string is at least a given length, as shown previously
- valMaxLen
Validates that a string is not above a given length
- valRegex
Validates that a string matches the given pattern
An example of regular expression validation on a field would be:
import java.util.regex.Pattern
val url = new StringField(this, 1024) {
override def validations =
valRegex( Pattern.compile("^https?://.*"),
"URLs should start http:// or https://") _ ::
The list of errors from validate are of type List[FieldError]. The S.error method accepts this list and registers each validation error message so it can be shown on the page. It does this by associating the message with an ID for the field, allowing you to pick out just the errors for an individual field, as we do in this recipe. The ID is stored on the field, and in the case of Planet.name, it is available as Planet.name.uniqueFieldId. It's a Box[String] with a value of Full("name_id"). It is this name_id value that we used in the lift:Msg?id=name_id&errorClass=error markup to pick out just the error for this field.
You don't have to use S.error to display validation messages. You can roll your own display code, making use of the FieldError directly. As you can see from the source for FieldError, the error is available as a msg property:
case class FieldError(field: FieldIdentifier, msg: NodeSeq) {
override def toString = field.uniqueFieldId + " : " + msg
See Also
BaseField.scala in the Lift source code contains the definition of the built-in StringValidators.
[Forms] describes form processing, notices, and errors.
Custom Validation Logic
You want to provide your own validation logic and apply it to a field in a record.
Implement a function from the type of the field to List[FieldError], and reference the function in the validations on the field.
Here's an example: we have a database of planets, and when a user enters a new planet, we want the name to be unique. The name of the planet is a String, so we need to provide a function from String => List[FieldError].
With the validation function defined (valUnique, next), we include it in the list of validations on the name field:
import net.liftweb.util.FieldError
class Planet extends Record[Planet] with KeyedRecord[Long] {
override def meta = Planet
override val idField = new LongField(this)
val name = new StringField(this, 256) {
override def validations =
valUnique("Planet already exists") _ ::
private def valUnique(errorMsg: => String)(name: String): List[FieldError] =
Planet.unique_?(name) match {
case true => FieldError(this.name, errorMsg) :: Nil
case false => Nil
object Planet extends Planet with MetaRecord[Planet] {
def unique_?(name: String) = from(planets) { p =>
where(lower(p.name) === lower(name)) select(p)
The validation is triggered just like any other validation, as described in [FieldValidation].
By convention, validation functions have two argument lists: the first for the error message, and the second to receive the value to validate. This allows you to easily reuse your validation function on other fields. For example, if you wanted to validate that satellites have a unique name, you could use exactly the same function but provide a different error message.
The FieldError you return needs to know the field it applies to as well as the message to display. In the example, the field is name, but we've used this.name to avoid confusion with the name parameter passed into the valUnique function.
The example code has used text for the error message, but there is a variation of FieldError that accepts NodeSeq. This allows you to produce safe markup as part of the error if you need to. For example:
FieldError(this.name,
Please see our name policy
)
For internationalisation, you may prefer to pass in a key to the validation function, and resolve it via S.?:
val name = new StringField(this, 256) {
override def validations =
valUnique("validation.planet") _ ::
// ...combined with...
private def valUnique(errorKey: => String)(name: String): List[FieldError] =
Planet.unique_?(name) match {
case false => FieldError(this.name, S ? errorKey) :: Nil
case true => Nil
See Also
[FieldValidation] discusses field validation and the built-in validations.
Text localisation is discussed on the Lift wiki.
Modify a Field Value Before It Is Set
You want to modify the value of a field before storing it (for example, to clean a value by removing leading and trailing whitespace).
Override setFilter and provide a list of functions to apply to the field.
To remove leading and trailing whitespace entered by the user, the field would use the trim filter:
val name = new StringField(this, 256) {
override def setFilter = trim _ :: super.setFilter
The built-in filters are:
- crop
Enforces the field's min and max length by truncation
- trim
Applies String.trim to the field value
- toUpper and toLower
Change the case of the field value
- removeRegExChars
Removes matching regular expression characters
- notNull
Converts null values to an empty string
Filters are run before validation. This means if you have a minimum length validation and the trim filter, for example, users cannot pass the validation test by just including spaces on the end of the value they enter.
A filter for a String field would be of type String => String, and the setFilter function expects a List of these. Knowing this, it's straightforward to write custom filters. For example, here's is a filter that applies a simple form of title case on our name field:
def titleCase(in: String) =
collect {
case x :: xs => (Character.toUpperCase(x).toString :: xs).mkString
}.mkString(" ")
This function is splitting the input string on spaces, converting each word into a list of characters, converting the first character into uppercase, and then gluing the strings back together.
We install titleCase on a field like any other filter:
val name = new StringField(this, 256) {
override def setFilter =
trim _ :: titleCase _ :: super.setFilter
Now when a user enters "jaglan beta" as a planet name, it is stored in the database as "Jaglan Beta."
See Also
The best place to understand the filters is the trait StringValidators in the source for BaseField.
If you really do need to apply title case to a value, the Apache Commons WordUtils class provides ready-made functions for this.
Testing with Specs
You want to write Specs2 unit tests that access your database model with Squeryl and Record.
Use an in-memory database, and arrange for it to be set up before your test and destroyed after it.
There are three parts to this: including a database in your project and connecting to it in an in-memory mode; creating a reusable trait to set up the database; and then using the trait in your test.
The H2 database has an in-memory mode, meaning it won't save data to disk. It needs to be included in build.sbt as a dependency. Whilst you are editing build.sbt, also disable SBT's parallel test execution to prevent database tests from influencing each other:
libraryDependencies += "com.h2database" % "h2" % "1.3.170"
parallelExecution in Test := false
Create a trait to initialise the database and create the schema:
package code.model
import java.sql.DriverManager
import org.squeryl.Session
import org.squeryl.adapters.H2Adapter
import net.liftweb.util.StringHelpers
import net.liftweb.common._
import net.liftweb.http.{S, Req, LiftSession }
import net.liftweb.squerylrecord.SquerylRecord
import net.liftweb.squerylrecord.RecordTypeMode._
import org.specs2.mutable.Around
import org.specs2.execute.Result
trait TestLiftSession {
def session = new LiftSession("", StringHelpers.randomString(20), Empty)
def inSession[T](a: => T): T = S.init(Req.nil, session) { a }
trait DBTestKit extends Loggable {
Logger.setup = Full(net.liftweb.util.LoggingAutoConfigurer())
Logger.setup.foreach { _.apply() }
def configureH2() = {
"sa", ""),
new H2Adapter)
def createDb() {
inTransaction {
try {
} catch {
case e : Throwable =>
logger.error("DB Schema error", e)
throw e
case class InMemoryDB() extends Around with DBTestKit with TestLiftSession {
def around[T <% Result](testToRun: =>T) = {
inSession {
inTransaction {
In summary, this trail provides an InMemoryDB context for Specs2. This context ensures that the database is configured, the schema created, and a transaction is supplied around your test.
Finally, mix the trait into your test and execute in the scope of the InMemoryDB context.
As an example, using the schema from [SquerylOneToMany], we can test that the planet Mars has two moons:
package code.model
import org.specs2.mutable._
import net.liftweb.squerylrecord.RecordTypeMode._
import MySchema._
class PlanetsSpec extends Specification with DBTestKit {
"Planets" >> {
"know that Mars has two moons" >> InMemoryDB() {
val mars = planets.insert(Planet.createRecord.name("Mars"))
mars.satellites.size must_== 2
Running this with SBT's test command would show a success:
> test [info] PlanetsSpec [info] [info] Planets [info] + know that Mars has two moons [info] [info] [info] Total for specification PlanetsSpec [info] Finished in 1 second, 274 ms [info] 1 example, 0 failure, 0 error [info] [info] Passed: : Total 1, Failed 0, Errors 0, Passed 1, Skipped 0 [success] Total time: 3 s, completed 03-Feb-2013 11:31:16
The DBTestKit trait has to do quite a lot of work for us. At the lowest level, it loads the H2 driver and configures Squeryl with an in-memory connection. The mem part of the JDBC connection string (jdbc:h2:mem:dbname;DB_CLOSE_DELAY=-1) means that H2 won't try to persist the data to disk. The database just resides in memory, so there are no files in disk to maintain, and it runs quickly.
By default, when a connection is closed, the in-memory database is destroyed. In this recipe, we've disabled that by adding the DB_CLOSE_DELAY=-1, which will allow us to write unit tests that span connections if we want to.
The next step up from connection management is the creation of the database schema in memory. We do this in createDb by throwing away the schema and any data when we start a test, and create it afresh. If you have very common test datasets, this might be a good place to insert that data before your test runs.
These steps are brought together at the InMemoryDB class, which implements a Specs2 interface for code to run Around a test. We've also wrapped the test around a TestLiftSession. This provides an empty session, which is useful if you are accessing
In our specification itself, we mix in the DBTestKit and reference the InMemoryDB context on the tests that access the database. You'll note that we've used >> rather than Specs2's should and in that you may have seen elsewhere. This is to avoid name conflicts between Specs2 and Squeryl that you might come across.
As we disabled parallel execution with SBT, we also disable parallel execution in Specs2 with sequential. We are doing this to prevent a situation where one test might be expecting data that another test is modifying at the same time.
If all the tests in a specification are going to use the database, you can use the Specs2 AroundContextExample[T] to avoid having to mention InMemoryDB on every test. To do that, mix in AroundContextExample[InMemoryDB] and define aroundContext:
package code.model
import MySchema._
import org.specs2.mutable._
import org.specs2.specification.AroundContextExample
import net.liftweb.squerylrecord.RecordTypeMode._
class AlternativePlanetsSpec extends Specification with
AroundContextExample[InMemoryDB] {
def aroundContext = new InMemoryDB()
"Solar System" >> {
"know that Mars has two moons" >> {
val mars = planets.insert(Planet.createRecord.name("Mars"))
mars.satellites.size must_== 2
All the tests in AlternativePlanetsSpec will now be run with an InMemoryDB around them.
We've used a database with an in-memory mode for the advantages of speed and no files to clean up. However, you could use any regular database: you'd need to change the driver and connection string.
See Also
See the H2 database website for more about H2's in-memory database settings.
[MongoUnitTest] discusses unit testing with MongoDB, but the comments on SBT's other testing commands and testing in an IDE would apply to this recipe, too.
Store a Random Value in a Column
You need a column to hold a random value.
Use UniqueIdField:
import net.liftweb.record.field.UniqueIdField
val randomId = new UniqueIdField(this, 32) {}
Note the {} in the example; this is required as UniqueIdField is an abstract class.
The size value, 32, indicates how many random characters to create.
The UniqueIdField field is a kind of StringField and the default value for the field comes from StringHelpers.randomString. The value is randomly generated, but not guaranteed to be unique in the database.
The database column backing the UniqueIdField in this recipe will be a varchar(32) not null or similar. The value stored will look like:
As the value is made up of just letters and numbers, it makes it easy to use in URLs as there are no characters to escape. For example, it could be used in a link to allow a user to validate her account when sent the link over email, which is one of the uses in ProtoUser.
If you need to change the value, the reset method on the field will generate a new random string for the field.
If you need an automatic value that is even more likely to be unique per-row, you can add a field that wraps a universally unique identifier (UUID):
import java.util.UUID
val uuid = new StringField(this, 36) {
override def defaultValue = UUID.randomUUID().toString
This will automatically insert values of the form "6481a844-460a-a4e0-9191-c808e3051519" in records you create.
See Also
Java's UUID support includes a link to RFC 4122, which defines UUIDs.
Automatic Created and Updated Timestamps
You want created and updated timestamps on your records and would like them automatically updated when a row is added or updated.
Define the following traits:
package code.model
import java.util.Calendar
import net.liftweb.record.field.DateTimeField
import net.liftweb.record.Record
trait Created[T <: Created[T]] extends Record[T] {
self: T =>
val created: DateTimeField[T] = new DateTimeField(this) {
override def defaultValue = Calendar.getInstance
trait Updated[T <: Updated[T]] extends Record[T] {
self: T =>
val updated = new DateTimeField(this) {
override def defaultValue = Calendar.getInstance
def onUpdate = this.updated(Calendar.getInstance)
trait CreatedUpdated[T <: Updated[T] with Created[T]] extends
Updated[T] with Created[T] {
self: T =>
Add the trait to the model. For example, we can modify a Planet record to include the time the record was created and updated:
class Planet private () extends Record[Planet]
with KeyedRecord[Long] with CreatedUpdated[Planet] {
override def meta = Planet
// field entries as normal...
Finally, arrange for the updated field to be updated:
class MySchema extends Schema {
override def callbacks = Seq(
beforeUpdate[Planet] call {_.onUpdate}
Although there is a built-in net.liftweb.record.LifecycleCallbacks trait that allows you to trigger behaviour onUpdate, afterDelete, and so on, it is only for use on individual fields, rather than records. As our goal is to update the updated field when any part of the record changes, we can't use the LiftcycleCallbacks here.
Instead, the CreatedUpdated trait simplifies adding updated and created fields to a record, but we do need to remember to add a hook into the schema to ensure the updated value is changed when a record is modified. This is why we set the callbacks on the Schema.
The schema for records with CreatedUpdated mixed in will include two additional columns:
updated timestamp not null,
created timestamp not null
The timestamp is used for the H2 database. For other databases, the type may be
The values can be accessed like any other record field. Using the example data from [SquerylOneToMany], we could run the following:
val updated : Calendar = mars.updated.id
val created : Calendar = mars.created.is
If you only need created time, or updated time, just mix in the Created[T] or Updated[T] trait instead of CreatedUpdated[T].
It should be noted that onUpdate is called only on full updates and not on partial updates with Squeryl. A full update is when the object is altered and then saved; a partial update is where you attempt to alter objects via a query.
If you're interested in other automations for Record, the Squeryl schema callbacks support these triggered behaviours:
beforeInsert and afterInsert
beforeUpdate and afterUpdate
beforeDelete and afterDelete
See Also
Full and partial updates are described in Insert, Update, and Delete.
Logging SQL
You want to see the SQL being executed by Squeryl.
Add the following any time you have a Squeryl season, such as just before your query:
org.squeryl.Session.currentSession.setLogger( s => println(s) )
By providing a String => Unit function to setLogger, Squeryl will execute that function with the SQL it runs. In this example, we are simply printing the SQL to the console.
You'll probably want to use the logging facilities in Lift to capture SQL. For example:
package code.snippet
import net.liftweb.common.Loggable
import org.squeryl.Session
class MySnippet extends Loggable {
def render = {
Session.currentSession.setLogger( s => logger.info(s) )
// ...your snippet code here...
This will log queries according to the settings for the logging system, typically the Logback project configured in src/resources/props/default.logback.xml.
It can be inconvenient to have to enable logging in each snippet during development. To trigger logging for all snippets, you can modify the addAround call in Boot.scala ([ConfiguringSqueryl]) to include a setLogger call while inTransaction:
S.addAround(new LoanWrapper {
override def apply[T](f: => T): T = {
val result = inTransaction {
Session.currentSession.setLogger( s => logger.info(s) )
// ... rest of addAround as normal
See Also
You can learn about logging in Lift from the Logging wiki page.
Model a Column with MySQL MEDIUMTEXT
You want to use MySQL's MEDIUMTEXT for a column, but StringField doesn't have this option.
Use Squeryl's dbType in your schema:
object MySchema extends Schema {
on(mytable)(t => declare(
t.mycolumn defineAs dbType("MEDIUMTEXT")
This schema setting will give you the correct column type in MySQL:
create table mytable (
mycolumn MEDIUMTEXT not null
On the record you can use StringField as usual.
This recipe points towards the flexibility available with Squeryl's schema definition DSL. The column attribute in this example is just one of a variety of adjustments you can make to the default choices that Squeryl uses.
For example, you can use the syntax to chain column attributes for a single column, and also define multiple columns at the same time:
object MySchema extends Schema {
on(mytable)(t => declare(
t.mycolumn defineAs(dbType("MEDIUMTEXT"),indexed),
t.id definedAs(unique, named("MY_ID"))
See Also
The schema definition page for Squeryl gives examples of attributes you can apply to tables and columns.
MySQL Character Set Encoding
Some characters stored in your MySQL database are appearing as ???.
Ensure that:
LiftRules.early.append(_.setCharacterEncoding("UTF-8")) is included in Boot.scala.
?useUnicode=true&characterEncoding=UTF-8 is included in your JDBC connections URL.
Your MySQL database has been created using a UTF-8 character set.
There are a number of interactions here that can impact characters going into, and coming out of, a MySQL database. The basic problem is that bytes transferred across networks have no meaning unless you know the encoding.
The setCharacterEncoding("UTF-8") call in Boot.scala is being applied to every HTTPRequest that ultimately, in a servlet container, is applied to a ServletRequest. This is how parameters in a request are going to be interpreted by the servlet container when received.
The flip side of this is that responses from Lift are encoded as UTF-8. You'll see this in a number of places. For example, templates-hidden/default includes:
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
Also, the LiftResponse classes set the encoding as UTF-8.
Another aspect is how character data from Lift is sent to the database over the network. This is controlled by the parameters to the JDBC driver. The default for MySQL is to detect the encoding, but it seems from experience that this is not a great option, so we force the UTF-8 encoding.
Finally, the MySQL database itself needs to store the data as UTF-8. The default character encoding is not UTF-8, so you'll need to specify the encoding when you create the database:
CREATE DATABASE myDb CHARACTER SET utf8
See Also
Relational database persistence with Mapper
Sequence numbers and existing data
You have a table with data in it, but Lift inserts new records with a primary key starting from 1, or some other value that may already exist.
Work with the native sequence facility in your database to set the starting sequence value to be the value you want Lift to use.
The first step is to work out what value you want the sequence to start from. Most likely this will be just after the largest primary key ID in the table you're working with. With PostgreSQL, for example, you can check this via the psql command:
SELECT MAX(id) FROM mytable;
To find out what sequences exist, run \ds in psql. The sequence to change will contain the name of your table. You can then change the value:
ALTER SEQUENCE mytable_id_seq RESTART WITH 1000;
Lift defers to the database sequence facility to generate primary key values. If you insert data by-passing the sequence, the sequence value will not know about the specific primary key values you have used (this is not Lift-specific). The solution above resolves this by updating the starting sequence number to skip over the rows that already exist in your database.
The same instructions apply for using Record as well as Mapper.
See Also
Mailing list discussion "Mapper starts counting primary keys with key 1 in a non-empty table".
PostgreSQL Sequence Manipulation Functions.
MySQL AUTO-INCREMENT describes how to use ALTER TABLE to change the sequence value.
Updating ORACLE sequence involves changing the incrementing step to cover the values to skip.
Detect if the schema has changed
You do not want to automatically migrate your schema, but you want to know if it is out of date.
Run Schemifier and capture the changes it would make if allowed. For example, in Boot.scala:
val cmds = Schemifier.schemify(false, true, Schemifier.infoF _, User, Company)
if (!cmds.isEmpty) {
error("Database schema is out of date. The following is missing: \n"+
The arguments and return value for schemify are:
performWrite - the example uses false meaning the database won't be updated.
structureOnly - true to check the tables and columns (not indexes).
logFunc - for logging, but only if we are writing to the database, which we are not.
tables (mapper objects) - the tables to include.
The result is a List[String] which are the statements required to update the database.
From the above description you may be able to select the parameters that best fit your needs.
See Also
Schemifier.scala source.
MongoDB Persistence with Record
This chapter gives recipes for making use of MongoDB in your Lift application. Many of the code examples in this chapter can be found at https://github.com/LiftCookbook/cookbook_mongo.
Connecting to a MongoDB Database
You want to connect to a MongoDB database.
Add the Lift MongoDB dependencies to your build and configure a connection using net.liftweb.mongodb and com.mongodb.
In build.sbt, add the following to libraryDependencies:
"net.liftweb" %% "lift-mongodb-record" % liftVersion
In Boot.scala, add:
import com.mongodb.{ServerAddress, Mongo}
import net.liftweb.mongodb.{MongoDB,DefaultMongoIdentifier}
val server = new ServerAddress("127.0.0.1", 27017)
MongoDB.defineDb(DefaultMongoIdentifier, new Mongo(server), "mydb")
This will give you a connection to a local MongoDB database called mydb.
If your database needs authentication, use MongoDB.defineDbAuth:
MongoDB.defineDbAuth(DefaultMongoIdentifier, new Mongo(server),
"mydb", "username", "password")
Some cloud services will give you a URL to connect to, such as mongodb://alex.mongohq.com:10050/fglvBskrsdsdsDaGNs1. In this case, the host and the port make up the first part, and the database name is the part after the /.
If you need to turn a URL like this into a connection, you can do so by using java.net.URI to parse the URL and make a connection:
object MongoUrl {
def defineDb(id: MongoIdentifier, url: String) {
val uri = new URI(url)
val db = uri.getPath drop 1
val server = new Mongo(new ServerAddress(uri.getHost, uri.getPort))
Option(uri.getUserInfo).map(_.split(":")) match {
case Some(Array(user,pass)) =>
MongoDB.defineDbAuth(id, server, db, user, pass)
case _ =>
MongoDB.defineDb(id, server, db)
The full URL scheme for MongoDB is more complicated, allowing for multiple hosts and connection parameters, but the previous code handles optional username and password fields and may be enough to get you up and running with your MongoDB
The DefaultMongoIdentifier is a value used to identify a particular connection. Lift keeps a map of identifiers to connections, meaning you can connect to more than one database. The common case is a single database, and that is usually assigned to DefaultMongoIdentifier.
However, if you do need to access two MongoDB databases, you can create a new identifier and assign it as part of your record. For example:
object OtherMongoIdentifier extends MongoIdentifier {
def jndiName: String = "other"
MongoUrl.defineDb(OtherMongoIdentifier, "mongodb://127.0.0.1:27017/other")
object Country extends Country with MongoMetaRecord[Country] {
override def collectionName = "example.earth"
override def mongoIdentifier = OtherMongoIdentifier
The lift-mongodb-record dependency itself depends on another Lift module, lift-mongodb, which provides connectivity and other lower-level access to MongoDB. Both bottom out with the MongoDB Java driver.
See Also
Connection configuration that includes replica sets and MongoDB options, such as timeout settings, are described on the Lift wiki.
The full MongoDB connection format is described in Connection String URI Format.
Storing a Hash Map in a MongoDB Record
You want to store a hash map in MongoDB.
Create a MongoDB record that contains a MongoMapField:
import net.liftweb.mongodb.record._
import net.liftweb.mongodb.record.field._
class Country private () extends MongoRecord[Country] with StringPk[Country] {
override def meta = Country
object population extends MongoMapField[Country,Int](this)
object Country extends Country with MongoMetaRecord[Country] {
override def collectionName = "example.earth"
In this example, we are creating a record for information about a country, and the population is a map from a String key, representing a city in that country, to an Integer value, representing the population of that city.
We can use it in a snippet like this:
class Places {
val uk = Country.find("uk") openOr {
val info = Map(
"Brighton" -> 134293,
"Birmingham" -> 970892,
"Liverpool" -> 469017)
def facts = "#facts" #> (
for { (name,pop) <- uk.population.is } yield
".name *" #> name & ".pop *" #> pop
When this snippet is called, it looks up a record by _id of uk or creates it using some canned information. The template to go with the snippet could include:

Name here	Population
In MongoDB, the resulting data structure would be:
$ mongo cookbook
MongoDB shell version: 2.0.6
connecting to: cookbook
> show collections
> db.example.earth.find().pretty()
"_id" : "uk",
"population" : {
"Brighton" : 134293,
"Birmingham" : 970892,
"Liverpool" : 469017
If you do not set a value for the map, the default will be an empty map, represented in MongoDB as the following:
{ "_id" : "uk", "population" : { } }
An alternative is to mark the field as optional:
object population extends MongoMapField[Country,Int](this) {
override def optional_? = true
If you now write the document without a population set, the field will be omitted in MongoDB:
> db.example.earth.find();
{ "_id" : "uk" }
To append data to the map from your snippet, you can modify the record to supply a new Map:
uk.population(uk.population.is + ("Westminster"->81766)).update
Note that we are using update here, rather than save. The save method is pretty smart and will either insert a new document into a MongoDB collection or replace an existing document based on the _id. Update is different: it detects just the changed fields of the document and updates them. It will send this command to MongoDB for the document:
{ "$set" : { "population" : { "Brighton" : 134293 , "Liverpool" : 469017 ,
"Birmingham" : 970892 , "Westminster" : 81766} }
You'll probably want to use update over save for changes to existing records.
To access an individual element of the map, you can use get (or value):
uk.population.get("San Francisco")
// will throw java.util.NoSuchElementException
or you can access via the standard Scala map interface:
val sf : Option[Int] = uk.population.is.get("San Francisco")
What a MongoMapField can contain
You should be aware that MongoMapField supports only primitive types.
The mapped field used in this recipe is typed String => Int, but of course MongoDB will let you mix types such as putting a String or a Boolean as a population value. If you do modify the MongoDB record in the database outside of Lift and mix types, you'll get a java.lang.ClassCastException at runtime.
See Also
There's a discussion on the mailing list regarding the limited type support in MongoMapField and a possible way around it by overriding
Storing an Enumeration in MongoDB
You want to store an enumeration in a MongoDB document.
Use EnumNameField to store the string value of the enumeration. Here's an example using days of the week:
object DayOfWeek extends Enumeration {
type DayOfWeek = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
We can use this to model someone's birth day-of-week:
package code.model
import net.liftweb.mongodb.record._
import net.liftweb.mongodb.record.field._
import net.liftweb.record.field.EnumNameField
class Birthday private () extends MongoRecord[Birthday] with StringPk[Birthday]{
override def meta = Birthday
object dow extends EnumNameField(this, DayOfWeek)
object Birthday extends Birthday with MongoMetaRecord[Birthday]
When creating records, the dow field will expect a DayOfWeek value:
import DayOfWeek._
Birthday.createRecord.id("Albert Einstein").dow(Fri).save
Birthday.createRecord.id("Richard Feynman").dow(Sat).save
Birthday.createRecord.id("Isaac Newton").dow(Sun).save
Take a look at what's stored in MongoDB:
> db.birthdays.find()
{ "_id" : "Albert Einstein", "dow" : "Fri" }
{ "_id" : "Richard Feynman", "dow" : "Sat" }
{ "_id" : "Isaac Newton", "dow" : "Sun" }
The dow value is the toString of the enumeration, not the id value:
Fri.toString // java.lang.String = Fri
Fri.id // Int = 4
If you want to store the ID, use EnumField instead.
Be aware that other tools, notably Rogue, expect the string value, not the integer ID, of an enumeration, so you may prefer to use EnumNameField for that reason.
See Also
[QueryingWithRogue] introduces Rogue.
Embedding a Document Inside a MongoDB Record
You have a MongoDB record, and you want to embed another set of values inside it as a single entity.
Use BsonRecord to define the document to embed, and embed it using BsonRecordField. Here's an example of storing information about an image within a record:
import net.liftweb.record.field.{IntField,StringField}
class Image private () extends BsonRecord[Image] {
def meta = Image
object url extends StringField(this, 1024)
object width extends IntField(this)
object height extends IntField(this)
object Image extends Image with BsonMetaRecord[Image]
We can reference instances of the Image class via BsonRecordField:
class Country private () extends MongoRecord[Country] with StringPk[Country] {
override def meta = Country
object flag extends BsonRecordField(this, Image)
object Country extends Country with MongoMetaRecord[Country] {
override def collectionName = "example.earth"
To associate a value:
val unionJack =
In MongoDB, the resulting data structure would be:
> db.example.earth.findOne()
"_id" : "uk",
"flag" : {
"url" : "http://bit.ly/unionflag200",
"width" : 200,
"height" : 100
If you don't set a value on the embedded document, the default will be saved as:
"flag" : { "width" : 0, "height" : 0, "url" : "" }
You can prevent this by making the image optional:
object image extends BsonRecordField(this, Image) {
override def optional_? = true
With optional_? set in this way, the image part of the MongoDB document won't be saved if the value is not set. Within Scala you will then want to access the value with a valueBox call:
val img : Box[Image] = uk.flag.valueBox
In fact, regardless of the setting of optional_?, you can access the value using valueBox.
An alternative to optional values is to always provide a default value for the embedded document:
object image extends BsonRecordField(this, Image) {
override def defaultValue =
See Also
The Lift wiki describes BsonRecord in more detail.
Linking Between MongoDB Records
You have a MongoDB record and want to include a link to another record.
Create a reference using a MongoRefField such as ObjectIdRefField or StringRefField, and dereference the record using the obj call.
As an example, we can create records representing countries, where a country references the planet where you can find it:
class Planet private() extends MongoRecord[Planet] with StringPk[Planet] {
override def meta = Planet
object review extends StringField(this,1024)
object Planet extends Planet with MongoMetaRecord[Planet] {
override def collectionName = "example.planet"
class Country private () extends MongoRecord[Country] with StringPk[Country] {
override def meta = Country
object planet extends StringRefField(this, Planet, 128)
object Country extends Country with MongoMetaRecord[Country] {
override def collectionName = "example.country"
To make this example easier to follow, our model mixes in StringPk[Planet] to use strings as the primary key on our documents, rather than the more usual MongoDB object IDs. Consequently, the link is established with a StringRefField.
In a snippet we can make use of the planet reference by resolving it with .obj:
class HelloWorld {
val uk = Country.find("uk") openOr {
val earth = Planet.createRecord.id("earth").review("Harmless").save
def facts =
".country *" #> uk.id &
".planet" #> uk.planet.obj.map { p =>
".name *" #> p.id &
".review *" #> p.review
For the value uk, we look up an existing record, or create one if none is found. We create earth as a separate MongoDB record, and then reference it in the planet field with the ID of the planet.
Retrieving the reference is via the obj method, which returns a Box[Planet] in this example.
Referenced records are fetched from MongoDB when you call the obj method on a MongoRefField. You can see this by turning on logging in the MongoDB driver. Do this by adding the following to the start of your Boot.scala:
System.setProperty("DEBUG.MONGO", "true")
System.setProperty("DB.TRACE", "true")
Having done this, the first time you run the previous snippet, your console will include:
INFO: find: cookbook.example.country { "_id" : "uk"} INFO: update: cookbook.example.planet { "_id" : "earth"} { "_id" : "earth" , "review" : "Harmless"} INFO: update: cookbook.example.country { "_id" : "uk"} { "_id" : "uk" , "planet" : "earth"} INFO: find: cookbook.example.planet { "_id" : "earth"}
What you're seeing here is the initial lookup for uk, followed by the creation of the earth record and an update that is saving the uk record. Finally, there is a lookup of earth when uk.obj is called in the facts method.
The obj call will cache the planet reference. That means you could say:
".country *" #> uk.id &
".planet *" #> uk.planet.obj.map(_.id) &
".review *" #> uk.planet.obj.map(_.review)
and you'd still only see one query for the earth record despite calling obj multiple times. The flip side of that is if the earth record was updated elsewhere in MongoDB after you called obj you would not see the change from a call to uk.obj unless you reloaded the uk record first.
Querying by reference
Searching for records by a reference is straightforward:
val earth : Planet = ...
val onEarth : List[Country] = Country.findAll(Country.planet.name, earth.id.is)
Or in this case, because we have String references, we could just say:
val onEarth : List[Country] = Country.findAll(Country.planet.name, "earth")
Updating and deleting
Updating a reference is as you'd expect:
uk.planet.obj.foreach(_.review("Mostly harmless.").update)
This would result in the changed field being set:
INFO: update: cookbook.example.planet { "_id" : "earth"} { "$set" : { "review" : "Mostly harmless."}}
A uk.planet.obj call will now return a planet with the new review.
Or you could replace the reference with another:
uk.planet( Planet.createRecord.id("mars").save.id.is ).save
Again, note that the reference is via the ID of the record (id.is), not the record itself.
To remove the reference:
This removes the link, but the MongoDB record pointed to by the link will remain in the database. If you remove the object being referenced, a later call to obj will return an Empty box.
Types of link
The example uses a StringRefField, as the MongoDB records themselves use String as the _id. Other reference types are:
- ObjectIdRefField
This is possibly the most frequently used kind of reference, when you want to reference via the usual default ObjectId in MongoDB.
- UUIDRefField
This is used for records with an ID based on java.util.UUID.
- StringRefField
This is used in this example, where you control the ID as a String.
- IntRefField and LongRefField
This is used when you have a numeric value as an ID.
See Also
10Gen, Inc.'s Data Modeling Decisions describes embedding of documents compared to referencing objects.
Using Rogue
You want to use Foursquare's type-safe domain specific language (DSL), Rogue, for querying and updating MongoDB records.
You need to include the Rogue dependency in your build and import Rogue into your code.
For the first step, edit build.sbt and add:
"com.foursquare" %% "rogue" % "1.1.8" intransitive()
In your code, run import com.foursquare.rogue._ and then start using Rogue. For example, using the Scala console (see [MongoScalaConsole]):
scala> import com.foursquare.rogue.Rogue._
import com.foursquare.rogue.Rogue._
scala> import code.model._
import code.model._
scala> Country.where(_.id eqs "uk").fetch
res1: List[code.model.Country] = List(class code.model.Country={_id=uk,
population=Map(Brighton->134293, Liverpool->469017, Birmingham->970892)})
scala> Country.where(_.id eqs "uk").count
res2: Long = 1
scala> Country.where(_.id eqs "uk").
modify(_.population at "Brighton" inc 1).updateOne()
Rogue is able to use information in your Lift record to offer an elegant way to query and update records. It's type-safe, meaning, for example, if you try to use an Int where a String is expected in a query, MongoDB would allow that and fail to find results at runtime, but Rogue enables Scala to reject the query at compile time:
scala> Country.where(_.id eqs 7).fetch
<console>:20: error: type mismatch;
found : Int(7)
required: String
Country.where(_.id eqs 7).fetch
The DSL constructs a query that we then fetch to send the query to MongoDB. That last method, fetch, is just one of the ways to run the query. Others include:
- count
Queries MongoDB for the size of the result set
- countDistinct
Shows the number of distinct values in the results
- exists
True if there's any record that matches the query
- get
Returns an Option[T] from the query
- fetch(limit: Int)
Similar to fetch, but returns at most limit results
- updateOne, updateMulti, upsertOne, and upsertMulti
Modify a single document, or all documents, that match the query
- findAndDeleteOne and bulkDelete_!!
Delete records
The query language itself is expressive, and the best place to explore the variety of queries is in the QueryTest specification in the source for Rogue. You'll find a link to this in the README of the project on GitHub.
|Rogue is working towards a version 2 release that introduces a number of new concepts. If you want to give it a try, take a look at the instructions and comments on the Rogue mailing list.
See Also
For geospacial queries, see [MongoGeospatial].
The README page for Rogue is a great starting point, and includes a link to QueryTest giving plenty of example queries to crib.
The motivation for Rogue is described in a Foursquare engineering blog post.
Storing Geospatial Values
You want to store latitude and longitude information in MongoDB.
Use Rogue's LatLong class to embed location information in your model. For example, we can store the location of a city like this:
import com.foursquare.rogue.Rogue._
import com.foursquare.rogue.LatLong
class City private () extends MongoRecord[City] with ObjectIdPk[City] {
override def meta = City
object name extends StringField(this, 60)
object loc extends MongoCaseClassField[City, LatLong](this)
object City extends City with MongoMetaRecord[City] {
import net.liftweb.mongodb.BsonDSL._
ensureIndex(loc.name -> "2d", unique=true)
override def collectionName = "example.city"
We can store values like this:
val place = LatLong(50.819059, -0.136642)
val city = City.createRecord.name("Brighton, UK").loc(pos).save(true)
This will produce data in MongoDB that looks like this:
"_id" : ObjectId("50f2f9d43004ad90bbc06b83"),
"name" : "Brighton, UK",
"loc" : {
"lat" : 50.819059,
"long" : -0.136642
MongoDB supports geospatial indexes, and we're making use of this by doing two things. First, we are storing the location information in one of MongoDB's permitted formats. The format is an embedded document containing the coordinates. We could also have used an array of two values to represent the point.
Second, we're creating an index of type 2d, which allows us to use MongoDB's geospatial functions such as $near and $within. The unique=true in the ensureIndex highlights that you can control whether locations needs to be unique (true, no duplications) or not (false).
With regard to the unique index, you'll note that we're calling save(true) on the City in this example, rather than the plain save in most other recipes. We could use save here, and it would work fine, but the difference is that save(true) raises the write concern level from "normal" to "safe."
With the normal write concern, the call to save would return as soon as the request has gone down the wire to the MongoDB server. This gives a certain degree of reliability in that save would fail if the network had gone away. However, there's no indication that the server has processed the request. For example, if we tried to insert a city at the exact same location as one that was already in the database, the index uniqueness rule would be violated and the record would not be saved. With just save (or save(false)), our Lift application would not receive this error, and the call would fail silently. Raising the concern to "safe" causes save(true) to wait for an acknowledgment from the MongoDB server, which means the application will receive exceptions for some kinds of errors.
As an example, if we tried to insert a duplicate city, our call to save(true) would
com.mongodb.MongoException$DuplicateKey: E11000 duplicate key
error index: cookbook.example.city.$loc_2d
There are other levels of write concern, available via another variant of save that takes a WriteConcern as an argument.
If you ever need to drop an index, the MongoDB command is:
db.example.city.dropIndex( "loc_2d" )
The reason this recipe uses Rogue's LatLong class is to enable us to query using the Rogue DSL. Suppose we've inserted other cities into our collection:
> db.example.city.find({}, {_id:0} )
{"name": "London, UK", "loc": {"lat": 51.5, "long": -0.166667} }
{"name": "Brighton, UK", "loc": {"lat": 50.819059, "long": -0.136642} }
{"name": "Paris, France", "loc": {"lat": 48.866667, "long": 2.333333} }
{"name": "Berlin, Germany", "loc": {"lat": 52.533333, "long": 13.416667} }
{"name": "Sydney, Australia", "loc": {"lat": -33.867387, "long": 151.207629} }
{"name": "New York, USA", "loc": {"lat": 40.714623, "long": -74.006605} }
We can now find those cities within 500 kilometers of London:
import com.foursquare.rogue.{LatLong, Degrees}
val centre = LatLong(51.5, -0.166667)
val radius = Degrees( (500 / 6378.137).toDegrees )
val nearby = City.where( _.loc near (centre.lat, centre.long, radius) ).fetch()
This would query MongoDB with this clause:
{ "loc" : { "$near" : [ 51.5 , -0.166667 , 4.491576420597608]}}
which will identify London, Brighton, and Paris as near to London.
The form of the query is a centre point and a spherical radius. Records falling inside that radius match the query and are returned closest first. We calculate the radius in radians: 500 km divided by the radius of the Earth, approximately 6,378 km, gives us an angle in radians. We convert this to Degrees as required by Rogue.
See Also
The MongoDB Manual discusses geospatial indexes.
Learn more about write concerns from the MongoDB Manual.
Running Queries from the Scala Console
You want to try out a few queries interactively from the Scala console.
Start the console from your project, call boot(), and then interact with your model.
For example, using the MongoDB records developed as part of [ConnectingToMongo], we can perform a basic query:
$ sbt ... > console [info] Compiling 1 Scala source to /cookbook_mongo/target/scala-2.9.1/classes... [info] Starting scala interpreter... [info] Welcome to Scala version 2.9.1.final ... Type in expressions to have them evaluated. Type :help for more information. scala> import bootstrap.liftweb._ import bootstrap.liftweb._ scala> new Boot().boot scala> import code.model._ import code.model._ scala> Country.findAll res2: List[code.model.Country] = List(class code.model.Country={_id=uk, population=Map(Brighton -> 134293, Liverpool -> 469017, Birmingham -> 970892)}) scala> :q
Running everything in Boot may be a little heavy handed, especially if you are starting up various services and background tasks. All we need to do is define a database
scala> import bootstrap.liftweb._ import bootstrap.liftweb._ scala> import net.liftweb.mongodb._ import net.liftweb.mongodb._ scala> MongoUrl.defineDb(DefaultMongoIdentifier, "mongodb://127.0.0.1:27017/cookbook") scala> Country.findAll res2: List[code.model.Country] = List(class code.model.Country={_id=uk, population=Map(Brighton -> 134293, Liverpool -> 469017, Birmingham -> 970892)})
See Also
[ConnectingToMongo] explains connecting to MongoDB and [QueryingWithRogue] describes querying with Rogue.
Unit Testing Record with MongoDB
You want to write unit tests to run against your Lift Record code with MongoDB.
Using the Specs2 testing framework, surround your specification with a context that creates and connects to a database for each test and destroys it after the test runs.
First, create a Scala trait to set up and destroy a connection to MongoDB. We'll be mixing this trait into our specifications:
import net.liftweb.http.{Req, S, LiftSession}
import net.liftweb.util.StringHelpers
import net.liftweb.common.Empty
import net.liftweb.mongodb._
import com.mongodb.ServerAddress
import com.mongodb.Mongo
import org.specs2.mutable.Around
import org.specs2.execute.Result
trait MongoTestKit {
val server = new Mongo(new ServerAddress("127.0.0.1", 27017))
def dbName = "test_"+this.getClass.getName
.replace(".", "_")
def initDb() : Unit = MongoDB.defineDb(DefaultMongoIdentifier, server, dbName)
def destroyDb() : Unit = {
MongoDB.use(DefaultMongoIdentifier) { d => d.dropDatabase() }
trait TestLiftSession {
def session = new LiftSession("", StringHelpers.randomString(20), Empty)
def inSession[T](a: => T): T = S.init(Req.nil, session) { a }
object MongoContext extends Around with TestLiftSession {
def around[T <% Result](testToRun: =>T) = {
try {
inSession {
} finally {
This trait provides the plumbing for connection to a MongoDB server running locally, and creates a database based on the name of the class it is mixed into. The important part is the MongoContext, which ensures that around your specification the database is initialised, and that after your specification is run, it is cleaned up.
Specs2 2.x and Scala 2.10
If you're using Scala 2.10, you'll also be using a newer version of Specs2, and in that case MongoContent needs to be modified. For Specs2 2.1 you'll need this code:
object MongoContext extends Around with TestLiftSession {
def around[T : AsResult](testToRun: =>T) : Result = {
try {
inSession {
} finally {
The changes in the 2.x series of Specs2 are documented on Eric Torreborre's blog.
To use this in a specification, mix in the trait and then add the context:
import org.specs2.mutable._
class MySpec extends Specification with MongoTestKit {
"My Record" should {
"be able to create records" in MongoContext {
val r = MyRecord.createRecord
// ...your useful test here...
r.valueBox.isDefined must beTrue
You can now run the test in SBT by typing test:
> test [info] Compiling 1 Scala source to target/scala-2.9.1/test-classes... [info] My Record should [info] + be able to create records [info] [info] [info] Total for specification MySpec [info] Finished in 1 second, 199 ms [info] 1 example, 0 failure, 0 error [info] [info] Passed: : Total 1, Failed 0, Errors 0, Passed 0, Skipped 0 [success] Total time: 1 s, completed 03-Jan-2013 22:47:54
Lift normally provides all the scaffolding you need to connect and run against MongoDB. Without a running Lift application, we need to ensure MongoDB is configured when our tests run outside of Lift, and that's what the MongoTestKit trait is providing for us.
The one unusual part of the test setup is including a TestLiftSession. This provides an empty session around your test, which is useful if you are accessing or testing state-related code (e.g., access to S). It's not strictly necessary for running tests against Record, but it has been included here because you may want to do that at some point, for example if you are testing user login via MongoDB records.
There are a few nice tricks in SBT to help you run tests. Running test will run all the tests in your project. If you want to focus on just one test, you can:
> test-only org.example.code.MySpec
This command also supports wildcards, so if we only wanted to run tests that start with the word "Mongo" we could:
> test-only org.example.code.Mongo*
There's also test-quick (in SBT 0.12), which will only run tests that have not been run, have changed, or failed last time, and ~test to watch for changes in tests and run them.
test-only together with modifications to around in MongoTestKit can be a good way to track down any issues you have with a test. By disabling the call to destroyDb(), you can jump into the MongoDB shell and examine the state of the database after a test
Database cleanup
Around each test, we've simply deleted the database so the next time we try to use it, it'll be empty. In some situations, you may not be able to do this. For example, if you're running tests against a database hosted with companies such as MongoLabs or MongoHQ, then deleting the database will mean you won't be able to connect to it next time you run.
One way to resolve that is to clean up each individual collection, by defining the collections you need to clean up and replacing destroyDb with a method that will remove all entries in those collections:
lazy val collections : List[MongoMetaRecord[_]] = List(MyRecord)
def destroyDb() : Unit = {
collections.foreach(_ bulkDelete_!! new BasicDBObject)
Note that the collection list is lazy to avoid start up of the Record system before we've initialised our database connections.
Parallel tests
If your tests are modifying data and have the potential to interact, you'll want to stop SBT from running your tests in parallel. A symptom of this would be tests that fail apparently randomly, or working tests that stop working when you add a new test, or tests that seem to lock up. Disable by adding the following to build.sbt:
parallelExecution in Test := false
You'll notice that the example specification includes the line: sequential. This disables the default behaviour in Specs2 of running all tests concurrently.
Running tests in IDEs
IntelliJ IDEA detects and allows you to run Specs2 tests automatically. With Eclipse, you'll need to include the JUnit runner annotation at the start of your specification:
import org.junit.runner.RunWith
import org.specs2.runner.JUnitRunner
class MySpec extends Specification with MongoTestKit {
You can then "Run As…" the class in Eclipse.
See Also
The Specs2 site contains examples and a user guide.
If you prefer to use the Scala Test framework, take a look at Tim Nelson's Mongo Auth Lift module. It includes tests using that framework. Much of what Tim has written there has been adapted to produce this recipe for Specs2.
The Lift MongoDB Record library includes a variation on testing with Specs2, using just Before and After rather than the around example used in this recipe.
Flapdoodle provides a way to automate the download, install, setup, and cleanup of a MongoDB database. This automation is something you can wrap around your unit tests, and a Specs2 integration is included using the same Before and After approach to testing used by Lift MongoDB Record.
The test interface provided by SBT, such as the test command, also supports the ability to fork tests, set specific configurations for test cases, and ways to select which tests are run.
The Lift wiki describes more about unit testing and Lift sessions.
Around Lift
This chapter looks at interacting with other systems from within Lift, such as sending email, calling URLs, or scheduling tasks.
Many of the recipes in this chapter have code examples in a project at https://github.com/LiftCookbook/cookbook_around.
Sending Plain-Text Email
You want to send a plain-text email from your Lift application.
Use the Mailer:
import net.liftweb.util.Mailer
import net.liftweb.util.Mailer._
PlainMailBodyType("Hello from Lift") )
Mailer sends the message asynchronously, meaning sendMail will return immediately, so you don't have to worry about the time costs of negotiating with an SMTP server. However, there's also a blockingSendMail method if you do need to wait.
By default, the SMTP server used will be localhost. You can change this by setting the mail.smtp.host property. For example, edit src/mail/resources/props/default.props and add the line:
The signature of sendMail requires a From, Subject, and then any number of MailTypes:
- To, CC, and BCC
The recipient email address
- ReplyTo
The address that mail clients should use for replies
- MessageHeader
Key/value pairs to include as headers in the message
- PlainMailBodyType
A plain-text email sent with UTF-8 encoding
- PlainPlusBodyType
A plain-text email, where you specify the encoding
- XHTMLMailBodyType
For HTML email ([HTMLEmail])
- XHTMLPlusImages
For attachments ([EmailWithAttachments])
In the previous example, we added two types: PlainMailBodyType and To. Adding more is as you'd expect:
MessageHeader("X-Ignore-This", "true"),
PlainMailBodyType("Hello from Lift") )
The address-like MailTypes (To, CC, BCC, ReplyTo) can be given an optional "personal name":
From("firstname.lastname@example.com", Full("Example Corporation"))
This would appear in your mailbox as:
From: Example Corporation <firstname.lastname@example.com>
The default character set is UTF-8. If you need to change this, replace the use of PlainMailBodyType with PlainPlusBodyType("Hello from Lift", "ISO8859_1").
See Also
[EmailWithAttachments] describes email with attachments.
For HTML email, see [HTMLEmail].
Logging Email Rather than Sending
You don't want email sent when developing your Lift application locally, but you do want to see what would have been sent.
Assign a logging function to Mailer.devModeSend in Boot.scala:
import net.liftweb.util.Mailer._
import javax.mail.internet.{MimeMessage,MimeMultipart}
Mailer.devModeSend.default.set( (m: MimeMessage) =>
logger.info("Would have sent: "+m.getContent)
When you send an email with Mailer, no SMTP server will be contacted, and instead, you'll see output to your log:
Would have sent: Hello from Lift
The key part of this recipe is setting a MimeMessage => Unit function on Mailer.devModeSend. We happen to be logging, but you can use this function to handle the email any way you want.
The Lift Mailer allows you to control how email is sent at each run mode: by default, email is sent for devModeSend, profileModeSend, pilotModeSend, stagingModeSend, and productionModeSend; whereas, by default, testModeSend only logs that a message would have been sent.
The testModeSend logs a reference to the MimeMessage, meaning your log would show a message like:
Sending javax.mail.internet.MimeMessage@4a91a883
This recipe has changed the behaviour of Mailer when your Lift application is in developer mode (which it is by default). We're logging just the body part of the message.
Java Mail doesn't include a utility to display all the parts of an email, so if you want more information, you'll need to roll your own function. For example:
def display(m: MimeMessage) : String = {
val nl = System.getProperty("line.separator")
val from = "From: "+m.getFrom.map(_.toString).mkString(",")
val subj = "Subject: "+m.getSubject
def parts(mm: MimeMultipart) = (0 until mm.getCount).map(mm.getBodyPart)
val body = m.getContent match {
case mm: MimeMultipart =>
val bodyParts = for (part <- parts(mm)) yield part.getContent.toString
case otherwise => otherwise.toString
val to = for {
rt <- List(RecipientType.TO, RecipientType.CC, RecipientType.BCC)
address <- Option(m.getRecipients(rt)) getOrElse Array()
} yield rt.toString + ": " + address.toString
List(from, to.mkString(nl), subj, body) mkString nl
Mailer.devModeSend.default.set( (m: MimeMessage) =>
logger.info("Would have sent: "+display(m))
This would produce output of the form:
Would have sent: From: email@example.com To: firstname.lastname@example.com To: firstname.lastname@example.com Subject: Hello Hello from Lift
This example display function is long but mostly straightforward. The body value handles multipart messages by extracting each body part. This is triggered when sending more structured emails, such as the HTML emails described in [HTMLEmail].
If you want to debug the mail system while it's actually sending the email, enable the Java Mail debug mode. In default.props add:
This produces low-level output from the Java Mail system when email is sent:
DEBUG: JavaMail version 1.4.4 DEBUG: successfully loaded resource: /META-INF/javamail.default.providers DEBUG SMTP: useEhlo true, useAuth false DEBUG SMTP: trying to connect to host "localhost", port 25, isSSL false ...
See Also
Run modes are described on the Lift wiki.
HTML Email
You want to send an HTML email from your Lift application.
Give Mailer a NodeSeq containing your HTML message:
import net.liftweb.util.Mailer
import net.liftweb.util.Mailer._
val msg =
An implicit converts the NodeSeq into an XHTMLMailBodyType. This ensures the mime type of the email is text/html. Despite the name of "XHTML," the message is converted for transmission using HTML5 semantics.
The character encoding for HTML email, UTF-8, can be changed by setting mail.charset in your Lift properties file.
If you want to set both the text and HTML version of a message, supply each body wrapped in the appropriate BodyType class:
val html =
var text = "Hello!"
This message would be sent as a multipart/alternative:
Content-Type: multipart/alternative; boundary="----=_Part_1_1197390963.1360226660982" Date: Thu, 07 Feb 2013 02:44:22 -0600 (CST) ------=_Part_1_1197390963.1360226660982 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Hello! ------=_Part_1_1197390963.1360226660982 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 7bit   <title>Hello</title>
Hello!
   ------=_Part_1_1197390963.1360226660982--
When receiving a message with this content, it is up to the mail client to decide which version to show (text or HTML).
See Also
For sending with attachments, see [EmailWithAttachments].
Sending Authenticated Email
You need to authenticate with an SMTP server to send email.
Set the Mailer.authenticator in Boot with the credentials for your SMTP server, and enable the mail.smtp.auth flag in your Lift properties file.
Modify Boot.scala to include:
import net.liftweb.util.{Props, Mailer}
import javax.mail.{Authenticator,PasswordAuthentication}
Mailer.authenticator = for {
user <- Props.get("mail.user")
pass <- Props.get("mail.password")
} yield new Authenticator {
override def getPasswordAuthentication =
new PasswordAuthentication(user,pass)
In this example, we expect the username and password to come from Lift properties, so we need to modify src/main/resources/props/default.props to include them:
mail.password=correct horse battery staple
When you send email, the credentials in default.props will be used to authenticate with the SMTP server.
We've used Lift properties as a way to configure SMTP authentication. This has the benefit of allowing us to enable authentication for just some run modes. For example, if our default.props did not contain authentication settings, but our production.default.props did, then no authentication would happen in development mode, ensuring we can't accidentally send email outside of a production environment.
You don't have to use a properties file for this: the Lift Mailer also supports JNDI, or you could look up a username and password some other way and set Mailer.authenticator when you have the values.
However, some mail services such as SendGrid do require mail.smtp.auth=true to be set, and that should go into your Lift properties file or set as a JVM argument:
See Also
As well as mail.smtp.auth, there are a range of settings to control the Java Mail API. Examples include controlling port numbers and timeouts.
Sending Email with Attachments
You want to send an email with one or more attachments.
Use the Mailer XHTMLPlusImages to package a message with attachments.
Suppose we want to construct a CSV file and send it via email:
val content = "Planet,Discoverer\r\n" +
"HR 8799 c, Marois et al\r\n" +
"Kepler-22b, Kepler Science Team\r\n"
case class CSVFile(bytes: Array[Byte],
filename: String = "file.csv",
mime: String = "text/csv; charset=utf8; header=present" )
val attach = CSVFile(content.mkString.getBytes("utf8"))
val body =
Please research the enclosed.

val msg = XHTMLPlusImages(body,
PlusImageHolder(attach.filename, attach.mime, attach.bytes))
What's happening here is that our message is an XHTMLPlusImages instance, which accepts a body message and attachment. The attachment, the PlusImageHolder, is an Array[Byte], mime type, and a filename.
XHTMLPlusImages can also accept more than one PlusImageHolder if you have more than one file to attach. Although the name PlusImageHolder may suggest it is for attachment images, you can attach any kind of data as an Array[Byte] with an appropriate mime type.
By default, the attachment is sent with an inline disposition. This controls the Content-Disposition header in the message, and inline means the content is intended for display automatically when the message is shown. The alternative is attachment, and this can be indicated with an optional final parameter to PlusImageHolder:
PlusImageHolder(attach.filename, attach.mime, attach.bytes, attachment=true)
In reality, the mail client will display the message how it wants to, but this extra parameter may give you a little more control.
To attach a premade file, you can use LiftRules.loadResource to fetch content from the classpath. If our project contained a file called Kepler-22b_System_Diagram.jpg in the src/main/resources/ folder, we could load and attach it like this:
val filename = "Kepler-22b_System_Diagram.jpg"
val msg =
for ( bytes <- LiftRules.loadResource("/"+filename) )
yield XHTMLPlusImages(

Please research this planet.
,
PlusImageHolder(filename, "image/jpg", bytes) )
msg match {
case Full(m) =>
Subject("Planet attachment"),
case _ =>
logger.error("Planet file not found")
As the content of src/main/resources is included on the classpath, we pass the filename to loadResource with a leading / character so the file can be found at the right place on the classpath.
The loadResource returns a Box[Array[Byte]] as we have no guarantee the file will exist. We map this to a Box[XHTMLPlusImages] and match on that result to either send the email or log that the file wasn't found.
See Also
Messages are sent using the multipart/related mime heading, with an inline disposition. Lift ticket #1197 links to a discussion regarding multipart/mixed that may be preferable for working around issues with Microsoft Exchange.
RFC 2183 describes the Content-Disposition header.
Run a Task Later
You want to schedule code to run at some future time.
Use net.liftweb.util.Schedule:
import net.liftweb.util.Schedule
import net.liftweb.util.Helpers._
Schedule(() => println("doing it"), 30 seconds)
This would cause "doing it" to be printed on the console 30 seconds from now.
The signature for Schedule used previously expects a function of type () => Unit, which is the thing we want to happen in the future, and a TimeSpan from Lift's TimeHelpers, which is when we want it to happen. The 30 seconds value gives us a TimeSpan via the Helpers._ import, but there's a variation called perform that accepts a Long millisecond value if you prefer that:
Schedule.perform(() => println("doing it"), 30*1000L)
Behind the scenes, Lift is making use of the ScheduledExecutorService from java.util.concurrent and, as such, returns a ScheduledFuture[Unit]. You can use this future to cancel the operation before it runs.
It may be a surprise to find that you can call Schedule with just a function as an argument, and not a delay value. This version runs the function immediately, but on a worker thread. This is a convenient way to asynchronously run other tasks without going to the trouble of creating an actor for the purpose.
There is also a Schedule.schedule method that will send an actor a specified message after a given delay. This takes a TimeSpan delay, but again there's also a Schedule.perform version that accepts a Long as a delay.
The Helpers._ import brings with it some implicit conversions for TimeSpan. For example, a JodaTime Period can be given to schedule and that will be used as a delay before executing your function. Don't be tempted in this situation to use a JodaTime DateTime. This would be converted to a TimeSpan, but doesn't make sense as a delay.
See Also
[RunTasksPeriodically] includes an example of scheduling with actors.
ScheduledFuture is documented via the Java Doc for Future. If you're building complex, low-level, cancellable concurrency functions, it's advisable to have a copy of Java Concurrency in Practice close by (written by Goetz, et al., Addison-Wesley Professional).
Run Tasks Periodically
You want a scheduled task to run periodically (repeatedly).
Use net.liftweb.util.Schedule ensuring that you call schedule again during your task to reschedule it. For example, using an actor:
import net.liftweb.util.Schedule
import net.liftweb.actor.LiftActor
import net.liftweb.util.Helpers._
object MyScheduledTask extends LiftActor {
case class DoIt()
case class Stop()
private var stopped = false
def messageHandler = {
case DoIt if !stopped =>
Schedule.schedule(this, DoIt, 10 minutes)
// ... do useful work here
case Stop =>
stopped = true
The example creates a LiftActor for the work to be done. On receipt of a DoIt message, the actor reschedules itself before doing whatever useful work needs to be done. In this way, the actor will be called every 10 minutes.
The Schedule.schedule call is ensuring that this actor is sent the DoIt message after 10 minutes.
To start this process off, possibly in Boot.scala, just send the DoIt message to the actor:
MyScheduledTask ! MyScheduledTask.DoIt
To ensure the process stops correctly when Lift shuts down, we register a shutdown hook in Boot.scala to send the Stop message to prevent future reschedules:
LiftRules.unloadHooks.append( () => MyScheduledTask ! MyScheduledTask.Stop )
Without the Stop message, the actor would continue to be rescheduled until the JVM exits. This may be acceptable, but note that during development with SBT, without the Stop message, you will continue to schedule tasks after issuing the container:stop command.
Schedule returns a ScheduledFuture[Unit] from the Java concurrency library, which allows you to cancel the activity.
See Also
Chapter 1 of Lift in Action (by Perrett, Manning Publications, Co.) includes a Comet Actor clock example that uses Schedule.
Fetching URLs
You want your Lift application to fetch a URL and process it as text, JSON, XML, or HTML.
Use Dispatch, "a library for asynchronous HTTP interaction."
Before you start, include Dispatch dependency in build.sbt:
libraryDependencies += "net.databinder.dispatch" %% "dispatch-core" % "0.9.5"
Using the example from the Dispatch documentation, we can make an HTTP request to try to determine the country from the service at http://www.hostip.info/use.html:
import dispatch._
val svc = url("http://api.hostip.info/country.php")
val country : Promise[String] = Http(svc OK as.String)
Note that the result country is not a String but a Promise[String], and we use
The result printed will be a country code such as GB, or XX if the country cannot be determined from your IP address.
This short example expects a 200 (OK) status result and turns the result into a String, but that's a tiny part of what Dispatch is capable of. We'll explore further in this section.
What if the request doesn't return a 200? In that case, with the code we have, we'd get an exception such as: "Unexpected response status: 404." There are a few ways to change that.
We can ask for an Option:
val result : Option[String] = country.option()
As you'd expect, this will give a None or Some[String]. However, if you have debug level logging enabled in your application, you'll see the request and response and error messages from the underlying Netty library. You can tune these messages by adding a logger setting to default.logback.xml file:
<logger name="com.ning.http.client" level="WARN"/>
A second possibility is to use either with the usual convention that the Right is the expected result and Left signifies a failure:
country.either() match {
case Left(status) => println(status.getMessage)
case Right(cc) => println(cc)
This will print a result as we are forcing the evaluation with an apply via either().
Promise[T] implements map, flatMap, filter, fold, and all the usual methods you'd expect it to allow you to compose. This means you can use the promise with a for
val codeLength = for (cc <- country) yield cc.length
Note that codeLength is a Promise[Int]. To get the value, you can evaluate codeLength() and you'll get a result of 2.
As well as extracting string values with as.String, there are other options, including:
- as.Bytes
To work with Promise[Array[Byte]]
- as.File
To write to a file, as in Http(svc > as.File(new File("/tmp/cc")))
- as.Response
To allow you to provide a client.Response => T function to use on the response
- as.xml.Elem
To parse an XML response
As an example of as.xml.Elem:
val svc = url("http://api.hostip.info/?ip=22.214.171.124")
val country = Http(svc > as.xml.Elem)
println(country.map(_ \\ "description")())
This example is parsing the XML response to the request, which returns a Promise[scala.xml.Elem]. We're picking out the description node of the XML via a map, which will be a Promise[NodeSeq] that we then force to evaluate. The output is something like:
This is the Hostip Lookup Service
That example assumes the request is going to be well formed. In addition to the core Databinder library, there are extensions for JSoup and TagSoup to assist in parsing HTML that isn't necessarily well formed.
For example, to use JSoup, include the dependency:
libraryDependencies += "net.databinder.dispatch" %% "dispatch-jsoup" % "0.9.5"
You can then use the features of JSoup, such as picking out elements of a page using CSS selectors:
import org.jsoup.nodes.Document
val svc = url("http://www.example.org").setFollowRedirects(true)
val title = Http(svc > as.jsoup.Document).map(_.select("h1").text).option
println( title() getOrElse "unknown title" )
Here we are applying JSoup's select function to pick out the
 element on the page, taking the text of the element, which we turn into a Promise[Option[String]]. The result, unless example.org has changed, will be "Example Domain."
As a final example of using Dispatch, we can pipe a request into Lift's JSON library:
import net.liftweb.json._
import com.ning.http.client
object asJson extends (client.Response => JValue) {
def apply(r: client.Response) = JsonParser.parse(r.getResponseBody)
val svc = url("http://api.hostip.info/get_json.php?ip=22.214.171.124")
val json : Promise[JValue] = Http(svc > asJson)
case class HostInfo(country_name: String, country_code: String)
implicit val formats = DefaultFormats
val hostInfo = json.map(_.extract[HostInfo])()
The URL we're calling returns a JSON representation for location information of the IP address we've passed.
By providing a Response => JValue to Dispatch, we're able to pass the response body through to the JSON parser. We can then map on the Promise[JValue] to apply whatever Lift JSON functions we want to. In this case, we're extracting a simple case class.
The result would show hostInfo as:
HostInfo(UNITED KINGDOM,GB)
See Also
The Dispatch documentation is well written and guides you through the way Dispatch approaches HTTP. Do spend some time with it.
For questions about Dispatch, the best place is the Dispatch Google Group.
The previous major version of Dispatch, 0.8.x ("Dispatch Classic"), is quite different from the "reboot" of the project as version 0.9. Consequently, examples you may see that use 0.8.x will need some conversion to run with 0.9.x. Nathan Hamblen's blog describes the change.
For working with JSoup, take a look at the JSoup Cookbook.
Production Deployment
Deploying a Lift application to production means little more than packaging it and ensuring you set the run mode to production. The recipes in this chapter show how to do this for various hosted services.
You can also install and run a container such as Tomcat or Jetty on your own servers. Containers were introduced in [RunningYourApplication]. This brings with it the need to understand how to install, configure, start, stop, and manage each container, and how to integrate it with load balancers or other frontends. These are large topics, and you can find out more from such sources as:
The deployment section of the Lift wiki.
Timothy Perrett, Lift in Action, Chapter 15, "Deployment and Scaling," Manning Publications, Co.
Jason Brittain and Ian F. Darwin, Tomcat: The Definitive Guide, O'Reilly Media, Inc.
Tanuj Khare, Apache Tomcat 7 Essentials, Packt Publishing.
The Lift wiki includes a page on Tomcat configuration options relevant to Lift.
Deploying to CloudBees
You have an account with the CloudBees PaaS hosting environment, and you want to deploy your Lift application there.
|CloudBees have announced they are closing their hosting service as of 31st December 2014.
Use the SBT package command to produce a WAR file that can be deployed to CloudBees, and then use the CloudBees SDK to configure and deploy your application.
From within the CloudBees "Grand Central" console, create a new application under your account. In what follows, we'll assume your account is called myaccount and your application is called myapp.
For the best performance, you will want to ensure the Lift run mode is set to "production." Do this from the CloudBees SDK command line:
$ bees config:set -a myaccount/myapp run.mode=production
This will set the run mode to production for your CloudBees applications identified as myaccount/myapp. Omitting the -a will set it for your whole CloudBees account.
CloudBees will remember this setting, so you only need to do it once.
You can then deploy:
$ sbt package
[info] Packaging /Users/richard/myapp/target/scala-2.9.1/myapp.war...
$ bees app:deploy -a myaccount/myapp ./target/scala-2.9.1/myapp.war
This will send your WAR file to CloudBees and deploy it. You'll see the location (URL) of your application output from the bees app:deploy command when it completes.
If you change a configuration setting, you will need to restart the application for the setting to take effect. Deploying the application will do this, otherwise, run the bees app:restart command:
$ bees app:restart -a myaccount/myapp
If you are deploying an application to multiple CloudBees instances, be aware that, by default, CloudBees will round robin requests to each instance. If you use any of Lift's state features, you'll want to enable session affinity (sticky sessions):
$ bees app:update -a myaccount/myapp stickySession=true
If you are using Comet, it'll work fine, but the CloudBees default is to enable request buffering. This allows CloudBees to do smart things, such as rerouting requests in a cluster if one machine does not respond. A consequence of request buffering is that long-polling Comet requests will time out more often. To turn this feature off, run the following:
$ bees app:update -a myaccount/myapp disableProxyBuffering=true
As with the run mode setting, CloudBees will remember these settings, so you only need to set them once.
Finally, you may want to increase the permanent generation memory setting of the JVM. By default, an application has 64 MB assigned for the PermGen. To increase this to 128 MB, run the bees app:update command:
$ bees app:update -a myaccount/myapp jvmPermSize=128
The commands bees app:info and bees config:list will report back the settings for your application.
RDBMS configuration
If you are using a SQL database in your application, you'll want to configure src/main/webapp/WEB-INF/cloudbees-web.xml. For example:
<?xml version="1.0"?>
<cloudbees-web-app xmlns="http://www.cloudbees.com/xml/webapp/1">
<resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource">
<param name="username" value="dbuser" />
<param name="password" value="dbpassword" />
<param name="url" value="jdbc:cloudbees://mydb" />

<param name="validationQuery" value="SELECT 1" />
<param name="testOnBorrow" value="true" />
This is a JNDI database configuration, defining a connection to a CloudBees database called mydb. This will be used by Lift if the JNDI name is referenced in Boot.scala:
DefaultConnectionIdentifier.jndiName = "jdbc/mydb"
if (!DB.jndiJdbcConnAvailable_?) {
// set up alternative local database connection here
Because the JNDI setting is only defined in cloudbees-web.xml, it will only be available in a CloudBees environment. This means you can develop against a different database locally and use your CloudBees database when deploying.
Host IP and port number
Generally, you don't need to know about your deployed instance's public host name and port number. Requests to your application URL are routed to a specific instance by CloudBees. However there are situations, especially when you have multiple instances, where you do need to find this out. For example, if you want to receive messages from Amazon's Simple Notification Service (SNS), then each instance will need to give a direct URL to SNS when the application boots.
CloudBees has provided documentation on how to do this. To get the public hostname, you need to make an HTTP request to http://instance-data/latest/meta-data/public-hostname. For example:
import io.Source
val beesPublicHostname : Box[String] = tryo {
This will return a Full hostname on the CloudBees environment, but when running locally will fail and return a Failure. For example:
Failure(instance-data,Full(java.net.UnknownHostException: instance-data),Empty)
The port number can be found from the name of a file in the .genapps/ports folder of your application deployment:
val beesPort : Option[Int] = {
val portsDir = new File(System.getenv("PWD"), ".genapp/ports")
for {
files <- Option(portsDir.list)
port <- files.flatMap(asInt).headOption
} yield port
The java.io.File list method returns a list of filenames in a directory, but will return null if the directory doesn't exist or if there are any IO errors. For this reason, we wrap it in Option to convert null values to None.
Running locally, this will return a None, but on CloudBees, you'll see a Full[Int] port number.
You might put these two values together as follows:
import java.net.InetAddress
val hostAndPort : String =
(beesPublicHostname openOr InetAddress.getLocalHost.getHostAddress) +
":" + (beesPort getOrElse 8080).toString
Running locally, hostAndPort might be 192.168.1.60:8080 and running on CloudBees, it would be something like ec2-204-236-222-252.compute-1.amazonaws.com:8520.
Java version
Currently the default JVM provided by CloudBees is JDK 7, but you can select 6, 7, and 8. To change the default Java Virtual Machine, use the bees config:set command:
$ bees config:set -a myaccount/myapp -Rjava_version=1.8
Excluding the application identifier -a myaccount/myapp from the command will set the JVM as the default for all applications in the account. The bees config:set command will update the configuration, but not take effect until the application has been updated or restarted.
The JVM can also be changed when an application is deployed or updated via the following commands:
$ bees app:deploy -a myaccount/myapp sample.war -Rjava_version=1.6
$ bees app:update -a myaccount/myapp -Rjava_version=1.7
To confirm which JVM an application is currently running, use the bees config:list command, which will display the Java version:
$ bees config:list -a myaccount/myapp
Runtime Parameters:
Container version
CloudBees offers several containers: Tomcat 6.0.32 (the default), Tomcat 7, JBoss 7.02, JBoss 7.1, and GlassFish 3.
To change containers, the application will need to be redeployed, as CloudBees uses different file configurations for the various containers. Hence we use the bees app:deploy command. The following example updates to Tomcat 7:
$ bees app:deploy -t tomcat7 -a myaccount/myapp sample.war
The JVM and container commands can be run as a single bees app:deploy, as follows:
$ bees app:deploy -t tomcat -a myaccount/myapp sample.war -Rjava_version=1.6
This would deploy sample.war to the myapp application on myaccount with Tomcat 6.0.32 and JDK 6.
To determine which container an application is deployed to, use the command bees app:info:
$ bees app:info -a myaccount/myapp
Application : myaccount/myapp
Title : myapp
Created : Wed Mar 20 11:02:40 EST 2013
Status : active
URL : myapp.myaccount.cloudbees.net
clusterSize : 1
container : java_free
containerType : tomcat
idleTimeout : 21600
maxMemory : 256
proxyBuffering : false
securityMode : PUBLIC
serverPool : stax-global (Stax Global Pool)
ClickStart applications are templates to quickly get an application and automated build up and running at CloudBees. The Lift ClickStart creates a private Git source repository at CloudBees that contains a Lift 2.4 application, provisions a MySQL database, creates a Maven-based Jenkins build, and deploys the application. All you need to do is provide a name for the application (without whitespace).
To access the Git source repository created for you, you'll need to upload an SSH public key. You can do this in the "My Keys" section of your account settings on the CloudBees website.
The build that's created for you will automatically build and deploy your application to CloudBees when you push changes to your Git repository.
If all of that's a good match to the technologies and services you want to use, ClickStart is a great way to deploy your application. Alternatively, it gives you a starting point from which you can modify elements; or you could fork the CloudBees Lift template and create your own.
See Also
The CloudBees SDK provides command-line tools for configuring and controlling
The CloudBees developer portal contains a "Resources" section that provides details of the CloudBees services. In it, you'll find details on PermGen settings, JVM selection, and servlet containers.
Deploying to Amazon Elastic Beanstalk
You want to run your Lift application on Amazon Web Services (AWS) Elastic Beanstalk.
Create a new Tomcat 7 environment, use SBT to package your Lift application as a WAR file, and then deploy the application to your environment.
To create a new environment, visit the AWS console, navigate to Elastic Beanstalk, and select "Apache Tomcat 7" as your environment. This will create and launch a default Beanstalk application. This may take a few minutes, but will eventually report "Successfully running version Sample Application." You'll be shown the URL of the application (something like http://default-environment-nsdmixm7ja.elasticbeanstalk.com), and visiting the URL you're given will show the running default Amazon application.
Prepare your WAR file by running:
$ sbt package
This will write a WAR file into the target folder. To deploy this WAR file from the AWS Beanstalk web console (see [ConsoleImage]), select the "Versions" tab under the "Elastic Beanstalk Application Details" and click the "Upload new version" button. You'll be given a dialog where you give a version label and use the "Choose file" button to select the WAR file you just built. You can either upload and deploy in one step, or upload first and then select the version in the console and hit the "Deploy" button.
The Beanstalk console will show "Environment updating…", and after some minutes, it'll report "Successfully running." Your Lift application is now deployed and running on Beanstalk.
A final step is to enable Lift's production run mode. From the environment in the AWS Beanstalk web console, follow the "Edit Configuration" link. A dialog will appear, and under the "Container" tab, add -Drun.mode=production to the "JVM Command Line Options" and hit "Apply Changes" to redeploy your application.
Elastic Beanstalk provides a prebuilt stack of software and infrastructure, in this case: Linux, Tomcat 7, a 64 bit "t1.micro" EC2 instance, load balancing, and an S3 bucket. That's the environment and it has reasonable default settings. Beanstalk also provides an easy way to deploy your Lift application. As we've seen in this recipe, you upload an application (WAR file) to Beanstalk and deploy it to the environment.
As with many cloud providers, keep in mind that you want to avoid local file storage. The reason for this is to allow instances to be terminated or restarted without data loss. With your Beanstalk application, you do have a filesystem and you can write to it, but it is lost if the image is restarted. You can get persistent local file storage—for example, using Amazon Elastic Block Storage—but you're fighting against the nature of the
Logfiles are written to the local filesystem. To access them, from the AWS console, navigate to your environment, into the "Logs" tab, and hit the "Snapshot" button. This will take a copy of the logs and store them in an S3 bucket, and give you a link to the file contents. This is a single file showing the content of a variety of logfiles, and catalina.out will be the one showing any output from your Lift application. If you want to try to keep these logfiles around, you can configure the environment to rotate the logs to S3 every hour from the "Container" tab under "Edit Configuration."
The Lift application WAR files are stored in the same S3 bucket that the logs are stored in. From the AWS console, you'll find it under the S3 page listed with a name like "elasticbeanstalk-us-east-1-5989673916964." You'll note that the AWS uploads makes your WAR filename unique by adding a prefix to each filename. If you need to be able to tell the difference between these files in S3, one good approach is to bump the version value in your build.sbt file. This version number is included in the WAR
Multiple instances
Beanstalks enables autoscaling by default. That is, it launches a single instance of your Lift application, but if the load increases above a threshold, up to four instances may be running.
If you're making use of Lift's state features, you'll need to enable sticky sessions from the "Load Balancer" tab of the environment configuration. It's a checkbox named
Working with a database
There's nothing unusual you have to do to use Lift and a database from Beanstalk. However, Beanstalk does try to make it easy for you to work with Amazon's Relational Database Service (RDS). Either when creating your Beanstalk environment, or from the configuration options later, you can add an RDS instance, which can be an Oracle, SQL-Server, or MySQL database.
The MySQL option will create a MySQL InnoDB database. The database will be accessible from Beanstalk, but not from elsewhere on the Internet. To change that, modify the security groups for the RDS instance from the AWS web console. For example, you might permit access from your IP address.
When your application launches with an associated RDS instance, the JVM system properties include settings for the database name, host, port, user, and password. You could pull them together like this in Boot.scala:
val connection = for {
host <- Box !! System.getProperty("RDS_HOSTNAME")
port <- Box !! System.getProperty("RDS_PORT")
db <- Box !! System.getProperty("RDS_DB_NAME")
user <- Box !! System.getProperty("RDS_USERNAME")
pass <- Box !! System.getProperty("RDS_PASSWORD")
} yield DriverManager.getConnection(
"jdbc:mysql://%s:%s/%s" format (host,port,db),
user, pass)
That would give you a Box[Connection] that, if Full, you could use in a SquerylRecord.initWithSquerylSession call, for example (see [Squeryl]).
Alternatively, you might want to guarantee a connection by supplying defaults for all the values with something like this:
val connection = {
val host = System.getProperty("RDS_HOSTNAME", "localhost")
val port = System.getProperty("RDS_PORT", "3306")
val db = System.getProperty("RDS_DB_NAME", "db")
val user = System.getProperty("RDS_USERNAME", "sa")
val pass = System.getProperty("RDS_PASSWORD", "")
"jdbc:mysql://%s:%s/%s" format (host,port,db),
user, pass)
See Also
Amazon provided a walkthrough with screenshots, showing how to create a Beanstalk application.
The Amazon documentation for "Configuring Databases with AWS Elastic Beanstalk" describes the RDS settings in more detail.
Deploying to Heroku
You want to deploy your Lift application to your account on the Heroku cloud platform.
Package your Lift application as a WAR file and use the Heroku deploy plugin to send and run your application. This will give you an application running under Tomcat 7. Anyone can use this method to deploy an application, but Heroku provides support only for Enterprise Java customers.
This recipe walks through the process in three stages: one-time setup; deployment of the WAR; and configuration of your Lift application for production performance.
If you've not already done so, download and install the Heroku command-line tools ("Toolbelt") and log in using your Heroku credentials and upload an SSH key:
$ heroku login Enter your Heroku credentials. Email: email@example.com Password (typing will be hidden): Found the following SSH public keys: 1) github.pub 2) id_rsa.pub Which would you like to use with your Heroku account? 2 Uploading SSH public key ~/.ssh/id_rsa.pub... done Authentication successful.
Install the deploy plugin:
$ heroku plugins:install https://github.com/heroku/heroku-deploy Installing heroku-deploy... done
With that one-time setup complete, you can create an application on Heroku. Here we've not specified a name, so we are given a random name of "glacial-waters-6292" that we will use throughout this recipe:
$ heroku create Creating glacial-waters-6292... done, stack is cedar http://glacial-waters-6292.herokuapp.com/ | firstname.lastname@example.com:glacial-waters-6292.git
Before deploying, we set the Lift run mode to production. This is done via the config:set command. First check the current settings for JAVA_OPTS and then modify the options by adding -Drun.mode=production:
$ heroku config:get JAVA_OPTS --app glacial-waters-6292 -Xmx384m -Xss512k -XX:+UseCompressedOops $ heroku config:set JAVA_OPTS="-Drun.mode=production -Xmx384m -Xss512k -XX:+UseCompressedOops" --app glacial-waters-6292
We can deploy to Heroku by packaging the application as a WAR file and then running the Heroku deploy:war command:
$ sbt package
[info] Packaging target/scala-2.9.1/myapp-0.0.1.war ...
$ heroku deploy:war --war target/scala-2.9.1/myapp-0.0.1.war
--app glacial-waters-6292
Uploading target/scala-2.9.1/myapp-0.0.1.war............done
Deploying to glacial-waters-6292.........done
Created release v6
Your Lift application is now running on Heroku.
There are a few important comments regarding Lift applications on Heroku. First, note that there's no support for session affinity. This means if you deploy to multiple dynos (Heroku terminology for instances), there is no coordination over which requests go to which servers. As a consequence, you won't be able to make use of Lift's stateful features and will want to turn them off ([RunningStateless] describes how to do that).
Second, if you are using Lift Comet features, there's an adjustment to make in Boot.scala to work a little better in the Heroku environment:
LiftRules.cometRequestTimeout = Full(25)
This setting controls how long Lift waits before testing a Comet connection. We're replacing the Lift default of 120 seconds with 25 seconds, because Heroku terminates connections after 30 seconds. Although Lift recovers from this, the user experience may be to see a delay when interacting with a page.
A third important point to note is that the dyno will be restarted every day. Additionally, if you are only running one web dyno, it will be idled after an hour of inactivity. You can see this happening by tailing your application log:
$ heroku logs -t --app glacial-waters-6292
2012-12-31T11:31:39+00:00 heroku[web.1]: Idling
2012-12-31T11:31:41+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2012-12-31T11:31:43+00:00 heroku[web.1]: Process exited with status 143
2012-12-31T11:31:43+00:00 heroku[web.1]: State changed from up to down
Anyone visiting your Lift application will cause Heroku to unidle your application.
Note, though, that the application was stopped with a SIGTERM. This is a Unix signal sent to a process, the JVM in this case, to request it to stop. Unfortunately, the Tomcat application on Heroku does not use this signal to request Lift to shut down. This may be of little consequence to you, but if you do have external resources you want to release to other actions to take at shutdown, you need to register a shutdown hook with the JVM.
For example, you might add this to Boot.scala if you're running on Heroku:
Runtime.getRuntime().addShutdownHook(new Thread {
override def run() {
println("Shutdown hook being called")
// Do useful clean up here
Do not count on being able to do much during shutdown. Heroku allows around 10 seconds before killing the JVM after issuing the SIGTERM.
Possibly a more general approach is to perform cleanup using Lift's unload hooks (see [ShutdownHooks]) and then arrange the hooks to be called when Heroku sends the signal to terminate:
Runtime.getRuntime().addShutdownHook(new Thread {
override def run() {
LiftRules.unloadHooks.toList.foreach{ f => tryo { f() } }
This handling of SIGTERM may be a surprise, but if we look at how the application is running on Heroku, things become clearer. The dyno is an allocation of resources (512 MB of memory) and allows an arbitrary command to run. The command being run is a Java process starting a "webapp runner" package. You can see this in two ways. First, if you shell to your dyno, you'll see a WAR file as well as a JAR file:
$ heroku run bash --app glacial-waters-6292
Running `bash` attached to terminal... up, run.8802
~ $ ls
Procfile myapp-0.0.1.war webapp-runner-22.214.171.124.jar
Second, by looking at the processes executing:
$ heroku ps --app glacial-waters-6292 === web: `${PRE_JAVA}java ${JAVA_OPTS} -jar webapp-runner-184.108.40.206.jar --port ${PORT} ${WEBAPP_RUNNER_OPTS} myapp-0.0.1.war` web.1: up 2013/01/01 22:37:35 (~ 31s ago)
Here we see a Java process executing a JAR file called webapp-runner-184.108.40.206.jar that is passed our WAR file as an argument. This is not identical to the Tomcat catalina.sh script you may be more familiar with, but instead is this launcher process. As it does not register a handler to deal with SIGTERM, we will have to if we need to release any resources during shutdown.
All of this means that if you want to launch a Lift application in a different way, you can. You'd need to wrap an appropriate container (Jetty or Tomcat, for example), and provide a main method for Heroku to call. This is sometimes called containerless deployment.
If you are not a Heroku Enterprise Java customer, and you're uncomfortable with the unsupported nature of the deploy:war plugin, you now know what you need to do to run in a supported way: provide a main method that launches your application and listen for connections. The "See Also" section gives pointers for how to do this.
Database access in Heroku
Heroku makes no restrictions on which databases you can connect to from your Lift application, but they try to make it easy to use their PostgreSQL service by attaching a free database to applications you create.
You can find out if you have a database by running the pg command:
$ heroku pg --app glacial-waters-6292
Plan: Dev
Status: available
Connections: 0
PG Version: 9.1.6
Created: 2012-12-31 10:02 UTC
Data Size: 5.9 MB
Tables: 0
Rows: 0/10000 (In compliance)
Fork/Follow: Unsupported
The URL of the database is provided to your Lift application as the DATABASE_URL environment variable. It will have a value of something like this:
postgres://gghetjutddgr:firstname.lastname@example.com. amazonaws.com:5432/d44nsahps11hda
This URL contains a username, password, host, and database name, but needs to be manipulated to be used by JDBC. To do so, you might include the following in Boot.scala:
Box !! System.getenv("DATABASE_URL") match {
case Full(url) => initHerokuDb(url)
case _ => // configure local database perhaps
def initHerokuDb(dbInfo: String) {
// Extract credentials from Heroku database URL:
val dbUri = new URI(dbInfo)
val Array(user, pass) = dbUri.getUserInfo.split(":")
// Construct JDBC connection string from the URI:
def connection = DriverManager.getConnection(
"jdbc:postgresql://" + dbUri.getHost + ':' + dbUri.getPort +
dbUri.getPath, user, pass)
Session.create(connection, new PostgreSqlAdapter))
Here we are testing for the presence of the DATABASE_URL environment variable, which would indicate that we are in the Heroku environment. We can then extract out the connection information to use in Session.create. We would additionally need to complete the usual addAround configuration described in [ConfiguringSqueryl].
For it to run, build.sbt needs the appropriate dependencies for Record and PostgreSQL:
"postgresql" % "postgresql" % "9.1-901.jdbc4",
"net.liftweb" %% "lift-record" % liftVersion,
"net.liftweb" %% "lift-squeryl-record" % liftVersion,
With this in place, your Lift application can make use of the Heroku database. You can also access the database from the shell, for example:
$ pg:psql --app glacial-waters-6292 psql (9.1.4, server 9.1.6) SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256) Type "help" for help. d44nsahps11hda=> \d No relations found. d44nsahps11hda=> \q $
To access via a JDBC tool outside of the Heroku environment, you'll need to include parameters to force SSL. For example:
See Also
The Scala and Java articles at Heroku, and Dynos and the Dyno Manager, are useful to learn more of the details described in this recipe.
The JVM shutdown hooks are described in the JDK documentation.
Heroku's guide to containerless deployment makes use of Maven to package your application. There is also a template SBT project from Matthew Henderson that includes a JettyLauncher class.
Request Timeout describes how Heroku deals with Comet long polling.
Distributing Comet Across Multiple Servers
You use Lift's Comet support, and want to run across multiple servers for increased redundancy or to handle increased load.
Use the publish/subscribe (pubsub) model to connect each server to a topic and route Comet messages out to the topic where it can be broadcast to all servers that are part of your application.
There are a variety of technologies you can use to accomplish this, such as databases, message systems, and actor systems. For this recipe, we will use the RabbitMQ message service, but there are examples using CouchDB and Amazon's Simple Notification Service in the "See Also" section.
Regardless of the technology, the principle is illustrated in [DistributedCometDiagram]. A Comet event originating on one Lift application is sent to a service for redistribution. It is the responsibility of this service (labeled "topic" in the figure) to ensure all the participating Lift applications receive the event.
The first step is to download and install RabbitMQ. Then start the server:
$ ./sbin/rabbitmq-server -detatched
This command will produce various messages as it starts but will eventually say: "broker running."
The Lift application we'll use to demonstrate the pubsub pattern is the real-time chat application, described in Simply Lift. The first modification is to include the Lift module to talk to RabbitMQ. This is a one-line addition to the libraryDependencies in build.sbt:
"net.liftmodules" %% "amqp_2.5" % "1.3"
AMQP stands for Advanced Message Queuing Protocol, a protocol that RabbitMQ talks. The AMQP module provides abstract actors to send and receive messages, and we will implement these actors as RemoteSend and RemoteReceiver:
package code.comet
import net.liftmodules.amqp._
import com.rabbitmq.client._
object Rabbit {
val factory = new ConnectionFactory {
import ConnectionFactory._
val exchange = "lift.chat"
val routing = ""
val durable = true
val autoAck = false
object RemoteSend extends AMQPSender[String](factory, exchange, routing) {
def configure(channel: Channel) =
channel.exchangeDeclare(exchange, "fanout", durable)
object RemoteReceiver extends AMQPDispatcher[String](factory) {
def configure(channel: Channel) = {
channel.exchangeDeclare(exchange, "fanout", durable)
val queueName = channel.queueDeclare().getQueue()
channel.queueBind(queueName, exchange, routing)
channel.basicConsume(queueName, autoAck,
new SerializedConsumer(channel, this) )
This code is establishing RemoteSend and RemoteReceiver actors that serialise String values via RabbitMQ. This code is explored in the "Discussion" section next.
To make use of this and route Comet messages over RabbitMQ, we need to make two changes. In Boot.scala, we need to start listening for messages from RabbitMQ:
RemoteReceiver ! AMQPAddListener(ChatServer)
This is attaching the ChatServer as a listener for AMQP messages from the
The final change is to the ChatServer itself. The regular behaviour of the ChatServer is to receive a String message from a client and update all the screens attached to the Comet server:
override def lowPriority = {
case s : String => msgs :+= s; updateListeners()
The change to route messages over RabbitMQ is to redirect any String from clients to RabbitMQ, and handle any AMQP messages from RabbitMQ and update all clients:
override def lowPriority = {
case AMQPMessage(s: String) => msgs :+= s; updateListeners()
case s: String => RemoteSend ! AMQPMessage(s)
This change means all our Comet chat messages go out to RabbitMQ where they are distributed to all the instances of our Lift application, and all the instances receive the messages back as AMQPMessage instances and update chat clients as normal.
To run more than one instance of your Lift application locally, you'll want to start SBT as normal, and then in another Terminal, start again but on a different port number:
$ sbt ... > set port in container.Configuration := 9090 [info] Reapplying settings... [info] Set current project to RabbitMQ Chat (in build file:rabbitmq_chat/) > container:start
You can then visit one application at http://127.0.0.1:8080 and another at http://127.0.0.1:9090.
In the example code, you can see that AMQPSender[T] and AMQPDispatcher[T] take care of most of the work for us, and we provide some configuration. In the case of RemoteSend we're configuring the AMQPSender to work with String messages and to work with an exchange called lift.chat. In RabbitMQ, the exchange is the entity we send messages to, and the exchange has the responsibility for passing on the message. In this case, the exchange is a fanout (a simple kind of topic) where each subscriber receives a copy of any messages sent to the exchange. This is clearly what we want to get our chat messages sent to all connected Lift instances of the chat application.
The RemoteReceiver is also configured to receive String messages, although the configuration is a little longer. Here, as well as indicating the exchange to be used, we declare a temporary queue for our Lift instance. The queue is the place where RabbitMQ sends messages, and what we're saying here is that each receiver has its own queue. The fanout exchange will ensure any message sent to the exchange is placed into every queue. The queue has a random name assigned by RabbitMQ and is destroyed when we disconnect from it.
The final part of the RemoteReceiver is to specify how we consume messages. The default behaviour of RemoteSend is to serialise objects, so we mirror that in the receiver by using the SerializedConsumer class provided by the AMQP module.
To see the behaviour of RabbitMQ, it's useful to install the management web console. From the directory where you installed RabbitMQ:
$ ./sbin/rabbitmq-plugins enable rabbitmq_management
Visit the administrative web interface at http://127.0.0.1:15672/ and log in. The default username and password is "guest."
Needing to have RabbitMQ (or other types of pubsub solutions) running during development may be inconvenient. In that case, you can simply not initialise the service in Boot.scala:
if (Props.productionMode)
RemoteReceiver ! AMQPAddListener(ChatServer)
And in the chat server, send only to local clients:
override def lowPriority = {
case AMQPMessage(s: String) => msgs :+= s; updateListeners()
case s: String =>
if (Props.productionMode) RemoteSend ! AMQPMessage(s)
else { msgs :+= s; updateListeners() }
Note that Props.productionMode is true for the run modes of Production, Staging, and Pilot.
See Also
The Lift Chat example is described in Simply Lift. The source code used in this recipe is on GitHub.
Source for the Lift AMQP module can be found on GitHub.
If you want to learn more about RabbitMQ, take a look at the tutorials or Alvaro Videla and Jason J.W. Williams's RabbitMQ in Action: Distributed Messaging for Everyone (Manning Publications Co.).
Diego Medina has implemented a distributed Comet solution using CouchDB, and has described it in a blog post.
Amazon's Simple Notification Service (SNS) is a fanout facility so it can also be used to implement this pattern. You can find a Lift module for SNS on GitHub.
Contributing, Bug Reports, and
Getting Help
You'd Like Some Help
You're stuck on something in Lift and you'd like some help.
Ask a question on the Lift mailing list.
You will find some information about Lift on StackOverflow, Quora, and elsewhere, but the mailing list is the place to go to get help and support. You can search the archive to see if your question has already been addressed, but questions are very welcome as it helps the Lift community understand what users need and what might be causing problems or need explanation. Much of what you're reading here originates from questions that have been asked on the mailing list.
New members to the mailing list are moderated to help reduce spam. This means the first time you post, your message may take a few hours to show up.
See Also
The Lift community is one of the things that makes Lift what it is. Please take a look at http://liftweb.net/community before posting: you'll get the best response with a polite question.
If you need paid consulting, development, or SLA-backed support, there's a list of organizations on the wiki.
How to Report Bugs
You've found a bug and want to report it.
Discuss your findings on the Lift mailing list, describing what you're seeing, and what you'd expected to see.
By all means look at the existing tickets to see if your issue is there or recently fixed, but please do not raise a ticket unless asked to do so by a Lift committer on the mailing list.
If Lift is not behaving as you expect, please ask questions about what you're seeing. The ideal form of these questions is "When I do X, my Lift app does Y, but I expect it to do Z, why?" This provides a set of language to discuss your application and the way that Lift responds to requests. Perhaps there's a way of improving Lift. Perhaps there's a concept that's different in Lift than you might be used to. Perhaps there's a documentation issue that can help bridge the gap between what Lift is doing and what you expect it to do. Most importantly, just because Lift is behaving differently than you expect it to, it's not necessarily a bug in Lift.
— David Pollack
A great way to get help with the issue you have, or get a bug fixed, is to produce a small example to illustrate the problem and post it on GitHub. The key is to provide instructions so someone can run the example and see exactly what you see without having to jump through hoops.
See Also
You'll find a list of tickets at http://ticket.liftweb.net/.
If you're asked to, or want to, post example code, please follow the guide.
If you've found a bug, and you're asked to create a ticket, the main thing to do is include a link to the mailing list discussion of the issue, as described in Creating tickets.
Contributing Small Code Changes and ScalaDoc
You have a small change or ScalaDoc improvement you'd like incorporated into Lift.
You can issue pull requests against the Lift source, providing your change meets one of the following requirements:
It's a change to a comment.
It's example code.
It's a small change, enhancement, or bug fix to Lift.
Your pull request must include an edit to add your signature to the bottom of the contributors.md file.
Historically, Lift had a strict contributor policy of simply not accepting any code contributions except from committers who had signed an agreement to assign copyright to the Lift project. This allowed corporations wanting to adopt Lift to do so without litigation concerns.
The safety is still there, now via the requirement for a signature on the contributors file, which reads:
By submitting this pull request which includes my name and email address (the email address may be in a non-robot readable format), I agree that the entirety of the contribution is my own original work, that there are no prior claims on this work including, but not limited to, any agreements I may have with my employer or other contracts, and that I license this work under an Apache 2.0 license.
What's a small change? That's a good question, and if you're unsure, talk about your proposed change on the mailing list.
See Also
This contribution policy was introduced in November 2012.
The contributors.md file is found on GitHub.
The Lift source is on GitHub. The framework project is probably the one you want, although you'll also find Git repositories for examples and Lift websites there.
GitHub provides an introduction to pull requests.
[modules] describes how to share code of any size via Lift modules.
Contributing Documentation
You'd like to contribute documentation to Lift.
Update or add to the Lift wiki.
You'll need to sign in, or create a free account, with Assembla, the company that hosts the wiki. You then need to become a watcher of the Lift wiki, which is offered as a link on the top right of the Lift wiki page. As a watcher, you can edit pages and create new pages.
If you're unsure about a change you'd like to make, just ask for feedback on the Lift mailing list.
One limitation of the watcher role on Assembla is that you cannot move pages. If you create a new page in the wrong section, or want to reorganise pages, you'll need to ask on the Lift mailing list for someone with permissions to do that for you.
See Also
The markup format for the wiki pages is Textile.
How to Add a New Recipe to This Cookbook
You'd like to add a section or chapter to this cookbook.
If you're comfortable using Git, you can fork the repository and send a pull request.
Alternatively, download a template file, write your recipe, and email it to the Lift mailing list.
You can find the template file on GitHub.
Anything you've puzzled over, or things that have surprised you, impressed you, or are nonobvious are great topics for recipes. Improvements, discussions, and clarifications of existing recipes are welcome, too.
The cookbook is structured using a markup language called AsciiDoc. If you're familiar with Markdown or Textile, you'll find similarities. For the cookbook, you only need to know about section headings, source code formatting, and links. Examples of all of these are in the template.asciidoc file.
To find out where to make a change, you need to know that each chapter is a separate file, and each recipe is a section in that file.
We ask contributors the following:
You agree to license your work (including the words you write, the code you use, and any images) to us under the Creative Commons Attribution, Non Commercial, No Derivatives license.
You assert that the work is your own, or you have the necessary permission for the work.
To keep things simple, all author royalties from this book are given to charity.
See Also
The source to this book is on GitHub.
The AsciiDoc cheatsheet is a quick way to get into AsciiDoc, but if you need more, the AsciiDoc home page has the details.
GitHub provides an introduction to pull requests.
[wiki] describes other ways to contribute documentation to Lift.
Sharing Code in Modules
You have code you'd like to share between Lift projects or with the community.
Create a Lift module, and then reference the module from your Lift projects.
As an example, let's create a module to embed the snowstorm snowfall effect on every page in your Lift web application (please don't do this).
There's nothing special about modules: they are coded, packaged, and used like any other dependency. What makes them possible is the exposure of extension points via
For our snowstorm, we're going to package some JavaScript and inject the script onto every page.
Starting with the lift_blank template downloaded from liftweb.net, we can remove all the source and HTML files, as this won't be a runnable Lift application in itself. However, it will leave us with the regular Lift structure and build configuration.
Our module will need the snowstorm JavaScript file copied as resources/toserve/snowstorm.js. This will place the JavaScript file on the classpath of our Lift application.
The final piece of the module is to ensure the JavaScript is included on every page:
package net.liftmodules.snowstorm
import net.liftweb.http._
object Snowstorm {
def init() : Unit = {
ResourceServer.allow {
case "snowstorm.js" :: Nil => true
def addSnow(s: LiftSession, r: Req) = S.putInHead(
 )
LiftSession.onBeginServicing = addSnow _ :: LiftSession.onBeginServicing
We modify build.sbt to give the module a name, organisation, and version number. We also can remove many of the dependencies and the web plugin as we only depend on the web API elements of Lift:
name := "snowstorm"
version := "1.0.0"
organization := "net.liftmodules"
scalaVersion := "2.9.1"
resolvers ++= Seq(
"snapshots" at "http://oss.sonatype.org/content/repositories/snapshots",
"releases" at "http://oss.sonatype.org/content/repositories/releases"
scalacOptions ++= Seq("-deprecation", "-unchecked")
libraryDependencies ++= {
val liftVersion = "2.5"
"net.liftweb" %% "lift-webkit" % liftVersion % "compile"
We can publish this plugin to the repository on disk by starting SBT and typing:
With our module built and published, we can now include it in our Lift applications. To do that, modify the Lift application's build.sbt to reference this new "snowstorm" dependency:
libraryDependencies ++= {
val liftVersion = "2.5"
"net.liftmodules" %% "snowstorm" % "1.0.0",
In our Lift application's Boot.scala, we finally initialise the plugin:
import net.liftmodules.snowstorm.Snowstorm
When we run our Lift application, white snow will be falling on every page, supplied by the module.
The module is self contained: there's no need for users to copy JavaScript files around or modify their templates. To achieve that, we've made use of ResourceServer. When we reference the JavaScript file via /classpath/snowstorm.js, Lift will attempt to locate snowstorm.js from the classpath. This is what we want for our Lift application, because snowstorm.js will be inside the module JAR file.
However, we do not want to expose all files on the classpath to anyone visiting our application. To avoid that, Lift looks for resources inside a toserve folder, which for our purposes means files and folders inside src/main/resources/toserve. You can think of
As a further precaution, you need to explicitly allow access to these resources. That's done with:
ResourceServer.allow {
case "snowstorm.js" :: Nil => true
We're just always returning true for anyone who asks for this resource, but we could dynamically control access here if we wanted.
S.putInHead adds the JavaScript to the head of a page and is triggered on every page by LiftSession.onBeginServicing (also discussed in [OnSession]). We could make use of Req here to restrict the snowstorm to particular pages, but we're adding it to every page.
Hopefully you can see that anything you can do in a Lift application you can probably turn into a Lift module. A typical approach might be to have functionality in a Lift application, and then factor out settings in Boot into a module init method. For example, if you wanted to provide REST services as a module, that would be possible and is an approach taken by the Lift PayPal module.
Making your module available
If you do want your module to be used by a wider audience, you need to publish it to a public repository, such as Sonatype or CloudBees. You'll also want to keep your module up-to-date with Lift releases. There are a few conventions around this.
One convention is to include the Lift "edition" as part of the module name. For example, version 1.0.0 of your foo module for Lift 2.5 would have the name foo_2.5. This makes it clear your module is compatible with Lift for all of 2.5, including milestones, release candidates, snapshots, and final releases. It also means you need to publish your module only once, at least until Lift 2.6 or 3.0 is available.
One way to manage updates is to make a modification to your module build to allow the Lift version number to change. This makes it possible to automate the build when new versions of Lift are released. To do that, create project/LiftModule.scala in your module:
import sbt._
import sbt.Keys._
object LiftModuleBuild extends Build {
val liftVersion = SettingKey[String]("liftVersion",
"Full version number of the Lift Web Framework")
val liftEdition = SettingKey[String]("liftEdition",
"Lift Edition (short version number to append to artifact name)")
val project = Project("LiftModule", file("."))
This defines a setting to control the Lift version number. You use it in your module build.sbt like this:
name := "snowstorm"
organization := "net.liftmodules"
version := "1.0.0-SNAPSHOT"
liftVersion <<= liftVersion ?? "2.5-SNAPSHOT"
liftEdition <<= liftVersion apply { _.substring(0,3) }
name <<= (name, liftEdition) { (n, e) => n + "_" + e }
libraryDependencies <++= liftVersion { v =>
"net.liftweb" %% "lift-webkit" % v % "provided" ::
Note the "provided" configuration for Lift in the build file. This means that when your module is used, the version of Lift's WebKit will be the version provided by the application being built by the person using your module.
What the previous code gives you is a way for your module to depend on Lift ("2.5"), without locking your module into a specific release if it happens to be built with "2.5-SNAPSHOT." By using a setting of liftVersion, we can control the version via a script for all modules. This is what we do to publish a range of Lift modules after each Lift release, as described on the Lift wiki.
When your module is built, don't forget to announce it on the Lift mailing list.
Debugging your module
When working on a module and testing it in a Lift application, it would be a chore to have to publish your module each time you changed it. Fortunately, SBT allows your Lift application to depend on the source of a module. To use this, change your Lift project to remove the dependency on the published module and instead add a local dependency by creating project/LocalModuleDev.scala:
import sbt._
object LocalModuleDev extends Build {
lazy val root = Project("", file(".")) dependsOn(snow)
lazy val snow = ProjectRef(uri("../snowstorm"), "LiftModule")
We are assuming that the snowstorm source can be found at ../snowstorm relative to the Lift application we are using. With this in place, when you build your Lift project, SBT will automatically compile and depend on changes in the local snowstorm module.
See Also
Originally, Lift included a set of modules, but these have been separated out to individual projects. The Lift contributor policy outlined in [LiftCodeContributions] doesn't apply to Lift modules: you're free to contribute to these modules as you would any other open source project.
The Lift wiki pages for modules can be reached via http://liftmodules.net.
The Snowstorm project has been "setting CPUs on fire worldwide every winter since 2003," and the module developed for this recipe is on GitHub.
To publish to Sonatype, take a look at their guide. CloudBees offers an open source repository.
There are other ways to structure common code between Lift applications. For an example that uses SBT modules and Git, see the mailing list discussion on "Modularize Lift Applications".