Issue #2409: ClassCastException during query

Type: BugVersion: 2.7.6_02Priority: CriticalStatus: ActiveReplies: 5
#1

Hello,

we get following exception. Can you explain why?

best regards BTC

Caused by: java.lang.ClassCastException: com.btc.ep.vector.accessor.Identifier$IdentifierKind2 cannot be cast to com.btc.ep.vector.accessor.Identifier$IdentifierKind2
    at com.btc.ep.vector.tc.internal.dmos.TCSignal.__odbReadContent(TCSignal.java:1) ~[na:na]
    at com.objectdb.o.MMM.I(MMM.java:1207) ~[na:na]
    at com.objectdb.o.UTY.K(UTY.java:1505) ~[na:na]
    at com.objectdb.o.UTY.L(UTY.java:1432) ~[na:na]
    at com.objectdb.o.ENH.d(ENH.java:104) ~[na:na]
    at com.objectdb.o.LDR.d(LDR.java:836) ~[na:na]
    at com.objectdb.o.LDR.n(LDR.java:224) ~[na:na]
    at com.objectdb.o.OBC.ab(OBC.java:1085) ~[na:na]
    at com.objectdb.o.OBC.ai(OBC.java:990) ~[na:na]
    at com.objectdb.o.OBC.Yu(OBC.java:800) ~[na:na]
    at com.objectdb.o.SRB.a(SRB.java:162) ~[na:na]
    at com.objectdb.o.QRR.h(QRR.java:565) ~[na:na]
    at com.objectdb.o.QRR.i(QRR.java:225) ~[na:na]
    at com.objectdb.jpa.JpaQuery.getResultList(JpaQuery.java:721) ~[na:na]

#2

This exception indicates a class loader conflict. There are more than one version of the com.btc.ep.vector.accessor.Identifier.IdentifierKind2 class, loaded by different class loaders.

One version of the class is used by ObjectDB to create the object when it is loaded from the database (either through a class loader that is available for ObjectDB or generated by ObjectDB if the class is unavailable).

Another class is used by your application code (for casting the retrieved object to the version of the class known at the enhanced class com.btc.ep.vector.tc.internal.dmos.TCSignal).

Please verify that the same class loader that is available for your own application is also available for ObjectDB for loading retrieved objects.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
#3

Hello,

I solved the issue. It seems that the class which is an enum and caused the class cast exception must be also enhanced. I moved the enum to an entity package whose entities become automatically enhanced.

Thank you for your help.

best regards

BTC

#4

Interesting. Thank you for the update.

ObjectDB doesn't usually enhance enum classes (i.e. nothing to enhance, except if there is code in the enum class), but maybe moving the enum class made it available in one version for both ObjectDB and your other model classes, as discussed above.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
#5

Hello,

unfortunately I have to reopen the issue.
I cannot just move the enum class into the entity package, this has organization reasons.
And I tested your fix with the last ObjectDB patch 2.7.6_02, but the fix does not work.
We got the same exception as before.

I analyzed the bug deeper and I saw that the related enum class is only loaded once by the osgi classloader.
I would expect that this class has to load twice by the osgi classloader in order to cause the class cast exception.
Now I think the objectdb uses the boot class loader for the enum class, if the enum content is read within the ObjectDB.

Why is the class loading behavior so different, if we put the enum class in an entity package or outside of an entity package?

best regards

BTC

#6

> And I tested your fix with the last ObjectDB patch 2.7.6_02, but the fix does not work.

Changes in build 2.7.6_02 are not related to this thread but to other issues in other threads (issue #2403, issue #2406). Please reply in these other threads regarding fixes of build 2.7.6_02.

Regarding this issue, as discussed, this is a class loading issue. When objects are retrieved from the database ObjectDB has to instantiate entity objects and their components. It cannot retrieve an object with an enum value without obtaining a reference to the relevant enum value. Unfortunately it seems that ObjectDB doesn't have access to your enum class so it has to generate its own version of the enum class (possibly a synthetic class), which is different from the version that your application uses, so although it is the same enum name, it fails casting.

> unfortunately I have to reopen the issue.
> I cannot just move the enum class into the entity package, this has organization reasons.

Usually such an enum, which is part of the object model in the database, is kept together with the entire object model. However, if this is not possible, just make sure that ObjectDB will have access to that enum class.

ObjectDB uses the first available class loader (which is not null) from the following list:

  1. Thread.currentThread().getContextClassLoader()
  2. ClassLoader.getSystemClassLoader()
  3. The class loader that loaded the ObjectDB library itself.

By setting a thread class loader (Thread.currentThread().setContextClassLoader(...)) in the thread that instantiate the EntityManagerFactory and EntityManager, you can control which classes are accessible to ObjectDB. The enum class must be made accessible as well.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)

Post Reply

To post a reply and/or subscribe to update notifications - please login