2.7.3_03 Erroneous "Attempt to modify a primary key of a managed object"

#1

ObjectDB 2.7.3_03 gives my application a "com.objectdb.o.UserException: Attempt to modify a primary key of a managed object", but my application is not trying to change the primary key.  (ObjectDB log file attached.)

If I revert to ObjectDB 2.7.3, then no more exception.  (No other code changed, just ObjectDB.)

#2

(P.S.  When I submitted the forum post, I received an ObjectDB website error that my attachment could not be uploaded.  But, it did upload.  Screenshot image that shows the error is attached.)

#3

This is probably caused by a change in version 2.7.3_03 (which fixed an issue reported in this thread).

Could you please check version 2.7.3_04 (which disables the change, so exception should not be thrown) and version 2.7.3_05 (which enables the change, but improves the error message that you got with 2.7.3_03).

Thanks.

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

Confirmed.  2.7.3_04 does NOT give the exception.

2.7.3_05 log file attached.

#5

Thanks. Could you please provide details on the primary key of JdoBlob2?

Is it composite? embedded ID? Is there an ID class attached?

Relevant fields and annotations from class JdoBlob2 could help.

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

I uploaded my responses as a private Support Ticket (673?).

#7

Thanks. It seems that there is nothing wrong with the change in build 2.7.3_03 (and 2.7.3_05), but apparently it exposes an existing problem, due to an additional new check.

It could be again related to class loading (maybe the Java 9.0 modules).

Your id type is StringIdentity.

Note that StringIdentity is defined in JDO to represent a combination of class + primary key and therefore it seems a bit strange to use it as the type of the id field. You should be able to change the id field to a simple String without database schema change, and save some space in memory. You can still use StringIdentity to represent object IDs externally when a combination of class + primary key is needed. This may solve the exception.

Anyway, StringIdentity as a primary key field type (although rarely used) seems to work, usually, as your application demonstrates. Unfortunately it seems that the following lines of code in ObjectDB fail:

if (SingleFieldIdentity.class.isAssignableFrom(m_memberType.getSysType()))
    memberObj = ((SingleFieldIdentity)memberObj).getKeyAsObject();

The parameter to the isAssignableFrom method is the type of your primary key field, i.e. StringIdentity, which is a subclass of SingleFieldIdentity. Unexpectedly, it seems that the expression in the if is evaluated to false, and an essential operation for primary key field of type StringIdentity is missed.

This could happen if more than one version of these JDO classes is used in the JVM, due to class loader mismatch.

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

Not related to the reported issue, but why do you duplicate the primary key into an additional indexed field? Primary key fields are already indexed (and with a primary index, which is usually more powerful), so what are the benefits of having that additional indexed field?

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

Textual letter case.  I have an index on the exact case and on all lower case.  This gives me the ability to find the key regardless of case and still have the ability to display the actual letter case as entered by the user.

My key is similar to a filing system path.  Example.  "My Drawer/MyFolder/SomeTab/DocumentA" is the case typed by the user and is the primary key used to save/restore the object into/out of the database.  Another user might try to navigate and enter "My drawer/Myfolder/someTab/documenta", and I want to be able to find the object using the String ID (must match exactly), so I make that all lower case (the secondary indexed key) to find the object.  When displaying the path, I can use the primary key to display the correct case, "My Drawer/MyFolder/SomeTab/DocumentA".

#10

That makes sense. Anyway, post #8 is only a side note. See #7 for recent status.

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

You are saying that I could change all my JDO classes from

@Id private StringIdentity id;

to

@Index private String id;

and that might fix the issue, save memory, and not require database schema change (automatically updates and just works)?

I tried 2.7.3_05 again with ObjectDB logging "debug" to see if there is some class loading failure for SingleFieldIdentity.  No failures, except for class "String", but you explained to me in another forum post that that exception is "normal" and alright.

Here it is again for reference:

