简体   繁体   中英

Spring Mongo Auditing not working @CreatedDate @CreatedBy

I am using Spring Mongo Auditing and @CreatedDate @CreatedBy not working but @LastModifiedDate and @LastModifiedBy working fine.

I added @EnableMongoAuditing on a configuration class and also defined the AuditAware.

@Component("securityAuditorAware")
public class SecurityAuditorAware implements AuditorAware<String> {

 @Override
 public Optional<String> getCurrentAuditor() {
  return Optional.ofNullable(SecurityUtils.getUserPrincipal()).map(AuthenticatedUser::getIssuer);
 } 
}

Auditing class is:

@Document
public class Template  {

 @Id
 private UUID id = UUID.randomUUID();

 @CreatedDate
 private Date createdOn;
 @LastModifiedDate
 private Date modifiedOn;
 @CreatedBy
 private String createdBy;
 @LastModifiedBy
 private String modifiedBy;
}

When I save the document it put null in both createdOn and createdBy but the right values in both modifiedOn and modifiedBy

Thanks for the help

If your Entity does not inheritance Persistable interface, you should define a field which marked by @Version (org.springframework.data.annotation.Version).

@Document
public class Template {

 @Id
 private UUID id = UUID.randomUUID();

 @CreatedDate
 private Date createdOn;
 @LastModifiedDate
 private Date modifiedOn;
 @CreatedBy
 private String createdBy;
 @LastModifiedBy
 private String modifiedBy;
 @Version
 private Integer version;
}

In other side, if your entity inheritance Persistable interface, you should implement logical which to detect the entity never been persisted before.

For more information, you can check two class: PersistentEntityIsNewStrategy and PersistableIsNewStrategy

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
{
  // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM