[
https://issues.apache.org/jira/browse/OPENJPA-2718?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Damian Bułak updated OPENJPA-2718:
----------------------------------
Description:
Assuming I have three entities - Organization, Department and Employee and
Organization has collection of Departments and Department has collection of
employees where each association has CascadeType.ALL, when I open three
transactions within one entity manager session:
In 1st transaction a department is created and persisted
In 2nd transaction an organization is created and previously created department
is fetched from DB and added to organization departments set, then organization
is persisted
In 3rd transaction an employee is created and added to the department created
in 1st transaction, which is again as in 2nd transaction fetched from DB.
The following exception is thrown:
{code}
<openjpa-2.4.2-r422266:1777108 fatal store error>
org.apache.openjpa.persistence.RollbackException:
org.apache.openjpa.kernel.DetachedValueStateManager cannot be cast to
org.apache.openjpa.kernel.StateManagerImpl
at
org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:595)
at
CascadeTestCase.shouldEmployeeBeCascadedFromDepartment(CascadeTestCase.java:30)
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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
at
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
at
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
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.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at
org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at
org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
at
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: <openjpa-2.4.2-r422266:1777108 nonfatal general error>
org.apache.openjpa.persistence.PersistenceException:
org.apache.openjpa.kernel.DetachedValueStateManager cannot be cast to
org.apache.openjpa.kernel.StateManagerImpl
at
org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2029)
at
org.apache.openjpa.kernel.LocalManagedRuntime.commit(LocalManagedRuntime.java:81)
at org.apache.openjpa.kernel.BrokerImpl.commit(BrokerImpl.java:1526)
at
org.apache.openjpa.kernel.DelegatingBroker.commit(DelegatingBroker.java:932)
at
org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:571)
... 30 more
Caused by: java.lang.ClassCastException:
org.apache.openjpa.kernel.DetachedValueStateManager cannot be cast to
org.apache.openjpa.kernel.StateManagerImpl
at
org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:134)
at
org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushAndUpdate(BatchingPreparedStatementManagerImpl.java:79)
at
org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushInternal(PreparedStatementManagerImpl.java:100)
at
org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flush(PreparedStatementManagerImpl.java:88)
at
org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:550)
at
org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:107)
at
org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager.flush(BatchingConstraintUpdateManager.java:59)
at
org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:104)
at
org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:77)
at
org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:731)
at
org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2205)
at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2103)
at
org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2021)
... 34 more
{code}
What I did is I debugged the OpenJPA sources and found that persisting the
organization in the second transaction triggers flush on department entity but
the department state manager is marked with the FLAG_PRE_FLUSHED flag which
after the whole operation is still active (it should be removed in
StateManagerImpl#afterFlush(int reason)) and that's why the employee object
from 3rd transaction is not persisted - the first condition in
StateManagerImpl#preFlush(boolean logical, OpCallbacks call) is false.
Obviously the Employee entity should be persisted since it is added to the
collection with cascading and at the commit time flush should trigger that
operation.
It seems that the problem is very similar to
https://issues.apache.org/jira/projects/OPENJPA/issues/OPENJPA-2360 and
probably has the same root.
I attached a simple test case which reproduces the issue.
was:
Assuming I have three entities - Organization, Department and Employee and
Organization has collection of Departments and Department has collection of
employees where each association has CascadeType.ALL, when I open three
transactions within one entity manager session:
In 1st transaction a department is created and persisted
In 2nd transaction an organization is created and previously created department
is fetched from DB and added to organization departments set, then organization
is persisted
In 3rd transaction an employee is created and added to the department created
in 1st transaction, which is again as in 2nd transaction fetched from DB.
The following exception is thrown:
{code}
<openjpa-2.4.2-r422266:1777108 fatal store error>
org.apache.openjpa.persistence.RollbackException:
org.apache.openjpa.kernel.DetachedValueStateManager cannot be cast to
org.apache.openjpa.kernel.StateManagerImpl
at
org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:595)
at
CascadeTestCase.shouldEmployeeBeCascadedFromDepartment(CascadeTestCase.java:30)
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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
at
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
at
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
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.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at
org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at
org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
at
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: <openjpa-2.4.2-r422266:1777108 nonfatal general error>
org.apache.openjpa.persistence.PersistenceException:
org.apache.openjpa.kernel.DetachedValueStateManager cannot be cast to
org.apache.openjpa.kernel.StateManagerImpl
at
org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2029)
at
org.apache.openjpa.kernel.LocalManagedRuntime.commit(LocalManagedRuntime.java:81)
at org.apache.openjpa.kernel.BrokerImpl.commit(BrokerImpl.java:1526)
at
org.apache.openjpa.kernel.DelegatingBroker.commit(DelegatingBroker.java:932)
at
org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:571)
... 30 more
Caused by: java.lang.ClassCastException:
org.apache.openjpa.kernel.DetachedValueStateManager cannot be cast to
org.apache.openjpa.kernel.StateManagerImpl
at
org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:134)
at
org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushAndUpdate(BatchingPreparedStatementManagerImpl.java:79)
at
org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushInternal(PreparedStatementManagerImpl.java:100)
at
org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flush(PreparedStatementManagerImpl.java:88)
at
org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:550)
at
org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:107)
at
org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager.flush(BatchingConstraintUpdateManager.java:59)
at
org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:104)
at
org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:77)
at
org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:731)
at
org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2205)
at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2103)
at
org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2021)
... 34 more
{code}
What I did, I debugged the OpenJPA sources and found that persisting the
organization in the second transaction triggers flush on department however the
department state manager is marked with the FLAG_PRE_FLUSHED flag but after the
whole operation the flag is still active (it should be removed in
StateManagerImpl#afterFlush(int reason) and that's why the employee object from
3rd transaction is not persisted - the first condition in
StateManagerImpl#preFlush(boolean logical, OpCallbacks call) is false.
Obviously the Employee entity should be persisted since it is added to the
collection with cascading and at the commit time flush should trigger that
operation.
It seems that the problem is very similar to
https://issues.apache.org/jira/projects/OPENJPA/issues/OPENJPA-2360 and
probably has the same root.
I attached a simple test case which reproduces the issue.
> ClassCastException during flush
> -------------------------------
>
> Key: OPENJPA-2718
> URL: https://issues.apache.org/jira/browse/OPENJPA-2718
> Project: OpenJPA
> Issue Type: Bug
> Components: jpa, kernel
> Affects Versions: 2.4.2
> Reporter: Damian Bułak
> Priority: Critical
> Attachments: openjpa-cascading-bug.zip
>
>
> Assuming I have three entities - Organization, Department and Employee and
> Organization has collection of Departments and Department has collection of
> employees where each association has CascadeType.ALL, when I open three
> transactions within one entity manager session:
> In 1st transaction a department is created and persisted
> In 2nd transaction an organization is created and previously created
> department is fetched from DB and added to organization departments set, then
> organization is persisted
> In 3rd transaction an employee is created and added to the department created
> in 1st transaction, which is again as in 2nd transaction fetched from DB.
> The following exception is thrown:
> {code}
> <openjpa-2.4.2-r422266:1777108 fatal store error>
> org.apache.openjpa.persistence.RollbackException:
> org.apache.openjpa.kernel.DetachedValueStateManager cannot be cast to
> org.apache.openjpa.kernel.StateManagerImpl
> at
> org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:595)
> at
> CascadeTestCase.shouldEmployeeBeCascadedFromDepartment(CascadeTestCase.java:30)
> 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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
> at
> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
> at
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
> at
> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
> at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
> at
> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
> at
> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
> at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
> at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
> at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
> at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
> at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
> at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
> at
> org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
> at
> org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
> at
> org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
> 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.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
> at
> org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
> at
> org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
> at
> org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
> at
> org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
> Caused by: <openjpa-2.4.2-r422266:1777108 nonfatal general error>
> org.apache.openjpa.persistence.PersistenceException:
> org.apache.openjpa.kernel.DetachedValueStateManager cannot be cast to
> org.apache.openjpa.kernel.StateManagerImpl
> at
> org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2029)
> at
> org.apache.openjpa.kernel.LocalManagedRuntime.commit(LocalManagedRuntime.java:81)
> at org.apache.openjpa.kernel.BrokerImpl.commit(BrokerImpl.java:1526)
> at
> org.apache.openjpa.kernel.DelegatingBroker.commit(DelegatingBroker.java:932)
> at
> org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:571)
> ... 30 more
> Caused by: java.lang.ClassCastException:
> org.apache.openjpa.kernel.DetachedValueStateManager cannot be cast to
> org.apache.openjpa.kernel.StateManagerImpl
> at
> org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:134)
> at
> org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushAndUpdate(BatchingPreparedStatementManagerImpl.java:79)
> at
> org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushInternal(PreparedStatementManagerImpl.java:100)
> at
> org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flush(PreparedStatementManagerImpl.java:88)
> at
> org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:550)
> at
> org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:107)
> at
> org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager.flush(BatchingConstraintUpdateManager.java:59)
> at
> org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:104)
> at
> org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:77)
> at
> org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:731)
> at
> org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131)
> at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2205)
> at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2103)
> at
> org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2021)
> ... 34 more
> {code}
> What I did is I debugged the OpenJPA sources and found that persisting the
> organization in the second transaction triggers flush on department entity
> but the department state manager is marked with the FLAG_PRE_FLUSHED flag
> which after the whole operation is still active (it should be removed in
> StateManagerImpl#afterFlush(int reason)) and that's why the employee object
> from 3rd transaction is not persisted - the first condition in
> StateManagerImpl#preFlush(boolean logical, OpCallbacks call) is false.
> Obviously the Employee entity should be persisted since it is added to the
> collection with cascading and at the commit time flush should trigger that
> operation.
> It seems that the problem is very similar to
> https://issues.apache.org/jira/projects/OPENJPA/issues/OPENJPA-2360 and
> probably has the same root.
> I attached a simple test case which reproduces the issue.
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)