Scala powered Lift web framework - Eclipse, Scala IDE, latest versions of everything Jan 2013

I'm searching for a rock solid, performant and scalable framework for my new venture Linguathon, as I said in my last article. Hey, instead of server side javascript, why not server side Java? Or Scala? Wicket? Why not Lift?

Why not indeed! Considering that I spent many years working with the Spring framework (plain old Java objects) on desktop apps years ago, as a lightweight alternative to Enterprise Java, things might start looking quite powerful and familiar, and yet streamlined and better. Things might calm down a little and I might get a productive, solid environment to rock on!

So I'm documenting how I got up and running now with the latest versions of Lift and the Scala IDE for Eclipse, etc., on a souped up MacBook Air, it's pretty sui generis but it might help someone, certainly myself if I come back to things after a stint at something else.

First off I installed sbt with homebrew just like everything else, but it is not the best choice, since I think it's better to start off with little basic and blank app Lift templates, and for these the appropriate version of sbt is local, like. You'll see what I mean in a sec.

I was delighted to see a nice new book, Lift in Action: The Simply Functional Web Framework for Scala on Safari Books Online. It will definitely help me penetrate the new framework and dev-test-release environment, a great find. Part 2 has a cool auction application tutorial, totally compatible with the latest Lift release, and I'm looking forward to working through that.

Since Scala is fully interoperable with Java, you can actually use "your favorite" build tools and IDE, and be done. I remember Maven, for example, and the cool online Lift book Exploring Lift goes that route, so please feel free to check that out.

But many use the Scala Build Tool sbt, as per Lift in Action and other sources. And there's the rub. As author Timothy Perrett explains in section 2.1 Getting Started with SBT,

"As this book was being finished, the SBT project was starting to release early versions of a completely redesigned version of SBT under the 0.10+ branches. Currently this series is so radically different that the configuration and setup will differ from what is described here. The 0.7 series will continue to be supported for the foreseeable future, so using it is fine, and, when the time comes, migrating to the official 1.0 version of SBT shouldn’t be too difficult."

And it wasn't, really, so one of the reasons for writing this was to document that. To document what I did, anyway.

Downloading the latest version of Lift and running the basic example

When I found that I had to fend for myself getting Lift up and running, I was relieved to find some serious assistance in the form of the very up-to-date Lift documentation, the free and online Lift Cookbook. Wonderful! I just went to the Downloading and Running Lift section and followed the instructions for Mac and Linux, and I was up and away. I had Java 1.7 on my Mac, I had taken that off since it caused a lot of problems on my Mac, and gone back to Java 1.6:

$ java -version
java version "1.6.0_37"
Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909)
Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode)

