Roll-Your-Own IoC with Hibernate

It can be pretty useful to supply dependencies to domain objects that you’re loading via Hibernate This is where Hibernate Interceptors come into play.

The Interceptor interface can be used to create classes that get informed when Hibernate is doing anything. Here’s a way you can use an Interceptor to do IoC work:

/** @see Interceptor#onLoad(Object, Serializable, Object[], String[], Type[]) */
public boolean onLoad(Object entity, Serializable id, Object[] state,
    String[] propertyNames, Type[] types) throws CallbackException {

  if (entity instanceof FactoryAware) {
    FactoryAware factoryAwareEntity = (FactoryAware) entity;
    factoryAwareEntity.injectFactory(createFactory());
  }
}

(Another choice for the method to override would be the instantiate method; however, you would need to instantiate the object yourself; this would be good for Constructor Injection, however)

You can also use onLoad for other neat tricks, such as expanding on saved data. Case in point: the application I’m currently working on stores user IDs. These user IDs are backed by data from our HR system, and in fact I treat them as Employee instances. The class is mapped as a component via Hibernate, with just the user ID persisted; the interceptor handles the task of populating Employee instances during the onLoad call.

A minor gripe is that Hibernate doesn’t have a default implementation of the Interceptor available. If you write a few of them, this could get annoying. So “here’s one I prepared earlier”:

/**
* Default implementation of Interceptor
* @author Robert Watkins
*/
public abstract class NullInterceptor implements Interceptor {
  /** @see Interceptor#onLoad */
  public boolean onLoad(Object entity, Serializable id, Object[] state,
      String[] propertyNames, Type[] types) throws CallbackException {
    return false;
  }
  /** @see Interceptor#onFlushDirty */
  public boolean onFlushDirty(Object entity, Serializable id,
      Object[] currentState, Object[] previousState, String[] propertyNames,
      Type[] types) throws CallbackException {
    return false;
  }
  /** @see Interceptor#onSave */
  public boolean onSave(Object entity, Serializable id, Object[] state,
      String[] propertyNames, Type[] types) throws CallbackException {
    return false;
  }
  /** @see Interceptor#onDelete */
  public void onDelete(Object entity, Serializable id, Object[] state,
      String[] propertyNames, Type[] types) throws CallbackException {
    return;
  }
  /** @see Interceptor#preFlush */
  public void preFlush(Iterator entities) throws CallbackException {
    return;
  }
  /** @see Interceptor#postFlush(Iterator) */
  public void postFlush(Iterator entities) throws CallbackException {
    return;
  }
  /** @see Interceptor#isUnsaved(Object) */
  public Boolean isUnsaved(Object entity) {
    return null;
  }
  /** @see Interceptor#findDirty */
  public int[] findDirty(Object entity, Serializable id,
      Object[] currentState, Object[] previousState, String[] propertyNames,
      Type[] types) {
    return null;
  }
  /** @see Interceptor#instantiate(Class, Serializable) */
  public Object instantiate(Class clazz, Serializable id)
      throws CallbackException {
      return null;
  }
}

This simply provides the recommend “don’t do anything” implementation as per the Interceptor’s Javadoc. As such, it is a safe implementation that other interceptors can subclass to get default behaviour for the methods that they don’t care about.

Advertisements

Author: Robert Watkins

My name is Robert Watkins. I am a software developer and have been for over 18 years now. I currently work for people, but my opinions here are in no way endorsed by them (which is cool; their opinions aren’t endorsed by me either). My main professional interests are in Java development, using Agile methods, with a historical focus on building web based applications. I’m also a Mac-fan and love my iPhone, which I’m currently learning how to code for. I live and work in Brisbane, Australia, but I grew up in the Northern Territory, and still find Brisbane too cold (after 16 years here). I’m married, with two children and one cat. My politics are socialist in tendency, my religious affiliation is atheist (aka “none of the above”), my attitude is condescending and my moral standing is lying down.

2 thoughts on “Roll-Your-Own IoC with Hibernate”

  1. Is there any way that you could provide the Interceptor code that populates the Employee instances in the onLoad method? I’m basically facing the exact same issue.

    Thanks!

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