Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

What's new in Lift 2.0?

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

Summary:  Lift is a web application development framework that enables the building of web applications in the Scala programming language. Because it is powered by Scala, Lift can be deployed to any Java™ Servlet container such as Tomcat or Jetty, and can make use of both Java and Scala libraries and APIs. In June 2010, Lift 2.0 became available, and it boasts an impressive array of new features and highlights. This article describes many of these features and explains how they can benefit you in the development of your own web applications.

Date:  15 Mar 2011
Level:  Intermediate PDF:  A4 and Letter (69KB | 18 pages)Get Adobe® Reader®
Also available in:   Japanese

Activity:  12949 views
Comments:  

What is Lift?

Lift is a free, open source web application development framework for building powerful, interactive, and dynamic applications using the Scala programming language. Scala is purely object-oriented, but, uniquely, it also has support for functional programming, giving you access to features such as anonymous functions, nested functions, curry functions, and higher-order functions. Scala runs in a Java Virtual Machine (JVM), making it compatible with Java applications and libraries. These traits mean that web applications powered by Lift can use both Scala and Java class libraries. In addition, Lift applications are packaged as Web Application Archive (WAR) files and can be deployed to any web application server that supports the Servlet 2.4 specification, including Apache Tomcat 5.5 and later.

Features at a glance

As a web application framework, Lift encourages the development of applications that maintain a high level of security and scalability, providing users with rock solid performance and usability. By default, Lift applications are resistant to common web application vulnerabilities including cross-site scripting (XSS) attacks, cross-site request forgery, and hostile data injection.

Following are some of the features that Lift has to offer web app developers:

  • World-class Comet support for developing real-time interactive push-enabled web applications
  • Automatic Asynchronous JavaScript and XML (Ajax) request handling
  • Site Map configurations that offer automated menus, pretty URLs, security and access control, and more
  • Proper designer-friendly view templates—No application logic and programming code can be included in the static templates
  • Lift apps can be deployed to a variety of application servers including Tomcat, Jetty, Glassfish, and JBoss—basically any Java web container that supports the Servlet 2.4 specification
  • ORM and ActiveRecord persistence layers included out of the box
  • Great support for internationalization through property bundles, localized templates, and customer resource bundle providers.
  • Powerful JSON support including parsing, queries, validation, conversion, serialization, and other features
  • Excellent form validation, with declarative logic that does not require working with HTTP requests directly (LiftScreen and Wizard)
  • Lift makes it a breeze to provide RESTful web service APIs
  • A growing library of widgets that let you include components like autocomplete fields, day/week/month view calendars, data grids, charts, and hierarchical tree controls
  • Additional modules that extend Lift's feature set even further, including OAuth and OpenID

Lift in the real world

Although Lift is a relatively new web framework (version 1.0 was released in February 2009), it is already in use in some impressive large projects. Most notable is its use in the Foursquare location-oriented social network, which was ported to Lift and PostgreSQL from a PHP and MySQL configuration in late 2009. After the port, Rasmus Lerdorf famously tweeted: "Four stars to @foursquare — 1st site in a while I have taken a good look at that didn't have a single security issue (that I could find)."

Since porting to Lift, Foursquare has grown exponentially, with a reported 5 million users across the globe, checking in from any location worldwide. See the Resources section of this article for a link to a presentation given by Harry Heymann of Foursquare on his experience with developing using Lift and Scala.

Another widely used project that is powered by Lift is Novell's Vibe Cloud product, which provides enterprise social networking features, real-time collaboration and document editing facilities, file sharing, synchronization, and much more. Novell has cited Lift's excellent Comet support as one of the greatest benefits of using the framework (see Resources).

Other notable Lift users include Innovation Games, XMPie, Exchango, Snapshort, and No Fouls.


Exploring Lift 2.0's new features

Lift 2.0 and subsequent releases have delivered significant improvements and additional features over version 1.0. In this section, I will briefly highlight the new features the latest versions of the framework have to offer.

