DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Manage Hierarchical Data in MongoDB With Spring
  • MongoDB With Spring Boot: A Simple CRUD
  • CRUD Operations on Deeply Nested Comments: Scalable Spring Boot and Spring Data approach
  • JobRunr and Spring Data

Trending

  • 5 Subtle Indicators Your Development Environment Is Under Siege
  • A Developer's Guide to Mastering Agentic AI: From Theory to Practice
  • How to Convert XLS to XLSX in Java
  • Measuring the Impact of AI on Software Engineering Productivity
  1. DZone
  2. Data Engineering
  3. Databases
  4. Spring Data: Data Auditing Using JaVers and MongoDB

Spring Data: Data Auditing Using JaVers and MongoDB

By 
Anicet Eric user avatar
Anicet Eric
·
Nov. 16, 20 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
22.1K Views

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.

Prerequistes

  • 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. 

XML
xxxxxxxxxx
1
 
1
<dependency>
2
    <groupId>org.javers</groupId>
3
    <artifactId>javers-spring-boot-starter-mongo</artifactId>
4
    <version>5.13.2</version>
5
</dependency>


Shell
xxxxxxxxxx
1
 
1
compile 'org.javers:javers-spring-boot-starter-mongo:5.13.2'

JaversRepository Configuration

JaVers starters rely on Spring Data starters.  it offers an option to use a dedicated Mongo database for JaVers data.

YAML
xxxxxxxxxx
1
 
1
javers:
2
  mongodb:
3
    host: localhost
4
    port: 27017
5
    authentication-database: admin
6
    database: <<databasemane>>
7
    username: <<dbuser>>
8
    password: <<dbpassword>>


Or

YAML
xxxxxxxxxx
1
 
1
javers:
2
  mongodb:
3
    uri: mongodb://<<dbuser>>:<<dbpassword>>@localhost:27017/<<databasemane>>&authSource=admin


If javers.mongodb property is defined, either host or uri has to set. If so, an application’s data and JaVers data are stored in different databases. 

Audit Annotations

JaVers is based on annotations: @JaversSpringDataAuditable and @JaversAuditable. 

@JaversSpringDataAuditable annotation is used to audit JPA repositories.

Java
xxxxxxxxxx
1
 
1
@JaversSpringDataAuditable
2
    public interface EmployeeRepository extends MongoRepository<Employee, String> {
3
}


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 @JaversAuditable.

Java
xxxxxxxxxx
1
13
 
1
@JaversAuditable
2
public User save(User user) {
3
    ...//
4
}
5
@JaversAuditable
6
public User update(User user) {
7
    ...//
8
}
9
10
@JaversAuditable
11
public void delete(User user) {
12
    ...//
13
}

Trying it Out

Now let's try to change the data. for this, we use the Postman tool to run the endpoints.

testing API in Postman

we notice that JaVers added two new collections in our MongoDB database after saving the employee document.

Application file structure

  • 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:

creating employee document

  • 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:

updating the 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:

deleting the operation

Since the object has been deleted, the entry log type here is TERMINATE. Notice that the changed properties array is empty.

Author Provider

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. 

Java
xxxxxxxxxx
1
17
 
1
@Configuration
2
public class JaversConfiguration {
3
4
    private static final String AUTHOR = "aek author";
5
6
    @Bean
7
    public AuthorProvider provideJaversAuthor() {
8
        return new SimpleAuthorProvider();
9
    }
10
11
    private static class SimpleAuthorProvider implements AuthorProvider {
12
        @Override
13
        public String provide() {
14
            return AUTHOR;
15
        }
16
    }
17
}


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 property:value map.

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'

Shell
xxxxxxxxxx
1
28
 
1
<pre>Changes:
2
        Commit 5.00 done by aek author at 14 nov 2020, 14:30:11 :
3
        * changes on com.java.audit.springdatamongojavers.domain.Employee/5fafdbb15be81677928fbbb7 :
4
        - 'email' value changed from 'johndoe.emal.com' to 'john.email.com'
5
        - 'firstName' value changed from 'John' to 'Doe'
6
        - 'lastName' value changed from 'Doe' to 'John'
7
        Commit 4.00 done by aek author at 14 nov 2020, 14:29:21 :
8
        * new object: com.java.audit.springdatamongojavers.domain.Employee/5fafdbb15be81677928fbbb7
9
        * changes on com.java.audit.springdatamongojavers.domain.Employee/5fafdbb15be81677928fbbb7 :
10
        - 'email' value changed from '' to 'johndoe.emal.com'
11
        - 'firstName' value changed from '' to 'John'
12
        - 'id' value changed from '' to '5fafdbb15be81677928fbbb7'
13
        - 'lastName' value changed from '' to 'Doe'
14
        Commit 3.00 done by aek author at 14 nov 2020, 13:48:51 :
15
        * object removed: com.java.audit.springdatamongojavers.domain.Employee/5fafbbc7c3f606329bd51e7c
16
        Commit 2.00 done by aek author at 14 nov 2020, 13:37:02 :
17
        * changes on com.java.audit.springdatamongojavers.domain.Employee/5fafbbc7c3f606329bd51e7c :
18
        - 'email' value changed from 'johndoe.emal.com' to 'john.email.com'
19
        - 'firstName' value changed from 'John' to 'Doe'
20
        - 'lastName' value changed from 'Doe' to 'John'
21
        Commit 1.00 done by aek author at 14 nov 2020, 12:13:11 :
22
        * new object: com.java.audit.springdatamongojavers.domain.Employee/5fafbbc7c3f606329bd51e7c
23
        * changes on com.java.audit.springdatamongojavers.domain.Employee/5fafbbc7c3f606329bd51e7c :
24
        - 'email' value changed from '' to 'johndoe.emal.com'
25
        - 'firstName' value changed from '' to 'John'
26
        - 'id' value changed from '' to '5fafbbc7c3f606329bd51e7c'
27
        - 'lastName' value changed from '' to 'Doe'
28
</pre>


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.

Spring Framework Data (computing) Spring Data Relational database Database MongoDB Spring Boot application Spring Security Document

Opinions expressed by DZone contributors are their own.

Related

  • Manage Hierarchical Data in MongoDB With Spring
  • MongoDB With Spring Boot: A Simple CRUD
  • CRUD Operations on Deeply Nested Comments: Scalable Spring Boot and Spring Data approach
  • JobRunr and Spring Data

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!