I had similar issue recently, and I did a bit of digging around to see how auditing actually works, so I am just putting it here in case any one else runs into the same problem.
First of all, here are relevant spring docs regarding auditing with regards to mongo:
So auditing works via EntityCallbacks
(defined in the spring-data-commons
project) and the specific callback(s) that we need to run for mongo is either the AuditingEntityCallback
or the ReactiveAuditingEntityCallback
both defined in the spring-data-mongodb
project.
Please note that all that these EntityCallback
(s) does is to give either the AuditingHandler
or ReactiveAuditingHandler
in the spring-data-commons
project a change to do their work, both of these classes extends the AuditingHandlerSupport
abstract class and I would recommend putting a break point on the isAuditable
method:
/**
* Returns whether the given source is considered to be auditable in the first place.
*
* @param source must not be {@literal null}.
* @return {@literal true} if the given {@literal source} considered to be auditable.
*/
protected final boolean isAuditable(Object source) {
Assert.notNull(source, "Source entity must not be null");
return factory.getBeanWrapperFor(source).isPresent();
}
Please note that the method above uses the property factory
which is of type
AuditingHandlerSupport
to get bean wrapper, and ultimatly decide if the object can be audited or not, so you are definitly going to want to step into that if you are running a debugger. There is only one class that extends it, the DefaultAuditableBeanWrapperFactory
and then there is a class that extends that one in turn, the MappingAuditableBeanWrapperFactory
. Both define the getBeanWrapperFor
method, so if you are going to put breakpoints on this level add it to both classes.
Just out of interest I put my breakpoint in the DefaultAuditableBeanWrapperFactory.getBeanWrapperFor
method and was quickly able to resolve my mistake:
/**
* Returns an {@link AuditableBeanWrapper} if the given object is capable of being equipped with auditing information.
*
* @param source the auditing candidate.
* @return
*/
@Override
@SuppressWarnings("unchecked")
public <T> Optional<AuditableBeanWrapper<T>> getBeanWrapperFor(T source) {
Assert.notNull(source, "Source must not be null");
return Optional.of(source).map(it -> {
if (it instanceof Auditable) {
return (AuditableBeanWrapper<T>) new AuditableInterfaceBeanWrapper(conversionService, (Auditable<Object, ?, TemporalAccessor>) it);
}
AnnotationAuditingMetadata metadata = AnnotationAuditingMetadata.getMetadata(it.getClass());
if (metadata.isAuditable()) {
return new ReflectionAuditingBeanWrapper<T>(conversionService, it);
}
return null;
});
}
So I am on Spring Boot 2.7.3 which uses spring data commons 2.7.2 and spring data mongodb 3.4.2, and to fix my issue, (I use both blocking and reactive repositories), I had to add both two annotations to my data configuration:
/**
** NOTE @EnableMongoAuditing for blocking access
** NOTE @EnableReactiveMongoAuditing for reactive access
**/
@Configuration
@EnableMongoAuditing
@EnableReactiveMongoAuditing
public class MyProjectDataConfig
{
// ...
}