[2017-12-29 10:21:28 #265 type.loader]
java.lang.ClassNotFoundException: String
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
at com.objectdb/com.objectdb.o.RCL.c(RCL.java:301)
at com.objectdb/com.objectdb.o.ACL.loadClass(ACL.java:102)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
at com.objectdb/com.objectdb.o.TYM.L(TYM.java:1046)
at com.objectdb/com.objectdb.o.TRS.b(TRS.java:179)
at com.objectdb/com.objectdb.o.SYR.e(SYR.java:121)
at com.objectdb/com.objectdb.o.QRC.<init>(QRC.java:156)
at com.objectdb/com.objectdb.o.QRM.ZE(QRM.java:272)
at com.objectdb/com.objectdb.o.MST.ZE(MST.java:1001)
at com.objectdb/com.objectdb.o.WRA.ZE(WRA.java:313)
at com.objectdb/com.objectdb.o.WSM.ZE(WSM.java:117)
at com.objectdb/com.objectdb.o.QRR.k(QRR.java:249)
at com.objectdb/com.objectdb.o.QRR.i(QRR.java:155)
at com.objectdb/com.objectdb.jdo.JdoQuery.execute0(JdoQuery.java:843)
at com.objectdb/com.objectdb.jdo.JdoQuery.execute(JdoQuery.java:760)
at com.unilogical.moxydox.server/com.unilogical.moxydox.server.database.Database.debugDump(Database.java:1353)
at com.unilogical.moxydox.server/com.unilogical.moxydox.server.ui.MainController.lambda$debugDumpFired$27(MainController.java:953)
at com.unilogical.moxydox.server/com.unilogical.moxydox.server.BackgroundThread.run(BackgroundThread.java:148)
#12

OK, so it seems that this solves the issue.

There is still a question why StringIdentity is not identified as a subclass of SingleFieldIdentity in #7 above, which is probably the result of a class loading conflict that may or may not appear again somewhere else in the future.

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

Issue not yet resolved.  In #11 I ask a question.  Then a separate thought of "is there an error that we didn't see because I used "info" and not "debug" in the ObjectDB log?".

 

If you tell me #11 question is correct, THEN I will attempt that to see if it fixes my issue.

 

I am also investigating if my Java 9 module setup needs to be told to let ObjectDB module also reflectively access some other package.  (Presumably we see the ObjectDB failure, as you describe, because Java 9 module blocked a class loading via reflection.  Maybe.)

#14

Sorry. I thought that you reported trying this change and the result log,

Please try replacing:

@Id private StringIdentity id;

to

@Id private String id;

Note: @Id remains and not replaced with @Index.

You should be able to read old data with no schema change, as actually StringIdentity is not really supported as a primary key field, so it is considered as a simple String.

INFO logging mode should be sufficient to see reported errors. The stack trace in #11 is normal in debug.

 

 

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

Switching from "StringIdentity" to "String" resolves the issue, tested with ObjectDB 2.7.3_05.

#16

Good. Thank you for the update.

I wonder if StringIdentity should be allowed as a type of a primary key field, as it is not fully supported by ObjectDB, and actually its purpose is to represent object IDs externally where both class + PK are needed.

Have you seen using StringIdentity as a type of a PK field in JDO documentation?

Maybe ObjectDB should produce an error if StringIdentity is used as a PK field type.

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

http://www.objectdb.com/api/java/jdo/id/classes classes is the reference for this quote:

The following classes serve as predefined ID classes
for persistence capable classes with a simple single field
primary key (whose type is one of the supported simple types):

I took that as I SHOULD use StringIdentity if I wanted a persistent object where I wanted a primary key of just a String.

If StringIndentity is not to be used with ObjectDB that way, then some sort of warning message would be great to help avoid making the same mistake I did.

#18

A warning was added in build 2.7.3_06 and the documentation page was now updated to avoid further confusion.

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

still happening in 2.7.4_04

I rolled back to 2.7.3_06

-  Confirmed that it's still happening (I can't be sure it wasn't here originally).

rolled back to 2.7.3

- no problems in 2.7.3

 

#20

The exception should be thrown on an attempt to modify a primary key of a managed object. Older versions missed some checks that were added recently.

This thread discussed a very specific case of misusing JDO's SingleFieldIdentity subclasses for primary key fields, which started causing exceptions only with the additional checks.

Please describe your case in more details.

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

Hi, the error I got was the same as the title of this thread: Erroneous "Attempt to modify a primary key of a managed object"

So I assumed it was relevant to the thread.

This was an error that occured after updating the objectdb jar, no other changes.

In my case I don't actually modify primary keys at all.

Actually all objects in my application extend this abstract class:

abstract class AuEntity implements Serializable { @Id @GeneratedValue long id } 

it's the ONLY place in the entire application where id is set.

what other information can I provide?

 

#22

Please post a full stack trace of the exception.

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

Post Reply

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