Enable auditing with Spring Data MongoDB. For example with Spring Data JPA, visit Spring Data JPA Audit Example.
Background
Spring Data MongoDB provides auditing support for MongoDB. Auditing is a common requirement for most applications. It is used to track changes to entities, such as who created or modified an entity and when the change occurred.
In this example, we will create a simple Spring Boot application that uses Spring Data MongoDB to persist and retrieve data from MongoDB. We will also enable auditing to track changes to entities.
Document Class
We will have a Document
called User:
@Document
class User {
@Id
private ObjectId id;
private String name;
private String username;
@CreatedBy
private String createdBy;
@CreatedDate
private Instant created;
@LastModifiedBy
private String modifiedBy;
@LastModifiedDate
private Instant modified;
// getters and setters
}
Fields that are marked with @CreatedBy
, @CreatedDate
, @LastModifiedBy
and @LastModifiedDate
are meant for auditing and will be populated by Spring Data MongoDB.
Enable Mongo Audit
To enable auditing, we need to add @EnableMongoAuditing
annotation to our @Configuration
class - MongoAuditConfiguration:
@Configuration
@EnableMongoAuditing
class MongoAuditConfiguration {
@Bean
public AuditorAware<String> auditorAwareRef() {
return () -> Optional.of("Mr. Auditor");
}
}
Verify Audit Implementation
We will verify that the auditing is working by creating a test case that will create a new User
and verify that the created
, createdBy
, modified
, and modifiedBy
fields are populated.
@Testcontainers
@DataMongoTest(includeFilters = @Filter(type = ANNOTATION, classes = EnableMongoAuditing.class))
class UserAuditTests {
@Container
@ServiceConnection
private final static MongoDBContainer mongo = new MongoDBContainer("mongo:latest");
@Autowired
private UserRepository repository;
@Test
@DisplayName("When a user is saved Then created and modified fields are set And createdBy and modifiedBy fields are set to Mr. Auditor")
void create() {
var createdUser = repository.save(new User().name("Rashidi Zin").username("rashidi"));
assertThat(createdUser).extracting("created", "modified").isNotNull();
assertThat(createdUser).extracting("createdBy", "modifiedBy").containsOnly("Mr. Auditor");
}
}
Next we will verify that the modified
field are updated when we update the User
:
@Testcontainers
@DataMongoTest(includeFilters = @Filter(type = ANNOTATION, classes = EnableMongoAuditing.class))
class UserAuditTests {
@Container
@ServiceConnection
private final static MongoDBContainer mongo = new MongoDBContainer("mongo:latest");
@Autowired
private UserRepository repository;
@Test
@DisplayName("When a user is updated Then modified field should be updated")
void update() {
var createdUser = repository.save(new User().name("Rashidi Zin").username("rashidi"));
await().atMost(ofSeconds(1)).untilAsserted(() -> {
var persistedUser = repository.findById(createdUser.id()).orElseThrow();
var modifiedUser = repository.save(persistedUser.username("rashidi.zin"));
assertThat(modifiedUser.modified()).isAfter(createdUser.modified());
});
}
}
Full implementation can be found in UserAuditTests.