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.