Sunday, October 23, 2011

Starting a Lift project with SBT and IntelliJ

Getting up and running with Scala and Lift requires a lot of tools, especially if you want to develop from an IDE.  Coming from a Ruby on Rails and PHP background, a lot of this was new to me, and the books typically assume you've done a lot of Java development and are used to dealing with build tools, compiling, dependencies, etc.

So this is my guide for how to get started with Scala and Lift development, using the IntelliJ IDEA IDE, based on me spending hours and hours trying to figure it out.  I've used Rubymine and PHPStorm which are based on IntelliJ so IntelliJ is definitely my favorite IDE.  I believe you can also do Scala development from Eclipse and Netbeans.

I won't use the very latest version of everything, because the very latest of one thing might not be compatible with the other.  Also, this assumes you're using Linux, but it will be almost the same on Windows and Mac as most of the action happens in the sbt console.  I've gathered much of the info here from the Lift In Action book which I would highly recommend for learning Lift.  The setup part of this book wasn't completely comprehensive though and I spent a lot of time with trial and error to get to this point.

First step is getting Scala set up so you can run Scala from the command line.  This is actually optional, but you may occasionally want to manually run Scala code (like irb in Ruby), or compile a stand alone Scala script.  We're going to use version 2.8.1, since this is the latest that is compatible with everything else as of this writing.  (2.9.1 is the latest as of this writing)

  1. Download Scala 2.8.1.  
  2. Extract it to your /opt directory
  3. "ln -s /opt/scala-2.8.1-final /opt/scala" to create a symlink to your scala folder without having to use the version number.  
  4. "ln -s /opt/scala/bin/scala /usr/local/bin/scala" and "ln -s /opt/scala/bin/scalac /usr/local/bin/scalac" to make links to the scala executable and scala compiler so they'll be in your path.
Simple Build Tool (SBT) is the command line utility that you'll do pretty much all of the work from, other than editing files.  It will compile your code, run your code, load dependencies, load the correct version of Scala for your app, etc.  As of this writing, 0.11.0 is the latest.  However, after version 0.7.7, sbt had a lot of pretty fundamental changes that I don't like (what happened to it creating the project directory/file structure for you, specifying plugins through the sbt console instead of editing files, etc.)  I think version 0.7.7 is easier to use, and it's what the Lift In Action book is written for, so we'll install 0.7.7.
  1. Download sbt-launch-0.7.7.jar to /usr/local/bin.
  2. Create a file named sbt in /usr/local/bin with the contents:
    java -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=1024m -Xmx512M -Xss4M -jar `dirname $0`/sbt-launch-0.7.7.jar "$@"
  3. "chmod a+x /usr/local/bin/sbt" to allow it to execute
Create The Project
This is a little different that what you may be used to.  You'll actually create the project with sbt from the command line, not from your IDE.  
  1. Make a directory for your project and cd in to it
  2. Run "sbt".  It will ask you if you want to create a new project, enter y.
  3. Enter a name for your project
  4. Enter an organization.  
  5. Enter a version number for your app
  6. Enter 2.8.1 for the Scala version
  7. Use the default 0.7.7 for the sbt version