Lift 2.0

Lift 2.0 was announced on June 30, 2010, and is a significant upgrade from version 1.0. Some of the most notable enhancements include:

  • Improved Comet support
  • Declarative form validation and input using LiftScreen and Wizard
  • JSON parsing, validation, conversion, and querying support
  • Simple interface for deploying RESTful services
  • Support for NoSQL databases out of the box—CouchDB and MongoDB
  • Support for Simple Build Tool in addition to Maven
  • JTA and LDAP support
  • Ability to run applications outside of Servlet containers

Lift 2.1

Lift 2.1 was released on September 24, 2010, and brought with it the following improvements:

  • Support for Scala 2.8
  • Improvements in NoSQL database support
  • Support for Squeryl, a Scala ORM and DSL for SQL databases

Lift 2.2-RC2

On December 15, 2010, the Lift team announced the second release candidate version, Lift 2.2. Following are just some of the highlights of this release:

  • Support for Scala 2.8.1
  • HTML5 support
  • Automated update of dependent page elements through the Wiring feature
  • Improvements to the LiftScreen and Wizard features
  • CSS Selector Transforms in templates
  • Improved internationalization
  • Security enhancements
  • Improved MongoDB support
  • Imporved Squeryl integration

Designer-friendly templates

If you have developed a project using an MVC web application framework before, you will probably be familiar with the concept of templates or views, where the appearance and presentation tiers of the application are kept separate from the business logic and programming code. One of the aims of this architecture is to allow the design elements of a project to be worked on by designers, with little programming knowledge or work required on their part.

In truth, this is rarely the case, and many views or templates in an MVC application can end up containing quite a large amount of code. In many cases, to implement some conditional logic or iteration, some programming code is included in templates and views. In the CodeIgniter framework, for example, it is suggested that if you need to display the rows in an array, you use PHP's short syntax to do so in your views or templates. The obvious problem here is that the person working on the template needs to understand the syntax of these constructs in the relevant programming language. Another issue is that including programming code in these views makes it difficult to edit the template in a standard HTML editor or to validate the document using W3C validation tools.

An example of this issue can be seen in the template shown in Listing 1, which illustrates a typical template that needs to iterate over an array of objects. In this example, I've used the CodeIgniter and short PHP syntax mentioned previously.


Listing 1. Illustrating the logic inside template problem

<h1>Vegetables</h1>
<ul>
    <?php foreach($vegetables as $vegetable): ?>
    <li><?php echo $vegetable; ?></li>
    <?php endforeach; ?>
</ul>

The obvious problem with the code in Listing 1 is that you are relying on the designer to be comfortable with some basic PHP code constructs. They could easily change some part of the PHP code that causes the entire template to break, and debugging issues that reside in logic inside of templates can be a nightmare.

Lift was built with the primary design goal that static templates do not contain ANY programming logic or symbols, ensuring that it is possible to edit templates in design tools like Dreamweaver, and that designers can pass their HTML code using validation tools. Listing 2 illustrates how the template created in Listing 1 might look in Lift.


Listing 2. Avoiding programming logic with Lift (the old way)

<lift:surround with="default" at="content">
    <h1>Vegetables</h1>
    <ul>
        <lift:vegetables>
            <li><vegetable:name /></li>
        </lift:vegetables>
    </ul>
</lift:surround>

An improvement, I'm sure you'll agree. First, there are no pesky PHP tags or foreach constructs. The tag structure used here will be much more familiar to designers. With that said, this approach still suffers from the problem that it will not validate as valid (X)HTML markup, as it uses custom tags in the lift namespace. To validate correctly, you would need to explicitly define this namespace, which is overkill when you just want to create some HTML design templates.

As of version 2.2, Lift lets you use CSS class attribute values to define how snippets should be invoked, so all Lift templates will validate correctly without requiring the lift namespace to be declared explicitly. Rather than using custom tags, you now use regular valid HTML elements, so everything validates as HTML. This approach to writing templates looks like Listing 3.


