Spring Data: Data Auditing Using JaVers and MongoDB
Join the DZone community and get the full member experience.Join For Free
Recently I was looking for some simple options to track all changes to entities in all my microservices. After researching, I discovered the Java library named JaVers. It is designed as a framework for auditing changes in object-oriented data.
In this post, we’ll see how to use JaVers in a simple Spring Boot application and MongoDB environment to track changes of entities.
- Spring Boot 2.
- Maven 3.6.1.
- JAVA 8.
- Mongo 4.4.
What is JaVers
JaVers is an audit log framework that helps to track changes of entities in the application.
The usage of this tool is not limited to debugging and auditing only. It can be successfully applied to perform analysis, force security policies and maintaining the event log, too.
Why use JaVers
- It is open source and free to use.
- JaVers is written in Java 8 and can be run on JRE 8 or higher.
- It is compatible with both traditional relational relational database systems as well as NoSQL systems. This makes migration between RDBMS and NoSQL much smoother.
- Easy integration with Spring and Spring Boot.
Setup Spring Boot Project
To integrate JaVers in your application you just need to include the JaVers dependency in you project’s build.gradle or pom.xml file.
JaVers starters rely on Spring Data starters. it offers an option to use a dedicated Mongo database for JaVers data.
javers.mongodb property is defined, either
uri has to set. If so, an application’s data and JaVers data are stored in different databases.
JaVers is based on annotations:
@JaversSpringDataAuditable annotation is used to audit JPA repositories.
By adding this annotation, you create an audit entry for each create, update or delete operation you perform in the database.
In case of a custom repository or If you aren't using Spring Data repositories, annotate all data-changing methods with
Trying it Out
Now let's try to change the data. for this, we use the Postman tool to run the endpoints.
we notice that JaVers added two new collections in our MongoDB database after saving the employee document.
jv_head_id— one document with the last CommitId,
jv_snapshots— domain object snapshots. Each document contains snapshot data and commit metadata.
In the jv_snapshots collection, there are three types of documents for auditing a document.
- INITIAL: Create operation in the database.
- UPDATE: Update operation.
- TERMINATE: Delete operation has been performed.
When creating the employee document, we can see in jv_snapshots:
- commitMetadata: This includes valuable information such as the author of the change, the time of the event in local (commitDate) and UTC (commitDateInstant).
- globalId: Contains information about the entity being modified and its database id.
- state: Contains all the field values of the entity being modified. Please note that this is the state of the object after the change has been performed.
- changedProperties: This includes the fields that have been modified in this audit log entry. Since this is a creation operation, all fields have been included in the changed properties array.
Let's start the update operation:
Notice that a new document has been created with type UPDATE and the version has been incremented to 2.
Finally, let's run the delete operation:
Since the object has been deleted, the entry log type here is TERMINATE. Notice that the changed properties array is empty.
Each committed change in JaVers should have its author. i.e. the user who made the change. Moreover, JaVers supports Spring Security out of the box. You need to register an implementation of the
AuthorProvider interface, which should return a current user name.
In this article, I created a simple custom implementation of the AuthorProvider interface.
Retrieving Audit Information From JaVers Snapshots Repository
JaVers provides its own JaVers Query Language (JQL). It is a simple, fluent API which allows you to query JaversRepository for changes of a given class, object or property.
Data history can be fetched from JaversRepository using
javers.find*() methods in one of three views: Shadows, Changes, and Snapshots.
- Shadow is a historical version of a domain object restored from a snapshot.
- Change represents an atomic difference between two objects.
- Snapshot is a historical state of a domain object captured as the
Let's take a look at some examples:
When I want to retrieve all the changes made to the Employee collection.
curl --location --request GET 'http://localhost:8080/audit/employees'
Properties are matched by name, and their values are compared, without paying much attention to the actual Employee class.
JaVers can have different applications, from debugging to complex analysis. The official documentation presents several examples of use.
The complete source code can be found in my GitHub repository.
Opinions expressed by DZone contributors are their own.