Rapid Lift application development with Eclipse and JRebel

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)

Eclipse

I’m using the latest Eclipse 3.6 (Helios), which can be found here. Install it and launch with a new workspace.

JRebel

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:

  1. Select the Scala perspective (click on ‘+’ the first time and select “Other..”)
  2. Right-click in Package Explorer and select New->Scala Project
  3. Enter helloworld as Project name
  4. Expand the project, right-click on the src folder and select New->Scala Application
  5. Enter “HelloWorld” as Object name
  6. Add println(“Hello, World”)
  7. 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:

  1. Right-click in Package Explorer and select “Import…”
  2. Select General->Existing projects into Workspace
  3. 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.

Restart the application. JRebel should print something to the console.

JRebel in action

Now try to change something. Go to src/main/scala/example/snippet/HelloWorld.scala.

  1. Change the output of the howdy snippet by e.g. replacing “d.toString()” with some text.
  2. Save the file in order to compile it.
  3. Refresh the page in the browser.
  4. Watch the new content be displayed in the browser!
  5. 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!

About these ads

11 responses to this post.

  1. Perfectly done! Thanks for the Lift+JRebel review!

    Reply

  2. […] This post was mentioned on Twitter by Jeppe Nejsum Madsen, Anton Arhipov. Anton Arhipov said: RT @nejsum: New blog post: Rapid #lift app dev with #eclipse and #jrebel: http://bit.ly/abCDiZ #scala […]

    Reply

  3. Posted by Parsa on October 2, 2010 at 05:22

    Impressive.

    Reply

  4. Posted by Andre on November 11, 2010 at 16:29

    Like you posts about the lift framework, since its realy not easy to start with. Also appritiate the use of graddle.

    Could you provide an example how to use Lift with JPA? Perhaps as a mixed Java/Scla project.
    As a start, maybe you could just post as reply, how to do JPA Bytecode Enhancement on Entity classes in graddle after java/scala compile task.

    Thanks in Advance

    Reply

    • Posted by Jeppe on November 11, 2010 at 16:45

      Hi, I’m not using JPA so don’t have any examples handy. You should ask on the Lift mailing list. Very friendly people :-)

      Not sure how the JPA stuff runs, but you should be able to add a task after compilation by something like:

      task compileScala << { // Do JPA stuff for Scala here }
      task compileJava << { // Do JPA stuff for Java here }

      /Jeppe

      Reply

  5. Posted by Jeff McKenna on December 12, 2010 at 08:05

    I like your post and have started to try it. After the liftstart got running, then importing into Eclipse I get some 27 errors.
    starting with RunWebApp saying mortbay in not a value of package org, another error in AppTest is that junit is not a member of package root.
    It sounds like something basic is wrong. Can you direct me to a place that might be able to help me address the issue?

    Reply

    • Posted by Jeppe on December 12, 2010 at 19:24

      Sounds maybe like a classpath issue. Does the error appear as a “Scala problem”? Did you define the GRADLE_CACHE variable? Probably best to bring it to the scala-ide mailing list first

      Reply

      • Posted by Jeff McKenna on December 12, 2010 at 19:29

        I did set GRADLE_CACHE. They are all Scala problems. I’ll take it over to scala-ide.
        Thanks

  6. Outstanding! Your liftstart on github is updated to 2.8.1 and 2.4-M1, I tried it with 2.9.0 and 2.4-M3 but there is a problem with the javamail (pom is looking for 1.4.4). however, it works perfectly with scala 2.9.0 and lift 2.4-M2.

    quick question if you have a sec as I am not familiar with Gradle (yet :-)), once this is setup how do you handle adding additional dependencies in build.gradle, i.e. say I need amqp added in, what is needed to get library downloaded once I add dependency to build.gradle? do I need to do anything to get eclipse to recognize new libraries?

    thanks!

    Reply

    • Posted by Jeppe on August 5, 2011 at 19:34

      Yeah, will update this soon to match new versions ;-)

      To add a dependency, change the dependencies {} section. You probably need to add to the “compile” section in the same way as the lift dependencies. You should run “./gradlew eclipseClasspath” to generate a new Eclipse .classpath file with the new dependencies.

      /Jeppe

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: