Register user, mail activation, login & logout in 1 user story with Scala & Lift!

July 12th, 2010 by Chris lutje Spelberg Leave a reply »

If you could start a new web project and are free to choose any technique available, which one would you choose?

At Software Art we have the opportunity! We are all experienced Java web developers with lots of experience in Spring MVC, JSF, GWT, Wicket, etc. While discussing these options we decided we wanted something else. So we decided to start using Scala and the Lift web framework. We are prepared for a steep learning curve, lots of sweating and lots of *****ing ;-) But in the end we expect to enjoy using a great language and have a higher development speed than possible using java. We will keep you posted..

So.. in a normal Sprint we would have defined four separate stories for implementing user registration, activation by email, login and logout. Not in this case. Scala’s web framework Lift provides the tools for implementing these behavioures in a ‘single step’.

Getting Started

We started by creating the helloworld lift application from the maven artefact as specified in the Getting Started – Using Maven guide:

mvn archetype:generate \
 -DarchetypeGroupId=net.liftweb \
 -DarchetypeArtifactId=lift-archetype-blank \
 -DarchetypeVersion=2.0-scala280-SNAPSHOT \
 -DarchetypeRepository=http://scala-tools.org/repo-snapshots \
 -DremoteRepositories=http://scala-tools.org/repo-snapshots \
 -DgroupId=nl.softwareart  \
 -DartifactId=newproject \
 -Dversion=2.0-scala280-SNAPSHOT \
 -DscalaVersion=2.8.0.RC7

We expect scala and lift to have stable versions in the near future so we use the latest greatest versions.

Scala Coding

Lift provides a user framework with traits called MetaProtoUser and MetaMegaProtoUser used for the class and the ‘Mega’ used for the companion object. It uses the ‘Mapper’ framework that provides database abstraction. The User code looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class User extends MegaProtoUser[User] {
  /**
   * Link to the companion object, required by Mapper.
   */
  def getSingleton = User
}
 
object User extends User with MetaMegaProtoUser[User] {
  override val basePath = "user" :: Nil
 
  override def screenWrap = Full(<lift:surround with="default" at="content">
      <lift:bind/>
  </lift:surround>)
 
  /**
   * Overridden to add logging of activation url to be able to activate
   * without sending mail.
   */
  override def signupMailBody(user: User, validationLink: String) = {
    Log.warn("Sending activation mail to " + validationLink)
    super.signupMailBody(user, validationLink)
  }
}

In the bootstrap code just add these lines to wire the user registration menu entries in the main menu:

1
2
3
    // Build SiteMap
    val entries = Menu(Loc("Home", List("index"), "Home")) :: User.sitemap
    LiftRules.setSiteMap(SiteMap(entries: _*))

Note the ‘User.sitemap’ at the end of the first line. Nice and compact!

Database

The last part is to map the User class to the database. The actual mapping is already done by extending from Meta(Mega)ProtoUser, so we only need to specify the database to use. Add this to the bootstrap code:

1
2
    DB.defineConnectionManager(DefaultConnectionIdentifier, H2MemoryDBVendor)
    Schemifier.schemify(true, Schemifier.infoF _, User)

Since the product is still in development we use an in-memory H2 database. To use it, define the db vendor object H2MemoryDBVendor, extending from net.liftweb.mapper.ConnectionManager as documented here. It automatically uses an in-memory database unless the production property is specified.

That’s about it, we have a working site now with nice user registration, activation, login and logout.

Enjoy Scala & Lift!

Advertisement

Leave a Reply