openxava
/ documentation /
Auditing changes using Hibernate Envers
Since v5.9 you can also use the new
AccessTracker of OpenXava
Auditing
Basics
Auditing can add a very powerful component to your OpenXava project using
the
@Audited mechanism. For many legal, regulatory and
corporate-requirement reasons, your application will need to log any
changes to the database, beyond whatever logging/auditing capability may
be in your database itself.
Since
v5.4 OpenXava has added "Hibernate Envers" API by default.
For versions
5.3.* the API must be included in the classpath.
The
v5.3 had a bug that is resolved in this
discussion.
This article is a basic intro to using this capability in OpenXava 5.3 or
higher.
Configuration
Essentially, OpenXava uses the existing Hibernate envers mechanism to
perform auditing. As of OpenXava 5.3 or higher , there are a minimum of
steps to configure and use auditing. First, though, a couple of notes:
1 - You can specify to audit individual fields within a class or an entire
class itself. Just place the
@Audited tag immediately
before the item to be audited.
2 - Be
VERY aware, though, that any other object which
references the audited field must also be audited. This includes
super-classes, such as those "extends"ed.
First, perform the step below:
Add the fields below to the
persistence.xml of your
project:
<properties>
...
<property name="hibernate.hbm2ddl.auto" value="update"/>
...
<property name="org.hibernate.envers.audit_strategy"
value="org.hibernate.envers.strategy.ValidityAuditStrategy"/>
<property name="org.hibernate.envers.audit_strategy_validity_store_revend_timestamp"
value="true"/>
...
</properties>
It is possible to configure various aspects of Hibernate Envers behavior,
You can check the
documentation about this.
The next step is to add
@Audited to, again, either an
individual field or entire class, such as:
public class Invoice {
@Audited Audits invNumber field
private int invNumber;
or
@Audited Audits invoice class
public class Invoice {
private int invNumber;
Usage
Presuming that you are using Eclipse, you'll immediately notice that the
@Audited
tag is flagged red-X. That's because the missing Hibernate envers package
has not been imported. Highlight
@Audited and select to
include (or do it manually/via whatever other tool you may be using) the
package:
import org.hibernate.envers.*;
Create and test your package! After the first creation/modification event,
you should be able to launch your DB admin tool and check the columns of
your DB. For each table/entity, there should be a corresponding
xxx_aud
table and a table called
revinfo This table logs
revision info for the changes.
Until
v5.2.1
Add in
persistence.xml:
<properties>
...
<property name="hibernate.ejb.event.post-insert"
value="org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.post-update"
value="org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.post-delete"
value="org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.pre-collection-update"
value="org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.pre-collection-remove"
value="org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.post-collection-recreate"
value="org.hibernate.envers.event.AuditEventListener" />
...
</properties>
In
build.xml of OpenXava project modify the hibernatetool
classname adding Envers, as following:
<taskdef name="hibernatetool"
classname="org.hibernate.tool.ant.EnversHibernateToolTask"
classpathref="jpatoolslib"/>
Create the
RevEntity class to indicate that the revision will
contain user name.
package org.openxava.yourproject.auditing;
import javax.persistence.*;
import org.hibernate.envers.RevisionEntity;
import org.hibernate.envers.DefaultRevisionEntity;
@Entity
@RevisionEntity(ListenerUsuario.class)
public class RevEntity extends DefaultRevisionEntity{
private String username;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
}
Create the
UserListener to capture the user that is modifying.
package org.openxava.yourproject.auditing;
import org.hibernate.envers.*;
import org.openxava.util.*;
public class UserListener implements RevisionListener{
public void newRevision(Object revisionEntity) {
RevEntity reventity = (RevEntity) revisionEntity;
reventity.setUsername(getCurrentUser());
}
public static String getCurrentUser() {
if (Users.getCurrent() != null) {
return Users.getCurrentUserInfo().getGivenName() + " " +
Users.getCurrentUserInfo().getFamilyName();
} else {
return "";
}
}
}
Finally add to the class you want to audit:
@Audited
Generate the database and deploy the application.