Monday, October 13, 2008

Anything goes alternative Olympic Games


I've been toying with the idea of an alternative Olympics where anything goes as long as it is human powered. The rules are simple, (if you're stupid enough) you can use any kind of dope but more interestingly you can use any kind of technology, just as long as it is human powered. I want to see Phelps with one of these things! Maybe he can wear a fin on his back to go with it.

Saturday, October 11, 2008

Hibernate Interceptors, Events and JPA Entity Listeners

Hibernate became is an implementation of the JPA specification. The JPA specification is part of the EJB3 specification (JSR-220). See, SUNs FAQ on that if you want to know more about that.

Hibernate Interceptors
In a recent project I wanted to intercept Create, Update and Delete events. From the Hibernate Reference Documentation it was pretty straightforward to find out how to create an Interceptor class. I extended my AuditInterceptor class from the EmptyInterceptor interface and implemented the onSave, onFlushDirty and onDelete methods but then was a bit puzzled how to activate the interceptor. Chapter 2 talks about specific hibernate configuration properties, but how to use those when you're using a JPA persistence.xml? It turns out the answer is very simple. Pretty much any vendor specific property can be set in the persistence.xml using a properties block. In this case a property with name hibernate.ejb.interceptor needs to be set to the full name of my AuditInterceptor class.

Some advantages are that
  • you don't to change any of your existing code, just add your interceptor and update the persistence.xml
  • the onFlushDirty gives you a nice detailed information on what changed
but on the flipside
  • the interceptor fires for every entity bean, and chances are you're only interested in a subset. I ended up doing the filtering in my AudutInterceptor.
  • if your primary key is set by the database, the id is still undefined when onSave fires.
Hibernate Events
The capabilities of Hibernate Events API goes beyond those of the Interceptors. It gives you very fine-grained control over where to hook into the event stream. Check out the org.hibernate.event package for all the different interfaces you can implement.

Some advantages
  • fine-grained control over where to hook into the persistence process (lots of Pre- and Post-event interfaces)
  • The event objects are contain a wealth of information, including previous and current state of the entity.
but on the flipside
  • hooking up your EventListener is either done programmatically or using the Hibernate session-factory configuration block. I guess I could use a hibernate.cfg.xml file and reference that in my persistence.xml, but it started to feel convoluted to me.
JPA EntityListeners
FInally there are non vendor specific JPA EntityListeners. To use an EntityListener you simply add a '@EntityListener (class=)' annotation. Then in your listener class you can use other annotations (like @PrePersist, @PreRemove, @PostPersist, @PostRemove, @PreUpdate, @PostUpdate and @PostLoad) to decorate your listener methods.

Some advantages are
  • fine-grained control as to which entities you want to listen to (annotation on the entity, referencing your listener class)
  • pretty good control on where you want to hook in your listener (annotation on a method on the listeners class)
but on flipside
  • the API only gives you the current state of the entity, and does not provide information as to what changed in case of an update.
Conclusion
In my case I ended up with a hybrid solution using a HibernateInterceptor for the Update and Delete, and using EntityListeners for the Create event, listening to the PostInsert events so that the id field on my entities are defined.