Uploaded image for project: 'OpenJPA'
  1. OpenJPA
  2. OPENJPA-2718

ClassCastException during flush

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Critical
    • Resolution: Unresolved
    • 2.4.2
    • None
    • jpa, kernel
    • None

    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:

      <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
      

      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.

      Attachments

        1. openjpa-cascading-bug.zip
          5 kB
          Damian Bułak

        Activity

          People

            Unassigned Unassigned
            dbulak Damian Bułak
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: