PersistenceException: Failed to locate field

#1

Hi, have recently been running into this issue when changing the schema:

com.objectdb.o._PersistenceException: Failed to locate field

in this case, adding a primitive String field to an Entity.

pretty sure that in the past schema evolution would not have triggered errors, is this case, a simple new field, shouldn't the policy be to add a null in that field, or other default for that primitive.

Specifically, from:

http://www.objectdb.com/java/jpa/entity/schema

"Fields in the new schema that do not have matching fields in the old schema are initialized with default values (0, false or null)."

is this a bug, or have I somehow configured the database to complain about this?

 

#2

The schema evolution should work in this case, nothing was changed.

An exception may be thrown if you mix old and new enhancement. Please make sure that after the change you only use a clean build of your application with fresh enhancement.

ObjectDB Support
#3

Thanks, though I've been using this enhancement for ages (I think it's actually means no enhancement, serialization only):

<entities>

    <enhancement agent = "false" reflection = "warning"/>

    <cache ref = "weak" level2 = "20m"/>

    <fetch hollow = "true"/>

    <persist serialization = "true"/>

    <cascade-persist always = "true" on-persist = "true" on-commit = "true"/>

    <dirty-tracking arrays = "true"/>

  </entities>
#4

Changed settings to default:

<entities>
    <enhancement agent = "true" reflection = "warning"/>
    <cache ref = "weak" level2 = "20m"/>
    <fetch hollow = "true"/>
    <persist serialization = "false"/>
    <cascade-persist always = "true" on-persist = "true" on-commit = "true"/>
    <dirty-tracking arrays = "true"/>
  </entities>

and still get this error, so that's not the problem.

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: com.objectdb.o._PersistenceException: Failed to locate field field app.model.Auction.name2 using reflection
at com.objectdb.o._PersistenceException.b(_PersistenceException.java:45)
at com.objectdb.o.JPE.g(JPE.java:145)
at com.objectdb.o.ERR.f(ERR.java:55)
at com.objectdb.o.OST.onObjectDBError(OST.java:599)
at com.objectdb.jpa.EMF.createEntityManager(EMF.java:153)
at javax.persistence.EntityManagerFactory$createEntityManager$0.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at app.database.ObjectDbDatabase.<init>(ObjectDbDatabase.groovy:61)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:255)
at AuServerRedis.<clinit>(AuServerRedis.groovy:79)
Caused by: com.objectdb.o.UserException: Failed to locate field field app.model.Auction.name2 using reflection
at com.objectdb.o.MSG.d(MSG.java:75)
at com.objectdb.o.UMR.P(UMR.java:937)
at com.objectdb.o.UMR$T.i(UMR.java:1065)
at com.objectdb.o.MMM.<init>(MMM.java:299)
at com.objectdb.o.UTY.W(UTY.java:625)
at com.objectdb.o.UTY.S(UTY.java:407)
at com.objectdb.o.TYS.l(TYS.java:171)
at com.objectdb.o.TYM.ae(TYM.java:529)
at com.objectdb.o.MST.UP(MST.java:1163)
at com.objectdb.o.WRA.UP(WRA.java:213)
at com.objectdb.o.STC.m(STC.java:340)
at com.objectdb.o.SHN.ad(SHN.java:388)
at com.objectdb.o.SHN.K(SHN.java:133)
at com.objectdb.o.HND.run(HND.java:133)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NoSuchFieldException: name2
at java.lang.Class.getDeclaredField(Class.java:2070)
at com.objectdb.o.UMR$T.i(UMR.java:1060)
... 12 more
#5

The stack trace is thrown on the server side. Maybe the server has access to an old version of the class (in its classpath) without the new field.

ObjectDB Support
#6

I'm wondering if any of the classes are actually being enhanced.

I'm not using command line enhancement, nor programmatic enhancement, just relying on the config setting:

<enhancement agent = "true" reflection = "warning"/>

Am wondering if there is a way to know what settings ODB is using when it starts up?

Would be useful to log the location of the config file it is using, plus the contents of that config file, given that I've found many cases where the config file it's actually using isn't as expected, eg. in production vs development.

So, would be useful to log, at startup, current config file location and contents.

So, back to this question: does schema evolution work where you're relying only on the enhancement setting in the config file?

#7

You may not be using enhancement. But schema evolution should still work.

ObjectDB Support
#8

ok, so problem resolves if I add programmatic enhancement:

static void main ( args ) {

    com.objectdb.Enhancer.enhance("app.model.*");

Note: I removed programmatic many years ago because of some issue which I believe may have been related to my use of groovy instead of java. But, now it seems to be working fine.

I would still consider it a bug that enhancement based only on the XML agent=true flag, and no command line or programmatic enhancement, complains about schema evolution.

Or, at least there should be a note that enhancement based only on the XML setting won't allow schema evolution.

#9

not sure how to debug your question re the server having access to an old version,

shouldn't it automatically flush it's caches if the schema evolves?

or at least shouldn't that be a user setting?

Anyway the problem goes away with programmatic enhancement, which if I recall from the past, adds setters and getters and is much faster, or has that changed?

 

#10

There is a warning in the documentation (at the end of the Enhancer page) against the configuration based enhancement, which in some environments doesn't work (it is not something in the control of ObjectDB). Note that your current enhancement call is also not perfect, as it may fail if class for enhancement is loaded by the JVM before enhancement, but as long as it works it is fine.

Reflection should still work, including in schema evolution, and the cause for this failure is still unclear. But enhancement is certainly recommended in production as it produces faster code.

ObjectDB Support
#11
Thanks, I did notice that I needed to run the program twice to get enhancement to work. There is a block static { .... } So perhaps I should out the enhancement code in there first or have a proxy class which calls the main class, if I recall that was the recommended solution But having to run it twice is fine for me.

Reply