Uploaded image for project: 'Spring Data Commons'
  1. Spring Data Commons
  2. DATACMNS-1519

Auditing exception when nested entities in collection type filed have audit fields

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Minor
    • Resolution: Works as Designed
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Mapping / Conversion
    • Labels:
      None
    • Environment:
      macOS 10.14.4
      java 1.8.0_192
      spring-data-commons 2.1.3.RELEASE
      spring-data-mongodb 2.1.3.RELEASE

      Description

      Hi. I'm trying to add auto auditing into spring project using spring-data-commons,spring-data-mongodb,both version 2.1.3.RELEASE

      1. Enable mongo auditing in my spring project's mongodbConfig by using @EnableMongoAuditing.
      2. Add an abstract entity(AbstractEntity) with @CreatedDate, @LastModifiedDate, @CreatedBy, and @LastModifiedBy annotations.
      3. Add a sub object(EntityB) extends AbstractEntity,EntityB also have other ordinary fields.
      4. Add another object(EntityA) extends AbstractEntity,EntityA have other ordinary fields and a collection filed type of List<EntityB>
      5. Try saving EntityA's instance with collection filed type of List<EntityB> contains some EntityB's instance by calling the MongoRepository's save() method.
      6. The error(java.lang.IllegalArgumentException) should display(Target bean of type java.util.ArrayList is not of type of the persistent entity (EntityB)!: java.util.ArrayList).

      here's the data structure

      here's the exception stack trace:

        java.lang.Thread.State: RUNNABLE
      	  at org.springframework.util.Assert.instanceCheckFailed(Assert.java:655)
      	  at org.springframework.util.Assert.isInstanceOf(Assert.java:574)
      	  at org.springframework.data.mapping.model.BasicPersistentEntity.verifyBeanType(BasicPersistentEntity.java:551)
      	  at org.springframework.data.mapping.model.BasicPersistentEntity.getPropertyAccessor(BasicPersistentEntity.java:453)
      	  at org.springframework.data.mapping.PersistentPropertyAccessor.setProperty(PersistentPropertyAccessor.java:76)
      	  at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingMetadataAuditableBeanWrapper.lambda$setDateProperty$2(MappingAuditableBeanWrapperFactory.java:243)
      	  at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingMetadataAuditableBeanWrapper$$Lambda$1130.982668958.accept(Unknown Source:-1)
      	  at java.lang.Iterable.forEach(Iterable.java:75)
      	  at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingMetadataAuditableBeanWrapper.setDateProperty(MappingAuditableBeanWrapperFactory.java:243)
      	  at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingMetadataAuditableBeanWrapper.setLastModifiedDate(MappingAuditableBeanWrapperFactory.java:220)
      	  at org.springframework.data.auditing.AuditingHandler.lambda$touchDate$11(AuditingHandler.java:220)
      	  at org.springframework.data.auditing.AuditingHandler$$Lambda$1129.953422663.accept(Unknown Source:-1)
      	  at java.util.Optional.ifPresent(Optional.java:159)
      	  at org.springframework.data.auditing.AuditingHandler.touchDate(AuditingHandler.java:220)
      	  at org.springframework.data.auditing.AuditingHandler.lambda$touch$0(AuditingHandler.java:166)
      	  at org.springframework.data.auditing.AuditingHandler$$Lambda$1123.1510646824.apply(Unknown Source:-1)
      	  at java.util.Optional.map(Optional.java:215)
      	  at org.springframework.data.auditing.AuditingHandler.touch(AuditingHandler.java:163)
      	  at org.springframework.data.auditing.AuditingHandler.markModified(AuditingHandler.java:143)
      	  at org.springframework.data.auditing.IsNewAwareAuditingHandler.markAudited(IsNewAwareAuditingHandler.java:83)
      	  at org.springframework.data.mongodb.core.mapping.event.AuditingEventListener.lambda$onApplicationEvent$0(AuditingEventListener.java:54)
      	  at org.springframework.data.mongodb.core.mapping.event.AuditingEventListener$$Lambda$1095.2043125926.apply(Unknown Source:-1)
      	  at org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent.mapSource(MongoMappingEvent.java:90)
      	  at org.springframework.data.mongodb.core.mapping.event.AuditingEventListener.onApplicationEvent(AuditingEventListener.java:54)
      	  at org.springframework.data.mongodb.core.mapping.event.AuditingEventListener.onApplicationEvent(AuditingEventListener.java:32)
      	  at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
      	  at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
      	  at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
      	  at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:398)
      	  at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:355)
      	  at org.springframework.data.mongodb.core.ReactiveMongoTemplate.maybeEmitEvent(ReactiveMongoTemplate.java:2407)
      	  at org.springframework.data.mongodb.core.ReactiveMongoTemplate.lambda$doSave$35(ReactiveMongoTemplate.java:1428)
      	  at org.springframework.data.mongodb.core.ReactiveMongoTemplate$$Lambda$1094.398724568.doInCollection(Unknown Source:-1)
      	  at org.springframework.data.mongodb.core.ReactiveMongoTemplate.lambda$createMono$8(ReactiveMongoTemplate.java:599)
      	  at org.springframework.data.mongodb.core.ReactiveMongoTemplate$$Lambda$990.1881179642.apply(Unknown Source:-1)

      I found that method

      line:56  setProperty(..)

      in

      PersistentPropertyAccessor

      may have defect in this nested collection field scenario:

      line:64 Object parent = parentPath.isEmpty() ? getBean() : getProperty(parentPath)

      while object "parent" get the collection type of List<EntityB>

      line:74 PersistentPropertyAccessor<?> accessor = parent == getBean() //
       ? this //
       : leafProperty.getOwner().getPropertyAccessor(parent);

      1.leafProperty is EntityB's annotated property field

      2.leafProperty.getOwner() get PersistenceEntity of EntityB

      3.leafProperty.getOwner().getPropertyAccessor(parent) try to get audit fileld's accessor of the given bean(which is List<entityB>) from PersistenceEntity of EntityB

      4.IllegalArgumentException occurred

       

      I've checked github's master branch and seems latest code still have the same behavior

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              olivergierke Oliver Drotbohm
              Reporter:
              revivn revivn
              Last updater:
              Oliver Drotbohm
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: