OpenJPA
  1. OpenJPA
  2. OPENJPA-1900

ClassCastException when serializing an entity if DetachedStateField=true

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0.1, 2.1.0, 2.2.0
    • Fix Version/s: 2.1.0, 2.2.0
    • Component/s: kernel
    • Labels:
      None

      Description

      When using

      <property name="openjpa.DetachState" value="fetch-groups(DetachedStateField=true)"/>

      serializing an entity leads to the following Exception:

      java.lang.ClassCastException: org.apache.openjpa.kernel.StateManagerImpl cannot be cast to org.apache.openjpa.kernel.DetachedStateManager
      at org.apache.openjpa.util.Proxies.writeReplace(Proxies.java:147)
      at org.apache.openjpa.util.java$util$Date$proxy.writeReplace(Unknown Source)
      at sun.reflect.GeneratedMethodAccessor176.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at java.io.ObjectStreamClass.invokeWriteReplace(ObjectStreamClass.java:1032)
      at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1107)
      at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
      at org.apache.openjpa.kernel.SingleFieldManager.serialize(SingleFieldManager.java:545)
      at org.apache.openjpa.kernel.StateManagerImpl.writeDetached(StateManagerImpl.java:1478)
      at at.ac.tuwien.tiss.curriculum.be.entities.CurriculumVersion.writeExternal(CurriculumVersion.java)
      at java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1421)

      This seems related to OPENJPA-1597

      1. OPENJPA-1900-test-1.patch
        14 kB
        Mark Struberg
      2. OPENJPA-1900-fix.patch
        0.8 kB
        Mark Struberg
      3. OPENJPA-1900.patch
        17 kB
        Rick Curtis

        Activity

        Hide
        Mark Struberg added a comment -

        I was still not able to reproduce this in a unit test, but from debugging my real world app it seems to happen when lazy loaded entities get serialized.

        Show
        Mark Struberg added a comment - I was still not able to reproduce this in a unit test, but from debugging my real world app it seems to happen when lazy loaded entities get serialized.
        Hide
        Mark Struberg added a comment -

        I tried to reproduce my problem with an unit test but had no luck so far. But the test now crashes with another issue.

        testSerialization(org.apache.openjpa.persistence.proxy.TestEntitySerialize) Time elapsed: 14.822 sec <<< ERROR!
        java.lang.NullPointerException
        at org.apache.openjpa.persistence.proxy.TestEntitySerialize.testSerialization(TestEntitySerialize.java:104)

        The situation:
        I added a 'previousAnnuity' to reflect the existence of a annuity predecessor.
        The data I create is a FixedAnnuity which gets superceeded by an EquityAnnuity.
        I then load the last annuity (the EquityAnnuity) in one transaction. While having the EntityManager open, the previousAnnuity is available. But if I close the EntityManager, it suddenly dissapears (field get's reset to null).

        Is this a spec like behaviour that entity members get deleted while closing the EntityManager?

        Show
        Mark Struberg added a comment - I tried to reproduce my problem with an unit test but had no luck so far. But the test now crashes with another issue. testSerialization(org.apache.openjpa.persistence.proxy.TestEntitySerialize) Time elapsed: 14.822 sec <<< ERROR! java.lang.NullPointerException at org.apache.openjpa.persistence.proxy.TestEntitySerialize.testSerialization(TestEntitySerialize.java:104) The situation: I added a 'previousAnnuity' to reflect the existence of a annuity predecessor. The data I create is a FixedAnnuity which gets superceeded by an EquityAnnuity. I then load the last annuity (the EquityAnnuity) in one transaction. While having the EntityManager open, the previousAnnuity is available. But if I close the EntityManager, it suddenly dissapears (field get's reset to null). Is this a spec like behaviour that entity members get deleted while closing the EntityManager?
        Hide
        Mark Struberg added a comment -

        actually it was my error, forgot to @OneToOne the field ... slap, coffeerefill

        Show
        Mark Struberg added a comment - actually it was my error, forgot to @OneToOne the field ... slap , coffeerefill
        Hide
        Mark Struberg added a comment -

        think I know the difference between the openjpa-persistence-jdbc and my projects config. I use the openjpa-maven-plugin for enhancing my project and I get the Externalizable interface generated into my enhanced classes. This doesn't happen with the Annuity entities.

        But the problem above only happens if StateManagerImpl#writeDetached get's invoked on an entity which is linked to multiple other entites...

        Question: why do I get the Externalizable interface in my entities?

        Show
        Mark Struberg added a comment - think I know the difference between the openjpa-persistence-jdbc and my projects config. I use the openjpa-maven-plugin for enhancing my project and I get the Externalizable interface generated into my enhanced classes. This doesn't happen with the Annuity entities. But the problem above only happens if StateManagerImpl#writeDetached get's invoked on an entity which is linked to multiple other entites... Question: why do I get the Externalizable interface in my entities?
        Hide
        Mark Struberg added a comment -

        The Externalizable field gets added if I use the openjpa.DetachStage fetch-groups(DetachStateField=true)

        This is an issues in our test suite currently - it uses different persistence.xml for enhancing ($

        {project.build.testOutputDirectory}

        /META-INF/nopriv_persistence.xml) and running the tests (org/apache/openjpa/persistence/proxy/persistence1.xml)

        Thus my test currently succeeds but only because this isn't a real world scenario.

        PS: took me a while to figure this, but at least I'm now pretty deep into OpenJPA internals

        Show
        Mark Struberg added a comment - The Externalizable field gets added if I use the openjpa.DetachStage fetch-groups(DetachStateField=true) This is an issues in our test suite currently - it uses different persistence.xml for enhancing ($ {project.build.testOutputDirectory} /META-INF/nopriv_persistence.xml) and running the tests (org/apache/openjpa/persistence/proxy/persistence1.xml) Thus my test currently succeeds but only because this isn't a real world scenario. PS: took me a while to figure this, but at least I'm now pretty deep into OpenJPA internals
        Hide
        Mark Struberg added a comment -

        this small patch fixes the behaviour. This needs a review of course, because I might have overseen some side effects...

        Show
        Mark Struberg added a comment - this small patch fixes the behaviour. This needs a review of course, because I might have overseen some side effects...
        Hide
        Rick Curtis added a comment -

        Good work on this one. I just looked at your patches and you had to dig pretty deep to figure this out out.

        I have a few comments for you. I was able to recreate the CCE, but after applying the code fix I fail with a NPE coming from test code[1]. I'm not sure why that field is null but I'm guessing it has something to do with the DetachState setting. If I change fgs to loaded the NPE goes away.... Are you seeing the same benaviour?

        Thanks,
        Rick

        [1]:407 ann.getPreviousAnnuity().setApprovedAt( new Date() ); – getPreviousAnnuity() returns null

        Show
        Rick Curtis added a comment - Good work on this one. I just looked at your patches and you had to dig pretty deep to figure this out out. I have a few comments for you. I was able to recreate the CCE, but after applying the code fix I fail with a NPE coming from test code [1] . I'm not sure why that field is null but I'm guessing it has something to do with the DetachState setting. If I change fgs to loaded the NPE goes away.... Are you seeing the same benaviour? Thanks, Rick [1] :407 ann.getPreviousAnnuity().setApprovedAt( new Date() ); – getPreviousAnnuity() returns null
        Hide
        Rick Curtis added a comment -

        Mark -

        It looks like I should have read through all of your comments... I added @OneToOne to Annuity.getPreviousAnnuity() and things are looking better now.

        Thanks,
        Rick

        Show
        Rick Curtis added a comment - Mark - It looks like I should have read through all of your comments... I added @OneToOne to Annuity.getPreviousAnnuity() and things are looking better now. Thanks, Rick
        Hide
        Mark Struberg added a comment -

        Hi Rick! I'm currently compiling, so gimme an hour
        I'm online in #openjpa on freenode.

        Show
        Mark Struberg added a comment - Hi Rick! I'm currently compiling, so gimme an hour I'm online in #openjpa on freenode.
        Hide
        Rick Curtis added a comment -

        Resolved in 2.1.x and trunk.

        Thanks for the patch Mark!

        Show
        Rick Curtis added a comment - Resolved in 2.1.x and trunk. Thanks for the patch Mark!
        Hide
        Albert Lee added a comment -

        Close issue in preparation for 2.2.0 release.

        Show
        Albert Lee added a comment - Close issue in preparation for 2.2.0 release.

          People

          • Assignee:
            Rick Curtis
            Reporter:
            Mark Struberg
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development