Friday, December 7, 2007

Spring MVC, Data Binding and JPA

A project that I am working on is using Spring MVC. Naturally, we would like to use its data binding facilities to handle data coming in from HttpRequests into our beans. As mentioned by Matt Fleming in this blog post, the Spring docs don't do a great job of explaining how to deal with data binding when the bean in question has a collection as a property. Something like this:

public class Person
private String name;
private List<Address> addresses;

As Matt mentions, using LazyList found in the Apache Commons Collections is one way to get Spring to bind dynamic collections into your beans (in the example, use a lazy list for the addresses). However, you can run into some issues if your persisting your beans using JPA.

We're using OpenJPA, and when we try to persist an object that has a LazyList in one of its properties, it chokes. The problem is that it can't proxy LazyList because it doesn't have a default constructor. To get around this, we're applying a pretty simple hack. Before Spring does the data binding, we decorate the collection with a LazyList. Before we persist the object with JPA, we copy the collection back to a plain old ArrayList.

An example of doing this can be seen with Spring MVC's SimpleFormController in DocumentLocationCreationController. To help out with the whole process, we've created a LazyListHelper to make the decorating and copying easier.

If you're using Spring MVC with JPA, hopefully this will save you some headaches.

Thursday, October 4, 2007

JRuby Compiler Performance

I was pretty excited when I heard that JRuby's compiler was complete. I figured I could run some benchmarks against the C-Based Ruby Implementation to see how it was performing. I've only run this suite once, but I hope to provide enough info so that you could replicate the results yourself. Please let me know if you think I missed something.

The Setup

The benchmarks were run on a Dell D820 laptop. It has an Intel Core Duo running at 2.17GHz and has 1GB of RAM. I'm running Ubuntu 7.04 for an OS. The only wrinkle in my setup is that my root partition is encrypted using LUKS/dmcrypt. This will probably slow down the IO benchmarks, but I'm assuming it would penalize both Ruby implementations equally.

For the C-Based Ruby Implementation, I'm using the Ubuntu packaged Ruby version 1.8.5. For JRuby, I checked out the latest from Codehaus's SVN (Rev 4474) and built the code using Sun's Java version 1.6.0.

For the benchmarks, I pulled the suite from the Ruby Lang SVN (Rev 13608). 

I ran the benchmarks using the run.rb script. The C-Based Ruby Implementation was run with no command line options. I modified the script to run JRuby withe the following options:

  • -C to compile the ruby code before running it
  • -O to disable ObjectSpace
  • -J-Djruby.thread.pooling=true to enable thread pooling
  • -J-server to put the JVM in server mode

These options are explained in the Performance Tuning and Compiler pages of the JRuby Wiki.

The Results

The following shows the time it took the Ruby Implementation to perform the benchmark in seconds:

Here is the difference between the two implementations (CRuby - JRuby) again, in seconds:

As you can see, JRuby is performing really well on a lot of these benchmarks. It gets killed on eval, but I suppose that is to be expected. My guess is that JRuby is taking advantage of Java primitives to outperform CRuby at number crunching. Charles Nutter's comments at another blog entry on JRuby benchmarking seem to indicate that this would be the case. Can't wait until JRuby is 1.1