I then downloaded Lift 2.5 Milestone 4 from the Lift download page, and unpackaged it into a suitable working directory, changed directory there and then changed into the scala_29/lift_basic subdirectory. I typed "./sbt" (i.e. execute the sbt version in the current directory (important)), allowed things to trundle for quite some time (just the first time: sbt caches the dependencies it downloads), then at the sbt prompt typed "container:start" (that's sbt newspeak), and pointed my browser at http://localhost:8080 to enjoy the bare-bones app I was now running. The second time I followed these instructions, things went much quicker:

$ ./sbt
[info] Loading project definition from /Users/victorkane/Lift/lift-lift_25_sbt-b9779cc/scala_29/lift_basic/project
[info] Set current project to Lift 2.5 starter template (in build file:/Users/victorkane/Lift/lift-lift_25_sbt-b9779cc/scala_29/lift_basic/)
> container:start
[info] jetty-8.1.7.v20120910
[info] NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet
[info] started o.e.j.w.WebAppContext{/,[file:/Users/victorkane/Lift/lift-lift_25_sbt-b9779cc/scala_29/lift_basic/src/main/webapp/]}
[info] started o.e.j.w.WebAppContext{/,[file:/Users/victorkane/Lift/lift-lift_25_sbt-b9779cc/scala_29/lift_basic/src/main/webapp/]}
[info] Started SelectChannelConnector@0.0.0.0:8080
[success] Total time: 2 s, completed Jan 30, 2013 1:11:59 PM

To stop the app, I did:

> container:stop
[info] stopped o.e.j.w.WebAppContext{/,[file:/Users/victorkane/Lift/lift-lift_25_sbt-b9779cc/scala_29/lift_basic/src/main/webapp/]}
[success] Total time: 0 s, completed Jan 30, 2013 1:13:42 PM
> exit

Getting the right version of Eclipse and Scala IDE up and running

The Lift Cookbook shows you how to use a text editor, as well as how to integrate with the Eclipse and Intellij IDEA IDEs. I chose to follow the Developing using Eclipse section. Here's what I did:

  • Create and run the "Scala rocks" example program to make sure you are all set.

MyScala > src > (default package) > MyProgram.scala reads:

object MyProgram {

  def main(args: Array[String]): Unit = {
    println("Hello, world!")
  }
 
}

Procedure for starting a brand new LIFT project on Eclipse with ScalaIDE

At the end of the day, my conclusion was the following procedure based on the Getting Started section of the Lift Assembla Wiki:

  • Clone the appropriate release milestone directly from GitHub and change to lift basic starter template directory or folder
bash-3.2$ git clone git://github.com/lift/lift_25_sbt.git freshproject
Cloning into 'freshproject'...
remote: Counting objects: 937, done.
remote: Compressing objects: 100% (548/548), done.
remote: Total 937 (delta 330), reused 877 (delta 270)
Receiving objects: 100% (937/937), 3.05 MiB | 418 KiB/s, done.
Resolving deltas: 100% (330/330), done.
cd freshproject/scala_29/lift_basic/
bash-3.2$ ls
build.sbt        sbt            sbt.bat
project            sbt-launch-0.12.1.jar    src
  • Edit build.sbt to read as follows (first three lines changed only):
name := "My Fresh Project"

version := "0.0.1"

organization := "com.awebfactory"

scalaVersion := "2.9.1"

resolvers ++= Seq("snapshots" at "http://oss.sonatype.org/content/repositories/snapshots",
"releases" at "http://oss.sonatype.org/content/repositories/releases"
)

seq(com.github.siasia.WebPlugin.webSettings :_*)

unmanagedResourceDirectories in Test <+= (baseDirectory) { _ / "src/main/webapp" }

scalacOptions ++= Seq("-deprecation", "-unchecked")

libraryDependencies ++= {
val liftVersion = "2.5-M4"
Seq(
"net.liftweb" %% "lift-webkit" % liftVersion % "compile",
"net.liftweb" %% "lift-mapper" % liftVersion % "compile",
"net.liftmodules" %% "lift-jquery-module" % (liftVersion + "-2.1"),
"org.eclipse.jetty" % "jetty-webapp" % "8.1.7.v20120910" % "container,test",
"org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "container,test" artifacts Artifact("javax.servlet", "jar", "jar"),
"ch.qos.logback" % "logback-classic" % "1.0.6",
"org.specs2" %% "specs2" % "1.12.1" % "test",
"com.h2database" % "h2" % "1.3.167"
)
}
  • Edit project/plugins.sbt to make sure "sbteclipse" is installed (the line was already there):
//Enable the sbt eclipse plugin
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")
  • Run local sbt
bash-3.2$ ./sbt
[info] Loading project definition from /Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/project
[info] Updating {file:/Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/project/}default-29ae76...
[info] Resolving org.scala-sbt#precompiled-2_10_0-m7;0.12.1 ...
[info] Done updating.
[info] Set current project to My Fresh Project (in build file:/Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/)
[info] Updating {file:/Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/}default-e522fe...
[info] Resolving org.eclipse.jetty#jetty-io;8.1.7.v20120910 ...
[info] Done updating.
>
  • Inside the sbt console, create Eclipse project ready to import
> eclipse
[info] About to create Eclipse project files for your project(s).
[info] Successfully created Eclipse project files for project(s):
[info] My Fresh Project
  • Inside the sbt console, run app
> container:start
[info] Compiling 4 Scala sources to /Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/target/scala-2.9.1/classes...
[info] jetty-8.1.7.v20120910
[info] NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet
[info] started o.e.j.w.WebAppContext{/,[file:/Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/src/main/webapp/]}
[info] started o.e.j.w.WebAppContext{/,[file:/Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/src/main/webapp/]}
[info] Started SelectChannelConnector@0.0.0.0:8080
[success] Total time: 12 s, completed Jan 30, 2013 3:07:35 PM
>
> container:stop
[info] stopped o.e.j.w.WebAppContext{/,[file:/Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/src/main/webapp/]}
[success] Total time: 0 s, completed Jan 30, 2013 3:09:28 PM
>
  • Open up Eclipse to Scala Perspective as per video at http://scala-ide.org/download/current.html
  • Import as per Cookbook instructions at http://cookbook.liftweb.net/#eclipse
    • File > Import >> General >> Existing Projects into Workspace
    • Click on Next Button
    • Browse to document root of Lift basic project starter template which we have begun to tailor
    • Optionally check "Copy projects into workspace"
    • Click Finish
    • "My Fresh Project" appears in Project explorer
  • From the sbt console, run app in "Watch" mode
> ~; container:start; container:reload /
[info] jetty-8.1.7.v20120910
[info] NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet
[info] started o.e.j.w.WebAppContext{/,[file:/Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/src/main/webapp/]}
[info] started o.e.j.w.WebAppContext{/,[file:/Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/src/main/webapp/]}
[info] Started SelectChannelConnector@0.0.0.0:8080
[success] Total time: 1 s, completed Jan 30, 2013 3:32:44 PM
[info] stopped o.e.j.w.WebAppContext{/,[file:/Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/src/main/webapp/]}
[info] NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet
[info] started o.e.j.w.WebAppContext{/,[file:/Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/src/main/webapp/]}
[info] started o.e.j.w.WebAppContext{/,[file:/Users/victorkane/Work/ESL/Linguathon/dev/Lift/freshproject/scala_29/lift_basic/src/main/webapp/]}
[success] Total time: 1 s, completed Jan 30, 2013 3:32:45 PM
1. Waiting for source changes... (press enter to interrupt)
  • Make changes to code, reload browser to see changes if web resources changed

Interesting discussions

See:

Lift from scratch alternative

See http://cookbook.liftweb.net/#LiftFromScratch

This discussion contains a reference to a sample project created using this method at: https://github.com/bubblefoundry/lift-from-scratch  This project could be cloned and worked with in similar fashion to the Lift release, as described above.