8. OpenJPA Audit

8.1. Configuration
8.2. Developing custom auditing
Transactional applications often require to audit changes in persistent objects. OpenJPA can enable audit facility for all persistent entities in few simple steps.

8.1. Configuration

Annotate Persistent Entity Any persistence entity can be enabled for audit by annotating with org.apache.openjpa.audit.Auditable.

      @jakarta.persistence.Entity
      @org.apache.openjpa.audit.Auditable
      public class MyDomainObject { ...}
    

This Auditable annotation enables auditing of creation, update or delete of MyDomainObject instances. The Auditable annotation accepts list of enumerated values org.apache.openjpa.audit.AuditableOperation namely CREATE, UPDATE and DELETE to customize only appropriate operations be audited. By deafult, all of the above operations are audited.

Configure Persistence Configuration The audit facility is invoked at runtime via configuration of META-INF/persistence.xml. The following property configures auditing via a default auditor

<property name="openjpa.Auditor" value="default"/>

The default auditor does not do much. It simply prints each auditable instance with its latest and original states on a standard console (or to a designated file).

The latest state of an instance designates the state which is commited to the database. The originalstate designates the state when the instance entered the managed persistent context. For example, when a new instance is persisted or a existing instance is loaded from the database.

8.2. Developing custom auditing

For real use case, an application will prefer more than printing the changed instances. The application, in such case, needs to implement org.apache.openjpa.audit.Auditor interface. This simple interface has the following method:

    /**
	 * OpenJPA runtime will invoke this method with the given parameters
	 * within a transaction.
	 *
	 * @param broker the active persistence context.
	 * @param newObjects the set of auditable objects being created. Can be empty, but never null.
	 * @param updates the set of auditable objects being updated. Can be empty, but never null.
	 * @param deletes the set of auditable objects being deleted. Can be empty, but never null.
	 */
	public void audit(Broker broker, Collection<Audited> newObjects, Collection<Audited> updates,
			Collection<Audited> deletes);
    

OpenJPA runtime will invoke this method before database commit. Via this callback method, the application receives the auditable instances in three separate collections of org.apache.openjpa.audit.Auditable. An Auditable instance provides the latest and original state of a persistent object. The latest object is the same persistent instance to be committed. The original instance is a transient instance holding the original state of the instance when it entered the managed context. The active persistence context is also supplied in this callback method, so that an application may decide to persist the audit log in the same database.

It is important to note that the original object can not be persisted in the same transaction, because it has the same persistent identity of the latest object.

A single instance of implemented org.apache.openjpa.audit.Auditor interface is available for a persistence unit. However, an application's own implementation of this interface need not be thread-safe, because OpenJPA runtime guards against concurrent invocation of the callback method.

The org.apache.openjpa.audit.Auditor interface is configurable. Hence any bean style getter and setter method on its implementation will be populated as usual for any other OpenJPA plugin. In the following example,

    <property name="openjpa.Auditor" value="com.acme.Auditor(param2=10,param2='hello')"/>
    

An instance of com.acme.Auditor will be instantiated and if it has been style getter and setter methods for param1 and param2, then the respective setters will be called with 10 and "hello" before the instance being used.