Listing 3. Valid (X)HTML templates with Lift 2.2

<div class="lift:surround?with=default;at=content">
    <h1>Vegetables</h1>
    <ul class="lift:vegetables">
        <li><span class="name"></span></li>
    </ul>
</div>

A little bit later, you will see how this new approach to defining templates makes it easier to write Scala snippets that bind to these templates.


HTML5 support

By default, Lift outputs XHTML, and the content type of HTTP responses are "application/xhtml+xml" with a UTF-8 character set. Of course, there are many reasons why you may not be happy to use XHTML markup. With HTML5 emerging as the new defining standard for web application development, it is more important than ever to have options for how content will be sent to the browser.

Up until Lift 2.2, XHTML was the only option for output and input parsing. This is still the default behavior in the current version, but at least now you have the option to enable full HTML5 support in Lift. The various properties that define how HTML is parsed and output in Lift are kept in the HTMLProperties object. These properties are docType, encoding, contentType, htmlOutputHeader, htmlParser, htmlWriter, html5FormsSupport, maxOpenRequests, and userAgent. You can change any of these values mid-session or mid-request using LiftSession.sessionHtmlProperties and LiftSession.requestHtmlProperties. Alternatively, you can change the default setting to use HTML5 rather than XHTML by adding the following LiftRule in Boot.scala:

LiftRules.htmlProperties.default.set((r: Req) =>new Html5Properties(r.userAgent))

When HTML5 support is switched on in this way, the standard DOCTYPE for your pages will be the HTML5 declaration. Additionally, the Content-Type of your responses will be text/html, and your HTML syntax will be parsed using the nu.validator.htmlparser rather than the standard Scala XML parser.


CSS selector transforms

As anyone who has used Lift will know, Lift treats HTTP requests as transformations of input to output, using snippet functions to bind values to fields in a template. In Lift 2.2 and later, you can bind snippets to the template using CSS selectors. To see the advantages this offers, take a look at an example of CSS selector transforms in action. First, take an example that uses the old way of binding values to templates. Listing 4 shows a template to be used for old-style binding.


Listing 4. Template for old-style binding

<div class="lift:surround?with=default;at=content">
    <h2>A simple example</h2>
    <span class="lift:example.hello">
       <p>Hi there, <span class="person:name />!</p>
    </span>
</div>

Listing 5 shows the snippet for binding values to the template in Listing 4.


Listing 5. Snippet for binding values to template

class Example {
    def hello(xhtml:NodeSeq) = {
        bind("person", xhtml, "name" -> "Joe")
    }
}

In Listing 5, the hello function binds to the person:name element, replacing the contents with value Joe. The end result would be output like that shown in Listing 6.


Listing 6. Output result from above Snippet

<div>
<h2>A simple example</h2>
<span>
    <p>Hi there, Joe!</p>
</span>
</div>

Let's make a slight amendment to the template, this time simply giving the value you want to replace with output an ID attribute (see Listing 7).


Listing 7. Modified template with ID attribute

<div class="lift:surround?with=default;at=content">
    <h2>A simple example</h2>
    <span class="lift:example.hello">
       <p>Hi there, <span id="name" />!</p>
    </span>
</div>

Now let's use CSS selector transforms to render my name into the element with the ID attribute name (see Listing 8).


Listing 8. Modified snippet using CSS ID selector transform

class Example {
    def render = "#name" #> "Joe"
}

The result of Listing 8 should be identical to Listing 6. In this example, you are using the CSS ID selector, but you can also use various other selectors. Table 1 shows some examples.


Table 1. CSS Selector Transform examples
SelectorTemplateOutput
"#name" #> "Joe" <span id="name" /> Joe
"#name *" #> "Joe" <span id="name" /> <span id="name">Joe</span>
"#name [rel]" #> "friend" <span rel="" id="name">Joe</span> <span rel="friend" id="name">Joe</span>
".highlight" #> (n: NodeSeq) => n ("style", "color: red") <span class="highlight">Joe</span> <span class="highlight" style="color: red">Joe</span>
"href=# [href]" #> "about:blank" <a href="#">Link</a> <a href="about:blank">Link</a>

