Using Hibernate Interceptors for ChangeEvents

After doing some research for a new Change Event system for our Enterprise application at work I came across the Hibernate Interceptors interface. This interface allows you to register callbacks when persistent objects are saved, updated, deleted, or loaded within a Session.

The main idea I had was to use this Interceptor interface to monitor any changes which have occured within a particular Session. This information can than be used to delegate data change events to the interested parties.

Let me back up a little bit and give an overview of the application I am working with. Within our system we have a core 'Aenemic Domain Model' (save why we ended up with an anti-pattern for another discussion). The domain model we are currently working with has a very complex mapping of relationships representing multiple states of a particular scenario. This model is directly mapped to Hibernate using XML configuration files which are generated along side the model. The application must react to changes in the model inflicted by both the current user and any users collaborating within the particular scenario.

In order to opperate as desired there are two primary components which must react to changes within the core domain model. The first component are the 'Agents' whose responsiblity is to analyze the current scenario and give notifications, warnings, and errors. The second component, a Flash based UI, can be broken down into three sub categories.

The first component is the 'Agent Framework'. The 'Agent Framework', to summarize briefly, is a collection of 'Agents' which monitor all scenarios active within the system. The agents will observe each scenario and monitor undesirable configurations for each of their concerning domains. This framework uses a decoupled non-persistent model which is tailored to optimize the CPU intensive analysis.

The second component consists of the UI. Our application can be broken down into three main UI categories: Reports, Viewer, and general UI. The Reports is comprised by a large collection of grid displays used to represent detailed information about the current scenario. The Viewer is a CAD-style graphical display which allows the users to plan and interact with the scenario. The general UI includes any custom dialogs which allow the users to view or manipulate the configuration.

In summary we have a primary model and four components, or 'listeners', interested in changes to this model: agents, reports, viewers, and ui. Each of these components are interested in different subsets of data. Up until now these 'listeners' were explicity invoked within each operation. This was a reasonable solution to make it through the first few releases. However as the project grew, ensuring each listener was notified properly for each transaction became a debugging nightmare. Also as the agents' models grew in complexity and the volume of data increased, the time to load and convert the model began to effect the users interaction with the system.

Now back to the original idea. We can create a Hibernate Interceptor which will monitor any changes to the current session. These events can be tracked within a 'ChangeMonitor' to manage any object which has been changed including any affected attributes and both the current/previous state of the attributes. If a transaction is successfully completed and flushed to the database this interceptor can dispatch JMS messages of any data which has changed. The 'listeners' which must react to changes in the model can now recieve detailed information as what has occured within a particular transaction and react accordingly. However with any system this design has its benefits not void of any down sides.

The ChangeMonitor reduces the complexity of the service and business logic layers by leveraging the dirty check functionality already occuring within Hibernate. The developer no longer has to determine which parties are interested in the changes occuring within each transaction. The data collected from the Hibernate Listener also allows us to retain a before/after state to fine tune the reactions and filter uninteresting changes. The ChangeMonitor could also be used for both optimization and auditing to explicitly monitor all data which as been modified for the transaction. This being said there are a few negative issues which also must be considered.

With the introduction of the ChangeMonitor we start to see a common pattern of too much information can become a hassle to manage. In our previous framework we only knew when particular objects were added, updated, or removed. Now each component has the power to explicitly be aware of all objects and all attributes. This will require additional filtering on each of the four components to ensure they only react to data changes within their concerning subset. The other potential downside which will require more research is how changes to collections and different association types, one-to-one, many-to-one, many-to-many, etc., can be determined.

For now I think I have written enough. Time to give it a try and see what we can accomplish!