You don't need to download and install Lift, this is all done from a tool called Lifty which is a module to sbt.  It will give you a "lift" command in sbt that performs lift actions.  As of this writing, 1.6.1 is the latest released version of lifty, which only works with sbt 0.7.7.  There is a 1.7 beta that claims sbt 0.10 support.  We're going to go with 1.6.1.
  1. From an sbt prompt, enter "*lift is org.lifty lifty 1.6.1".  This will install the lifty module globally, to allow you to type lift.  (In newer versions of sbt, you can't do this, you have to edit a file and put Scala code in, why did they take out this ability?)
  2. Assuming you're in the project directory, run "lift create project-blank".  This will make your project a Lift project, with the default files. 
  3. Leave the default value for mainpack
  4. Enter 2.3 for the liftversion (this is important, do not use the default 2.3-RC version, or 2.4 which is not compatible with Scala 2.8.1)
  5. Enter "reload" at the prompt to reload the project definition
  6. Enter "update" to compile your blank app
Your app is now compiled and ready to run!  You can type jetty-run to start up a web server for your app, then navigate to localhost:8080.  Type enter then jetty-stop to stop the server.

IntelliJ IDEA Project
I didn't forget about using IntelliJ IDEA.  Before you open the directory in IntelliJ, you need to create an IntelliJ project file so IntelliJ knows where everything is.  This is done from the sbt-idea processor.
  1. From an sbt prompt, type "*sbtIdeaRepo at"  sbt-idea is not in the standard repo so you'll need to add a reference to it with this command.
  2. Install it with "*idea is com.github.mpeltonen sbt-idea-processor 0.4.0".  This will add "idea" as an option to the sbt prompt.  
  3. Type "update" to update references
  4. In your project directory, type "idea".  This will create the project file for IntelliJ.
IntelliJ IDEA
Now on to the IntelliJ program itself.  
  1. Load IntelliJ IDEA, and before opening the project, go to File, Settings, Plugins. 
  2. In the Available tab, add the Scala and SBT plugins.
  3. Restart IntelliJ, go to File, Open Project, and find your project.  It will take some time to index everything.
  4. You'll see an error "Cannot load facet Web".  Click Details and click Yes to remove it."
  5. You MAY have to add the lib and lib_managed folders as libraries.  I can't explain it, I had to do this on the first project I set up, on the second I didn't.  If you do, go to File, Project Structure, Libraries, Add a New Project Library called Libs, Attach Jar Directories, and pick the lib and lib_managed/scala-2.8.1/compile folders.  Also for some reason, it will not pick up some of the Lift JAR files that are in lib_managed.  I could not get it to recognize mapper, so on this same page I had to click Add Classes and pick the mapper JAR file in lib_managed.  
  6. You'll have to configure the SBT plugin.  Go to File, Settings, SBT.  Under IDE settings, enter /usr/local/bin/sbt-launch-0.7.7.jar for SBT launcher JAR file
Now that this is configured, you can use the SBT console at the bottom.  Just click start, and you'll get a prompt for this project.  This is where you'll want to run everything from.

If you want to use break points and everything else that comes along with debugging, from IntelliJ:
  1. From the drop down on the top menu, click Edit Configurations
  2. Click +, then Remote.
  3. Give it a name (like jetty debug)
  4. In the Before Launch section, check Run SBT Action
  5. Click the ... beside Run SBT Action
  6. Check Run in current module
  7. Enter jetty-run for the action
  8. Click File, Settings, SBT.  
  9. Add the following to the end of the VM Parameters line under IDE settings: "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
You're all set.  Just click the Debug button, and you're good to go.  SBT will be launched with jetty-run, and you can now debug (note that if you already had an SBT console open, you'll have to kill it).

So, that's all there is to it!  :)  This is a lot to go through to get going, but now that you've got all of this set up, you should have everything you need to develop with Scala and Lift, and distribute the code when you're done.

I'm using Scala and Lift now

I've started learning the language Scala and the web framework built with it, Lift. I'll be making some blog posts soon on these.

I'm going to hold off on making any final judgments until I've written some real things in both.  But so far I'm really liking Scala and Lift. If you haven't looked in to them, I would recommend you at least give Scala a quick look over.  Even if you don't ever intend to use it for your main web app, it can be great for back end processing jobs, as concurrency is built in to the language.  And, if like me you work on some projects that can only be distributed to customer's systems that only run the JVM, Scala is built right on top of Java.  Sometimes JRuby will allow you to distribute on to the JVM, but you don't always get the newest and best running JRuby.

Learning Scala and Lift and blog background

Several months ago I read the awesome book Seven Programming Languages In Seven Weeks, and knew I wanted to learn some more about Scala.  Most of the projects I work on are low volume and wouldn't necessarily benefit a whole lot from using Scala, so I couldn't motivate myself to learn a whole new language that I might not even use.  Then I read about the Lift framework, and knew I wanted to learn both and create something real with them, regardless of what the projects I do at work are.

I've read through Programming Scala, another great book published by The Pragmatic Bookshelf, and feel that I can really develop some good Scala applications.  I've just now started reading Lift In Action to learn about Lift.  Since the community around Lift is still pretty small, and there are a lot of rapidly moving pieces with Lift, I wanted to start blogging about using Scala and Lift.  My main goal here will be to post helpful info that will save others some time.

So some background on me.  I've been doing software development for over 9 years, with the past 5 years of that being web application development.  I've done mostly Ruby on Rails and some PHP for those 5 years.  While I do still like Ruby on Rails, I think it's time for me to learn another new language that overcomes some of the down sides of Ruby and Rails.  I was an early adopter of Rails (started using it in 2006, at version 1.1), and I loved programming in something new and revolutionary.  I have a feeling Scala and Lift will play this role in the next few years.  Soon I'm going to build a side project with Scala and Lift, and I'm hoping I can incorporate it in to projects at my job.