As you can see, the left side of the CSS selector transform defines the selector to use and the replacement rule to use. You can use any of the following CSS selectors:

  • ID (for example, #name) will select the element with the ID name
  • Class (for example, .highlight) will select all elements with the class name highlight
  • Attribute value (for example, href=#) will select all elements with the attribute href set to a value #

The replacement rules tell Lift what it should replace in any matching elements. You can use any of the following options:

  • Using no replacement rule will replace the entire matching elements
  • * will replace the inner content of the matching elements
  • [href] will replace the value of the href attribute of the matching elements

The right side of the transform defines what values should be used when replacing the template elements. This can be one of several types:

  • String constant
  • NodeSeq constant
  • NodeSeq=>NodeSeq transform function
  • Bindable
  • StringPromotable constant
  • IterableConst

CSS selector transforms offer a powerful and shorthand alternative to Lift's original template binding syntax and will probably make more sense to developers who have worked with CSS selectors (for example, developers who have used JavaScript libraries such as jQuery or Dojo).


LiftScreen and Wizard

Lift 2.0 introduces LiftScreen and Wizard, two concepts that offer a radically improved method of handling web forms in terms of validation and state management. Any web developer will have experience working with traditional web form handling—you have a client-side form, perhaps with some JavaScript validation, and then you process it and validate it on the server side. If there is a problem, your application responds as such and you start again. This is quite a tedious process; primarily because of the amount of work you need to do with making and responding to HTTP requests.

LiftScreen and Wizard aim to simplify the process of form handling by providing the following features:

  • Validate your forms without directly using HTTP
  • Validate your forms declaratively
  • Automatic state management
  • Browser history management (no broken Back buttons)
  • Strongly typed form elements

LiftScreen provides for single-form input handling and validation, whereas Wizard provides for multipage forms, where you might navigate between sections of a form using Next and Previous buttons, with each stage validated as you go. Lift Wizards are actually a collection of Screens, with logic to determine which order they should appear in. For example, if you wanted to have different screens display based on the user's input in one screen, you can do so using Wizards.

Let's take a quick look at a very simple LiftScreen in action in Listing 9.


Listing 9. LiftScreen basics

object WhatsMyName extends LiftScreen {
    val name = field(S ? "Please enter your name", "", 
valMinLen(1, "Name is a mandatory field"))
    def finish() {
        S.notice("Hello, "+name.is+"!")
    }
}

You could then add the screen in Listing 9 to a Lift template as follows:

<div class="lift:WhatsMyName" />

The concept behind Wizards is very similar to the LiftScreen, except that you can have multiple screens. Listing 10 is an example where you have one screen to enter your name, then a second screen to enter your company.


Listing 10. Wizard basics

object PersonWizard extends Wizard {
    val screen1 = new Screen {
        val name = new Field with StringField {
            def title = S ?? "Please enter your name"
        }
    }

    val screen2 = new Screen {
        override def screenTop = <div>Hello {page1.name}!</div>

        val company = new Field with StringField {
            def title = S ?? "Please enter company name"
        }
    }

    val screen3 = new Screen {
        override def screenTop = <div>Hello {page1.name} who works in 
{page2.company}!</div>
    }
}

LiftScreen and Wizard are probably the elements of Lift (well, maybe aside from Comet) that I am most excited about for the future. The Lift demos page contains some good examples of Wizards, and the Lift wiki has some detailed information about creating LiftScreens.


JSON support

JSON (JavaScript Object Notation) is a lightweight data interchange format that is becoming extremely popular in modern software development, particularly in the development of web applications. With excellent cross-language implementation support and its ability to be read natively by modern web browsers, people are often turning to JSON where they may previously have used XML.

Lift 2.0 introduced lift-json, a new library for working with JSON data. The features available in this library include:

  • JSON parsing
  • LINQ-style JSON queries
  • Serialization
  • Pretty JSON printing
  • Converting between JSON and XML
  • Manipulation using XPath-style expressions
  • Support for Merging and Diffing two JSON expressions

The lift-json library comes as part of the Lift framework, but is actually a stand-alone project that can be included in other Scala projects that don't use Lift. The project can be forked on Github and includes an excellent readme, which explains the library in great detail (see Resources).

Let's take a look at some examples of how lift-json makes working with JSON data easier. First, let's take some Scala types and create a JSON string from them:

val json = JsonAST.render(List(1, 2, 3, 4, 5))

This statement would result in the json value containing the following string:

[1,2,3,4,5]

So the Scala list has been mapped to a JSON array. What about JSON objects? Those are easy too, thanks to the ~ operator in Scala.


Listing 11. Mapping the Scala list to a JSON array

val obj = ("name" -> "Joe Lennon") ~ ("company" -> "Core International") 
~ ("email": "joe@joelennon.ie")
val json = JsonAST.render(obj)

This time, JSON would contain the following string:

{"name":"Joe Lennon","company":"Core International","email":"joe@joelennon.ie"}

As you can see, it's pretty easy to convert to JSON, but what about the other way around? Let's take the first example and turn it around. Let's say you have the string [1,2,3,4,5] and you want to create a List from it. You can use the lift_json parse function to do just that:

val obj = parse("""[1, 2, 3, 4, 5]""")

This produces a JArray object, which contains a List of the items in the given JSON array. This could be denoted as follows:

JArray(List(JInt(1), JInt(2), JInt(3), JInt(4), JInt(5)))

For further information on lift-json, see the Resources section to get a link to the readme file on Github.


NoSQL database support

Lift can work with various database systems, including traditional relational DBs like PostgreSQL, MySQL, SQL Server, and Apache Derby. Lift 2.1 includes native support for Squeryl, an Object-Relational Mapping (ORM) framework for Scala, providing direct integration with Lift's Mapper and Record features.

In recent times, there has been a steady increase in interest in new database management systems that are non-relational or don't use the Structured Query Language (SQL) to interact with the database. Two of the most popular "NoSQL" databases are MongoDB and CouchDB—document-oriented databases that store data in JSON-like object constructs, with all data self-contained in the majority of cases. For more information on the benefits (and pitfalls) of these databases, see the articles "Exploring MongoDB" and "Exploring CouchDB," which provide a detailed introduction to these emerging open source projects (see Resources for links). Now take a brief look at how Lift 2.0 lets you communicate directly with a MongoDB and CouchDB database.


Working with MongoDB

Lift 2.0's MongoDB support is available through two components, lift-mongodb and lift-mongodb-record. The main code and MongoDB driver is contained in the lift-mongodb library, which lets you directly communicate with the database at a low level, providing for manual document and database creation and management. The lift-mongodb-record provides an implementation of the Record framework for the MongoDB database. Let's take a look at some basic commands to work with the MongoDB driver.

To define a default database to use, you can use the following command:
MongoDB.defineDb(DefaultMongoIdentifier, MongoAddress(MongoHost("localhost", 27017), "my_database"))

Next, let's connect to this database; create a document and save it in a collection (see Listing 12).


Listing 12. Working with MongoDB

MongoDB.use(DefaultMongoIdentifier) ( db => {
val doc = new BasicDBObject
     doc.put("name", "Joe Lennon")
      doc.put("company", "Core Intrernational")
      doc.put("email", "joe@joelennon.ie")
      val coll = db.getCollection("people")
      coll.save(doc)
})

You can use the MongoDocument library to create object classes that will be saved as documents in the database. First, you need to define the class, as shown in Listing 13.


Listing 13. Defining the Person record structure

case Class Person(_id: String, name: String, company: String, 
email: String) extends MongoDocument[Person] {
      def meta = Person
}

object Person extends MongoDocumentMeta[Person] {
      override def mongoIdentifier = DefaultMongoIdentifier
      override def collectionName = "people"
}

Now, you can create a document of this type, as shown in Listing 14.


Listing 14. Creating a person document

val person1 = Person(
    ObjectId.get.toString,
    "Joe Lennon",
    "Core International",
    "joe@joelennon.ie"
)

To save the document, simply call the save function:

person1.save

You can retrieve documents from the database using the find function. To retrieve the above document, you could use:

val person1Copy = Person.find(person1._id)

To delete the document, you can use the following command:

person1.delete

For more information on working with MongoDB documents and for details on how to work with the lift-mongodb-record component, refer to the Lift documentation (see Resources).


Working with CouchDB

Lift's CouchDB support comes through a driver that automatically handles the HTTP requests and responses required to interact with CouchDB's RESTful interface. Let's get started and take a look at how you can connect to a CouchDB database (see Listing 15).


Listing 15. Connecting to a CouchDB database

val db = new Database("my_database")
db createIfNotCreated(new Http())
CouchDB.defaultDatabase = db

Listing 15 creates a CouchDB database object, and creates the physical database itself if it doesn't exist. It then tells CouchDB to use this database. Next, define a record structure for the Person object, like you did in the section on MongoDB (see Listing 16).


Listing 16. Defining the Person record structure

class Person extends CouchRecord[Person] {
    def meta = Person

    object name extends StringField(this, 100)
    object company extends StringField(this, 200)
    object email extends StringField(this, 255)
}

object Person extends Person with CouchMetaRecord[Person] {
    def createRecord = new Person
}

You can now create a person object, give it values for the three properties (name, company, and email), and save it to the database, as shown in Listing 17.


Listing 17. Using the Person structure to save data to CouchDB

val person1 = Person.createRecord.name("Joe Lennon")
.company("Core International").email("joe@joelennon.ie")
person1 save

You can easily change an attribute's value on the fly. For example, if I wanted to set the name of person1 to Joseph Lennon, I could use the code shown in Listing 18.


Listing 18. Setting an attribute's value on the fly

person1.name.set("Joseph Lennon")
person1 save

Querying data in CouchDB works in quite a unique way, basically using a set of permanent Map/Reduce view functions stored in design documents in the database itself (ad-hoc querying is possible, but is much slower). My book, Beginning CouchDB features a detailed overview of Map/Reduce and CouchDB views (see Resources for a link). Let's use Lift to create a design document for querying the documents now (see Listing 19).


Listing 19. Creating a CouchDB view design document

val design_doc: JObject =
    ("language" -> "javascript") ~
    ("views" -> (("all_people"-> ("map" -> "function(doc) 
{ if(doc.type === 'Person') { emit(doc._id, doc); } }"))))
Http(database.design("my_design_doc") put design_doc)

The code in Listing 19 will basically create a CouchDB view that returns all documents with the type attribute value Person, indexed by the _id attribute. This view will be kept in the design document named my_design_doc. You can then use this view as follows:

val results = Person.queryView("my_design_doc", "all_people")

For information on setting up your Lift application to use the CouchDB driver, and for more detailed instructions on its use, refer to the Lift wiki.


Conclusion

This article outlined the new features and enhancements in version 2.0 of the Lift web application development framework. First, you learned what Lift is and the general features that it provides. You then discovered the new features specific to versions 2.0, 2.1, and 2.2-RC1 of Lift. Finally, the article provided detailed analysis of some of these new features, including the improvements to the template system; inclusion of support for HTML5, JSON, and NoSQL databases; and other features like LiftScreen, Wizard, and Wiring. Hopefully, the article has inspired you to go further and learn more about this brilliant open source web framework.


Resources

Learn

Get products and technologies

Discuss

About the author

Photo of Joe Lennon

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

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=631798
ArticleTitle=What's new in Lift 2.0?
publish-date=03152011
author1-email=joe@joelennon.ie
author1-email-cc=bwetmore@us.ibm.com

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers