Spring

A Custom reuseable LoadableDetachableModel for Spring/Hibernate

the annoyance


org.hibernate.LazyInitializationException - could not initialize proxy - the owning Session was closed
org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed

the problem

Generally, detached objects in Hibernate are a bad thing when it comes to reusing objects between web-requests. Detached objects are objects that have been persistent but are not attached to a Hibernate session. They’re easily produced but can be a mess if it comes to Lazy-Loading or updating them. Just consider the following case


Foo foo = _myDAO.getFoo(); // attached object

add(new Link("fooLink", new Model(foo)) {

  protected void onClick() {
    Foo foo = (Foo) getModelObject(); // now it's detached as this is called in the next request
    Bar bar = foo.getBar(); // possible lazy-loading exception if bar gets loaded lazily

  }
}

the solution

First be sure to use the OpenSessionInViewFilter sothat a new hibernate session is opened when the request gets attached and closed when it gets detached.

Then the solution of course is a to use a LoadableDetachableModel that gets a fresh instance from the persistence-layer on each request. Could look like that:


IModel fooModel = new LoadableDetachableModel() {

  protected Object load() {
    return _myDAO.getFoo();
  }
}

add(new Link("fooLink", fooModel) {

  protected void onClick() {
    Foo foo = (Foo) getModelObject(); // attached as LDM has loaded a fresh instance
    Bar bar = foo.getBar(); // no lazy loading exception as still attached

  }
}

the improvement

LoadableDetachableModels are a nice thing but it’s quite a lot of work to inject your DAO (or service) and then create a new LDM for each of your objects in each and every one of your panels. so we came up with a more generic version of the LoadableDetachableModel. First, let your model-objects implement an Interface, say IPersistentObject with the single method


  Serializable getId();

As your object are likely to have a primary key named id it’ll be no problem anyway. Then create the following class:


public class PersistentObjectModel extends LoadableDetachableModel {

  private static final long serialVersionUID = 1L;

  private final Class _clazz;

  private final Serializable _id;

  @SpringBean(name = "myDao")
  private IMyDao _myDao;

  @SuppressWarnings("unchecked")
  public PersistentObjectModel(final T object) {
    super(object);

// object may be a hibernate proxy, so get the actual class
    if (object instanceof HibernateProxy) {
      _clazz = (Class) ((HibernateProxy) object).getHibernateLazyInitializer()
.getImplementation().getClass();
    } else {
      _clazz = (Class) object.getClass();
    }
    _id = object.getId();
    // inject the bean
    InjectorHolder.getInjector().inject(this);
  }

  public PersistentObjectModel(final Class clazz, final Serializable id) {
    clazz = clazz;
    _id = id;
    // inject the bean
    InjectorHolder.getInjector().inject(this);
  }

  @Override
  protected T load() {
    // the DAO then simply passes the params to hibernate (or spring's hibernatetemplate
    return _myDao.getById(_clazz, _id);
  }

  @SuppressWarnings("unchecked")
  @Override
  public T getObject() {
    return (T) super.getObject();
  }

}

This makes working with hibernate objects really easy. There are two options:

  1. Use the object e.g.

    setModel(new PersistentObjectModel(foo));

  2. Use only class and id.

    This might happen e.g. if you pass your id using PageParameters (but better encrypt it ;-) )
    setModel(new PersistentObjectModel(Foo.class, 1));

Hope that saved you some time writing boilerplate code ;-) have fun


Capacity planning

Today, I discovered a nice little gotcha in the Spring source, namely in org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor, while I was implementing a priority task queue. The mentioned class uses a template method to create the backing queue for pending tasks:

protected BlockingQueue createQueue(int queueCapacity) {...}

I’ve overridden this method like so:

protected BlockingQueue createQueue(int queueCapacity) {
return new PriorityBlockingQueue(queueCapacity, new Comparator() {...});
}

However, this didn’t work as I got:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

Why? By default, the ThreadPoolTaskExecutor uses

new LinkedBlockingQueue(queueCapacity);

With a default queueCapacity of Integer.MAX_VALUE … This is ok, as the capacity of a LinkedBlockingQueue is its maximum capacity while the capacity of the PriorityBlockingQueue is its initial capacity (and used to create a array of the given size). Unfortunately, it isnt’t even possible to limit the size of PriorityBlockingQueue at all. Therefore, the parameter should be ignored for PriorityBlockingQueues.


Tapestry/Spring Integration

In the last weeks I started to have a look at different web frameworks and came across Tapestry5. Having watched the screencasts on the website, I began to like it straight away. Although still in development (the release is planned in fall 2007), it offers some nice features. The most impressive one is that you do not have to restart the servlet-container to apply changes in java files. But for me personally, the features I appreciate the most are that you don’t have to bother with jsp-specific stuff (such as <% useBean="..." %> – Ugh!) and it lets you get rid of the servlet mapping stuff in the web.xml. That’s nice isn’t it? I also read some posts claiming that Apache Wicket already provides such features. I started reading the Wicket docs, but stopped when I saw that there’s a need to inherit from a Wicket base-class and to define servlet-mappings in the web.xml – as stated above, I don’t like too many manual servlet-mappings and I also prefer dealing with POJOs.

After playing around with Tapestry by implementing the screencasts and the tutorial, I tried to inject Spring2 managed-beans into a Tapestry5 app. I found a load of examples/tutorials online, but they either dealt with tapestry4 and/or spring1.2.x. There also is a tutorial on the Tapestry site from its creator Howard Lewis Ship. Unfortunately, he missed pointing out that it is vital to add another dependency, the tapestry-spring library. Worth mentioning is, that the tapestry-spring dependency differs from the tapestry-spring.jar available on the project page which I used at first. It took me quite a while to find out what’s wrong until I found a hint in the tapestry-mailing-list. A user there suggested to add the tapestry-spring dependency to your maven2 pom.xml. After including the library, a simple @Inject was enough to inject a spring-bean into the tapestry-class. The dependency should look as follows:

<dependency> <groupid>org.apache.tapestry</groupid> <artifactid>tapestry-spring</artifactid> <version>${tapestry-release-version}</version></dependency>

The hacks I did with Tapestry5 made me to get in touch with Maven2 for the first time. Together with the eclipse-plugin, it was very easy to add dependencies to the project and to build and pack the application. That’s of course only the tip of the iceberg, and I’ll definitely have to get a bit more into maven – as it really looks like it offers some nice features. And also I have to prove if Jelmer Kupurus’s statement is right or not :-)

Enough for now, I’d love to receive some comments with your experience with Tapestry5 and Spring integration!