Hibernate cascade warning

Description

Stack overflow report: https://stackoverflow.com/questions/58127755/hibernateexception-flush-during-cascade-is-dangerous-during-recordtransaction

Stack trace is below.

We flush in the AppendOnlyPersistentMap logic so that during a session more entities than can fit in memory can be iterated over, otherwise without the flush they all have to remain memory resident and tracked by Hibernate. We have a listener that can tell if we are already in a flush to prevent recursive flushes. It looks like we should do something similar for cascades, based on this exception. Hopefully there's a convenient listener. If not, we could look at creating a bypass for identities (this happens because there's a column converter for Party - so the map gets consulted from inside Hibernate itself, setting up potential recursion), perhaps as an option on the map.

javax.persistence.PersistenceException: org.hibernate.HibernateException: Flush during cascade is dangerous
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1460) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1440) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at net.corda.node.utilities.AppendOnlyPersistentMapBase.loadValue(AppendOnlyPersistentMap.kt:145) ~[corda-node-4.1.jar:?]
at net.corda.node.utilities.AppendOnlyPersistentMapBase.access$loadValue(AppendOnlyPersistentMap.kt:22) ~[corda-node-4.1.jar:?]
at net.corda.node.utilities.AppendOnlyPersistentMapBase$transactionalLoadValue$3.invoke(AppendOnlyPersistentMap.kt:160) ~[corda-node-4.1.jar:?]
at net.corda.node.utilities.AppendOnlyPersistentMapBase$Transactional$Unknown$valueWithoutIsolationDelegate$1.invoke(AppendOnlyPersistentMap.kt:251) ~[corda-node-4.1.jar:?]
at kotlin.SafePublicationLazyImpl.getValue(LazyJVM.kt:107) ~[kotlin-stdlib-1.2.71.jar:1.2.71-release-64 (1.2.71)]
at net.corda.node.utilities.AppendOnlyPersistentMapBase$Transactional$Unknown.isPresent(AppendOnlyPersistentMap.kt:249) ~[corda-node-4.1.jar:?]
at net.corda.node.utilities.AppendOnlyPersistentMapBase$Transactional.orElse(AppendOnlyPersistentMap.kt:222) ~[corda-node-4.1.jar:?]
at net.corda.node.utilities.AppendOnlyPersistentMapBase.get(AppendOnlyPersistentMap.kt:40) ~[corda-node-4.1.jar:?]
at net.corda.node.services.identity.PersistentIdentityService$certificateFromCordaX500Name$1.invoke(PersistentIdentityService.kt:165) ~[corda-node-4.1.jar:?]
at net.corda.node.services.identity.PersistentIdentityService$certificateFromCordaX500Name$1.invoke(PersistentIdentityService.kt:33) ~[corda-node-4.1.jar:?]
at net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:224) ~[corda-node-api-4.1.jar:?]
at net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:204) ~[corda-node-api-4.1.jar:?]
at net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:210) ~[corda-node-api-4.1.jar:?]
at net.corda.node.services.identity.PersistentIdentityService.certificateFromCordaX500Name(PersistentIdentityService.kt:164) ~[corda-node-4.1.jar:?]
at net.corda.node.services.identity.PersistentIdentityService.wellKnownPartyFromX500Name(PersistentIdentityService.kt:175) ~[corda-node-4.1.jar:?]
at net.corda.core.node.services.IdentityService$DefaultImpls.wellKnownPartyFromAnonymous(IdentityService.kt:103) ~[corda-core-4.1.jar:?]
at net.corda.node.services.api.IdentityServiceInternal$DefaultImpls.wellKnownPartyFromAnonymous(IdentityServiceInternal.kt) ~[corda-node-4.1.jar:?]
at net.corda.node.services.identity.PersistentIdentityService$wellKnownPartyFromAnonymous$1.invoke(PersistentIdentityService.kt:184) ~[corda-node-4.1.jar:?]
at net.corda.node.services.identity.PersistentIdentityService$wellKnownPartyFromAnonymous$1.invoke(PersistentIdentityService.kt:33) ~[corda-node-4.1.jar:?]
at net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:224) ~[corda-node-api-4.1.jar:?]
at net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:204) ~[corda-node-api-4.1.jar:?]
at net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:210) ~[corda-node-api-4.1.jar:?]
at net.corda.node.services.identity.PersistentIdentityService.wellKnownPartyFromAnonymous(PersistentIdentityService.kt:184) ~[corda-node-4.1.jar:?]
at net.corda.node.internal.AbstractNode$database$2.invoke(AbstractNode.kt:158) ~[corda-node-4.1.jar:?]
at net.corda.node.internal.AbstractNode$database$2.invoke(AbstractNode.kt:120) ~[corda-node-4.1.jar:?]
at net.corda.node.services.persistence.AbstractPartyToX500NameAsStringConverter.convertToDatabaseColumn(AbstractPartyToX500NameAsStringConverter.kt:23) ~[corda-node-4.1.jar:?]
at net.corda.node.services.persistence.AbstractPartyToX500NameAsStringConverter.convertToDatabaseColumn(AbstractPartyToX500NameAsStringConverter.kt:15) ~[corda-node-4.1.jar:?]
at org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl.toRelationalValue(JpaAttributeConverterImpl.java:50) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter$1.bind(AttributeConverterSqlTypeDescriptorAdapter.java:78) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:280) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:275) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:39) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2868) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3162) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3686) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:90) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.spi.ActionQueue.executeInserts(ActionQueue.java:461) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:258) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:359) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:292) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:200) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:131) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:824) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:791) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.spi.CascadingActions$7.cascade(CascadingActions.java:298) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:471) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:396) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:197) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:504) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:436) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:399) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:197) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:130) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:486) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:200) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:143) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:800) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
at net.corda.node.services.schema.PersistentStateService.persistStatesWithSchema$node(PersistentStateService.kt:48) ~[corda-node-4.1.jar:?]
at net.corda.node.services.schema.PersistentStateService.persist(PersistentStateService.kt:40) ~[corda-node-4.1.jar:?]
at net.corda.node.services.vault.NodeVaultService.processAndNotify(NodeVaultService.kt:364) ~[corda-node-4.1.jar:?]
at net.corda.node.services.vault.NodeVaultService.access$processAndNotify(NodeVaultService.kt:51) ~[corda-node-4.1.jar:?]
at net.corda.node.services.vault.NodeVaultService$notifyAll$1.invoke(NodeVaultService.kt:213) ~[corda-node-4.1.jar:?]
at net.corda.node.services.vault.NodeVaultService.notifyAll(NodeVaultService.kt:223) ~[corda-node-4.1.jar:?]
at net.corda.node.services.api.ServiceHubInternal$Companion$recordTransactions$1.invoke(ServiceHubInternal.kt:106) ~[corda-node-4.1.jar:?]
at net.corda.node.services.api.ServiceHubInternal$Companion$recordTransactions$1.invoke(ServiceHubInternal.kt:51) ~[corda-node-4.1.jar:?]
at net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:224) ~[corda-node-api-4.1.jar:?]
at net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:204) ~[corda-node-api-4.1.jar:?]
at net.corda.nodeapi.internal.persistence.CordaPersistence.transaction(CordaPersistence.kt:210) ~[corda-node-api-4.1.jar:?]
at net.corda.node.services.api.ServiceHubInternal$Companion.recordTransactions(ServiceHubInternal.kt:60) ~[corda-node-4.1.jar:?]
at net.corda.node.services.api.ServiceHubInternal$DefaultImpls.recordTransactions(ServiceHubInternal.kt:132) ~[corda-node-4.1.jar:?]
at net.corda.node.internal.AbstractNode$ServiceHubInternalImpl.recordTransactions(AbstractNode.kt:962) ~[corda-node-4.1.jar:?]
at net.corda.core.flows.ReceiveTransactionFlow.call(ReceiveTransactionFlow.kt:62) ~[corda-core-4.1.jar:?]
at net.corda.core.flows.ReceiveTransactionFlow.call(ReceiveTransactionFlow.kt:28) ~[corda-core-4.1.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:329) ~[corda-node-4.1.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:314) ~[corda-core-4.1.jar:?]
at net.corda.core.flows.ReceiveFinalityFlow.call(FinalityFlow.kt:256) ~[corda-core-4.1.jar:?]
at net.corda.core.flows.ReceiveFinalityFlow.call(FinalityFlow.kt:251) ~[corda-core-4.1.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:329) ~[corda-node-4.1.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:314) ~[corda-core-4.1.jar:?]
at com.corda.test.flows.TestFlow$Responder.call(TestFlow.kt:226) ~[?:?]
at com.corda.test.flows.TestFlow$Responder.call(TestFlow.kt:221) ~[?:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:269) ~[corda-node-4.1.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:45) ~[corda-node-4.1.jar:?]
at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_222]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_222]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_222]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_222]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_222]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_222]
at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:63) ~[corda-node-4.1.jar:?]
Caused by: org.hibernate.HibernateException: Flush during cascade is dangerous
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1449) ~[hibernate-core-5.3.6.Final.jar:5.3.6.Final]
... 104 more

Status

Assignee

Dimos Raptis

Reporter

Rick Parker

Labels

Priority

High

Fix versions

Ported to...

Corda 4.3

Feature Team

Kernel Group

CVSS Vector

None

Severity

High

Story Points

5

Sprint

None

Affects versions

Configure