In this article I’ll describe the setup I use to do develop Lift applications. While more heavy-weight than if an interpreted language is used, I find this setup provides fairly decent turnaround times.
So, it took a little longer than expected to write this article which continues where the previous stopped. But all good things come to he who waits :-) The software used in the previous article all had major updates in the meantime:
- Scala 2.8 (2.8.1 is just around the corner)
- Eclipse 3.6
- Scale IDE for Eclipse (though a nightly build is currently needed for Eclipse 3.6)
- Gradle 0.9 RC1
- Lift 2.1 RC2
Installing the software
I’m writing this on OS X 10.6.4, using the default Java installation:
java version "1.6.0_20" Java(TM) SE Runtime Environment (build 1.6.0_20-b02-279-10M3065) Java HotSpot(TM) 64-Bit Server VM (build 16.3-b01-279, mixed mode)
I’m using the latest Eclipse 3.6 (Helios), which can be found here. Install it and launch with a new workspace.
JRebel allows you to make code changes and have the changes reflected in your running app without restarting. This is very handy for a rapid development cycle. It’s not perfect and doesn’t work with all changes, but most of the time it picks up the changes ok. Note that you can get a free license if you only work with Scala files!
Follow step 1-3 in the instructions here to download and install JRebel as well as the JRebel Eclipse plugin.
Scala IDE for Eclipse
Next, install the Scala IDE for Eclipse from this update site: http://download.scala-ide.org/nightly-update-helios-2.8.0.final/
Use this guide as a starting point: https://www.assembla.com/wiki/show/scala-ide/Requirements_and_Installation
Try creating a small sample Scala project to verify your installation:
- Select the Scala perspective (click on ‘+’ the first time and select “Other..”)
- Right-click in Package Explorer and select New->Scala Project
- Enter helloworld as Project name
- Expand the project, right-click on the src folder and select New->Scala Application
- Enter “HelloWorld” as Object name
- Add println(“Hello, World”)
- Right-click in the editor and select Run As->Scala Application
Note, that since this is a nightly build, there may be times when the plugin is not in a good shape. Seek help on the scala-ide mailing list :-)
Creating the Lift Eclipse project
Since we’re using Gradle to manage the dependencies to external JARs (see previous article for details), we need to tell Eclipse where in the file system those jars can be found. You need to find this directory on your system. It’s usally in ~/.gradle/cache which for me maps to /Users/Jeppe/.gradle/cache.
So we create a classpath variable, GRADLE_CACHE that points to this directory. Open Eclipse preferences:
Next, create the actual Eclipse files (.classpath and .project) by running
$ ./gradlew eclipse :eclipseClasspath :eclipseProject :eclipseWtp :eclipse BUILD SUCCESSFUL Total time: 11.27 secs
Finally, import the project into Eclipse:
- Right-click in Package Explorer and select “Import…”
- Select General->Existing projects into Workspace
- Select the location of your build.gradle file as root
The created Lift application contains a main object that runs an embedded Jetty container which is very useful for development. It’s located in src/test/scala/RunWepApp.scala. Right-click this file and select Run As->Scala Application. Now Jetty starts up and you can navigate to http://localhost:8080 to see the application.
The final step is to enable JRebel for the Run configuration just created. Select “Run Configurations” and find RunWebApp$, select the JRebel tab and enable the JRebel agent.
JRebel in action
Now try to change something. Go to src/main/scala/example/snippet/HelloWorld.scala.
- Change the output of the howdy snippet by e.g. replacing “d.toString()” with some text.
- Save the file in order to compile it.
- Refresh the page in the browser.
- Watch the new content be displayed in the browser!
- Watch the console output that says JRebel has reloaded the class
As mentioned earlier, not everything can be reloaded by JRebel and not everything in Lift can be changed during runtime.
If JRebel cannot reload the changes, you usually get a runtime error (ClassNotFound, ClassCastException etc) and you’ll have to restart. If JRebel does pickup your changes and nothing happens, chances are that Lift cannot dynamically pick up the changes. Examples of the latter are:
- Things that happen in Boot. Your application is not re-booted to pickup the changes. This unfortunately includes SiteMap changes.
- Addition/removal of mapper fields. The fields of a mapped object are determined at startup and cannot change at runtime.
So, this completes the post. Enjoy! And please provide feedback if you have any ideas to improve the development cycle!