In above, isNew() is crucial and used to differentiate if a model is new or already saved model. The auditing listeners will use this method to decide if created fields to be updated or not. The above implementation is on assumption that the Ids are generated by DB and hence it will be NULL for models created newly.We also require to define beans which provide auditing principal and current time.

Auditing
principal

The auditing principal can be obtained by implementing the interface
org.springframework.data.domain.AuditorAware. A sample implementation
is as below.

public class MyAuditor implements AuditorAware<String> {
@Override
public String getCurrentAuditor() {
//If you are using spring-security, you may get this from SecurityContext.
return "System";
}
}

Date
Provider

To
get the auditing time, we need an implemenation of interface
org.springframework.data.auditing.DateTimeProvider. Spring provides a
defulat implementation for current time is
org.springframework.data.auditing.CurrentDateTimeProvider

This configuration will create listener bean
org.springframework.data.mongodb.core.mapping.event.AuditingEventListener
which listens for BeforConvertEvent that is fired by
MongoTemplate(MongoOperations) during save operations.

Gaps

If
due to some reason <mongo:auditing>is included multiple times
in your application context, then spring creates multiple instances
of AuditingEventListener i.e., the audit update logic gets executed
multiple times. This happens as the spring NameSpaceHandler creates a different listener bean each time.

MongoTemplate
fires BeforeConvert event only during save and insert operations
i.e., the AuditEventListener and hence the audit fields are updated only if the whole entity is being
saved (either by insert or update). But MongoTemplate provides many
other methods like update*(**) and findAndModify(**) methods which will update the model, but not the audit and version.

Custom
AuditEventListener

The
first gap can be overcome by creating custom AuditEventListener and
registering this bean instead of <mongo:auditing>. A Sample
implementation is defined as below.

Following
is updated bean configuration. Note that we no longer require <mongo:auditing>. As bean id is specified for
MyAuditEventListener, the bean will be registered only once even if the file containing this bean is imported multiple times.

The Aspect works on MongoOperations interface and hence on MongoTemplate.

PointCut expression specifies to work on all update and findAndModify methods.

This is @Before aspect and updates Update object with auditing fields.

The same dateTimeProvider and myAuditor used in MyAuditingEventListener are used in MyMongoAuditAspect also.

The application context should be configured to register this aspect as bean and also configured for AOP using <aop:aspectj-autoproxy/>

Conclusion

I have tried to explain how to achieve auditing while using spring framework for mongodb. I have also explained with code snippets on how AOP can be used to fill some gaps. I have explained AOP for few methods. The same can be extended to work for upsert method and also for update method when upsert flag is true.