spring-projects / spring-data-commons

Spring Data Commons. Interfaces and code shared between the various datastore specific implementations.
https://spring.io/projects/spring-data
Apache License 2.0
778 stars 675 forks source link

Auditor attempts to set created date on null object [DATACMNS-1671] #2091

Closed spring-projects-issues closed 4 years ago

spring-projects-issues commented 4 years ago

Joel Toby opened DATACMNS-1671 and commented

The exact issue reported in DATACMNS-1461 is still persisting in v2.2.4.  I recently upgraded from v2.0.6.RELEASE which worked fine with the same code.

The only difference with my code vs Lukas Krecan's  example in DATACMNS-1461 is that my @CreatedDate annotated field is within an _@Embeddable_.

@MappedSuperclass
public abstract class ClassA {

  @Id
  private String id;

  @Embedded
  private ClassB embeddable;
}

@Embeddable
public class ClassB {

  @CreatedDate
  private Date created;
}

 

Stack trace:

 

org.springframework.data.mapping.MappingException: Cannot lookup property @javax.persistence.Embedded()private com.company.ClassB com.company.ClassA.created on null intermediate! Original path was: embeddable.created on com.company.ConcreteA.
at org.springframework.data.mapping.PersistentPropertyAccessor.setProperty(PersistentPropertyAccessor.java:70) at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingMetadataAuditableBeanWrapper.lambda$setDateProperty$1(MappingAuditableBeanWrapperFactory.java:265) at java.lang.Iterable.forEach(Iterable.java:75) at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingMetadataAuditableBeanWrapper.setDateProperty(MappingAuditableBeanWrapperFactory.java:265) at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingMetadataAuditableBeanWrapper.setCreatedDate(MappingAuditableBeanWrapperFactory.java:198) at org.springframework.data.auditing.AuditingHandler.lambda$touchDate$9(AuditingHandler.java:219) at java.util.Optional.ifPresent(Optional.java:159) at org.springframework.data.auditing.AuditingHandler.touchDate(AuditingHandler.java:219) at org.springframework.data.auditing.AuditingHandler.lambda$touch$0(AuditingHandler.java:166) at java.util.Optional.map(Optional.java:215) at org.springframework.data.auditing.AuditingHandler.touch(AuditingHandler.java:163) at org.springframework.data.auditing.AuditingHandler.markCreated(AuditingHandler.java:131) at org.springframework.data.jpa.domain.support.AuditingEntityListener.touchForCreate(AuditingEntityListener.java:92) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.hibernate.jpa.event.internal.ListenerCallback.performCallback(ListenerCallback.java:35) at org.hibernate.jpa.event.internal.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:95) at org.hibernate.jpa.event.internal.CallbackRegistryImpl.preCreate(CallbackRegistryImpl.java:55) at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:113) at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118) at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:726) at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:694) at org.hibernate.engine.spi.CascadingActions$7.cascade(CascadingActions.java:298) at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:492) at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:416) at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218) at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:151) at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:432) at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:269) at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:198) at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:140) at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:108) at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:702) at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:688) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:314) at com.sun.proxy.$Proxy182.persist(Unknown Source) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:554) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAll(SimpleJpaRepository.java:588) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAll(SimpleJpaRepository.java:78) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:371) at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:204) at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:657) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:621) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy211.saveAll(Unknown Source)
  

Affects: 2.1.15 (Lovelace SR15), 2.2.4 (Moore SR4)

Issue Links:

Backported to: 2.1.16 (Lovelace SR16)

spring-projects-issues commented 4 years ago

Joel Toby commented

Apologies for opening a new issue.  I couldn't manage to re-open the other one

spring-projects-issues commented 4 years ago

Mark Paluch commented

Thanks for report. With DATACMNS-1461, we only fixed setting the auditor user but the same issue persists for date values. We're going to fix that issue

spring-projects-issues commented 4 years ago

Joel Toby commented

Perfect. Thanks for the fast reply and context Mark Paluch

spring-projects-issues commented 4 years ago

Mark Paluch commented

That's fixed now

spring-projects-issues commented 4 years ago

Joel Toby commented

Super fast!  Thanks