Aspect Oriented Audit Logging with Spring and Hibernate
July 3, 2006 5 Comments
Audit logging is one of the important concerns in huge applications and usually treated as some kind of a non-functional requirement. I mean a software may work with or without an audit logging infrastructure, the thing is when it plays an important role in a software, design problems may likely to occur because it does not seem to be easy to change the design of the software to enable audit logging at first glance.
In our project, there is a layered architecture where spring is located at business/service layer and hibernate at DAO layer. At first this architecture was not designed considering stuff like audit logging or security. But the good news is that, since these are cross-cutting concerns, they can be easily integrated in an Aspect Oriented Way. Audit Logging could also be solved for simple systems using database triggers in an old school fashion but I can’t imagine how hard it could be to create and maintain it. Master Kenan created a high level base infrastructure to enable audit logging and I’ve worked on it for some time to make it ready for integration to our project modules. The ingridients are the following;
* IAuditable: Marker interface which domain object must implement.
* AuditLogger: Spring bean to do the audit logging job.
* ServiceAuditLogInterceptor: Spring’s MethodInterceptor that intercepts the calls to service beans.
* EntityAuditLogInterceptor: Hibernate’s interceptor to intercept the transactions.
* Commons attributes: Attributes to define the audit log types for service methods. JAVA5 annotations should do the job too.
* AuditLogRecord: A persistent object to hold the audit logs. It has types like service_level_save, service_level_update, entity_level_save and etc.
An audit logging story is enabled using the commons attributes defined for the interfaces which are implemented by spring beans;
This is how it works;
1) ServiceAuditLogInterceptor intercepts the method call and checks for the audit log commons attributes, if it finds any, creates a service level audit log record to the AuditLogger bean.
2) When the call reaches the below layers which are hibernate dao objects, EntityAuditLogInterceptor takes the scene. By overriding methods like onSave, onFlushDirty, it adds entity level audit logs to the service level audit log record hold in the audit logger for this transaction.
3) When the flush method of EntityInterceptor is called, audit logger flushes itself by calling hibernate templates save method to insert the audit log records it holds.
Since audit logger makes a db call using hibernate, it needs to use a seperate session factory configured in application context. If not, it will start intercepting it’s own calls and cause infinite loop. Also you need to configure the interceptors in Spring. ServiceAuditLogInterceptor can be configured to intercept the calls to the beans ending with *Service implicitly by adding it to the interceptor names property of your auto proxy creator. The other one, EntityAuditLogInterceptor is integrated by configuring the entityInterceptor property of a session factory bean.
One of the best sides of this architecture is, it is so easy to add new audit log types, like user logins, db functions, changing passwords and more you can think of. I’ve also build pages with JSF to search the audit log records in the system criterias like date, user, log types and etc. Using it we can figure out the finger prints of each user from the system tracking module. Anyway, if you want to learn more, Kenan Sevindik will post an entry at his blog and present the whole thing with codes of these ingridients to describe the audit logging infrastructure in detail.