Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging Entity changes in Java Web Application

We have a requirement on our project, where we need to maintain a sort of history of changes that are made to certain Entities in the Application. The the Application is a Java Web App based on Struts, Spring and Hibernate. What sort of approaches have been used in this case ?

  • Triggers on the respective tables is one idea but they are not easily maintainable ? and perhaps also they should not be part of transactions (its ok if the triggers fail, but the entity update transactions should not fail ).
  • Use AoP for this since its a cross-cutting concern, but has to be really granular, as in capturing only the values when the entity changes. (All edits don't have their corresponding different methods... many edits happen in a single java Method).
  • Use Hibernate Event Listeners.

Are there any other approaches for doing this sort of activity ?

like image 413
Arun R Avatar asked Sep 20 '10 05:09

Arun R


2 Answers

JBoss Envers supports audition and versioning - take a look.

like image 176
Bozho Avatar answered Oct 03 '22 14:10

Bozho


Because you said

All edits do not have their corresponding different methods... many edits happen in a single java Method

Even if your method just receive one argument as parameter and you can retrieve its relationships, AOP still can be a nice idea. I strongly advice you to see this nice article

The Hibernate documentation itself says:

Hibernate Interceptor allows the application to inspect and/or manipulate properties of a persistent object before it is saved, updated, deleted or loaded. One possible use for this is to track auditing information.

But it also says

Ensure that you do not store sessionspecific states, since multiple sessions will use this interceptor potentially concurrently

If you use a Spring managed Transaction, you can get the session atached to the current Thread by using sessionFactory.getCurrentSession();

public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
    if(entity instanceof SomeEntity) {
        Session session = sessionFactory.getCurrentSession();

See getCurrentSession() documentation

If not, you should create a local Hibernate interceptor (attached to the opened Session) instead of a global interceptor(attached to the SessionFactory), and then, set up its session

AuditableInterceptor interceptor = new AuditableInterceptor()
Session session = sessionFactory.openSession(interceptor);

/**
  * do it before processing anything if you use local interceptor
  */ 
interceptor.setSession(session);

About Triggers, it depends on other issues like DB administration (you have DB administration access. If not, Talk to DBA is your best bet).

like image 24
Arthur Ronald Avatar answered Oct 03 '22 14:10

Arthur Ronald