Recursive calls with @PreUpdate annotation and Glassfish OutOfMemoryError

#1

Hi,

   I've had an issue that started today and it's got me stumped. I've got a subclass User, which extends a BaseEntity. The BaseEntity has a @PreUpdate as per:

@PreUpdate  
     public void update(){
   System.out.println(" ********* Called update() **********");
   lastUpdatedDate = new Date();
  }

I've managed to deduce that it only happens when classes are enhanced. When they are not enhanced, everything works fine. Once the error is hit, it keeps on happening and until I remove the enhancement (I do this build time with maven).

First, for the test case I supplied:

1) You need to run test test repeatedly (it is a repeatable test) to expose the issue

2) Once you get the issue, comment out the method "enhanceClasses()" - this shows that it does not happen anymore.

 

On Glassfish it does the same thing but the app dies with "OutOfMemoryError" but the underlying condition is hard to see - Glassfish doesn't report any objectdb errors.  In glassfish I run client/server, but the test is running embedded. 

Example output of error

....
********* Called update() **********
********* Called update() **********
********* Called update() **********
********* Called update() **********
********* Called update() **********
********* Called update() **********
********* Called update() **********
Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class com.objectdb.o.MSS
at com.objectdb.o.ECI.invoke(ECI.java:101)
at com.objectdb.o.EDS.i(EDS.java:241)
at com.objectdb.jpa.EMImpl.fire(EMImpl.java:1083)
at com.objectdb.jpa.EMImpl.bd(EMImpl.java:1036)
at com.objectdb.jdo.PMImpl.bd(PMImpl.java:2572)
at com.objectdb.o.ENT.Z(ENT.java:1177)

If you need more explanation, please let me know. The test isn't pretty code as I tried to get  only the things to expose the issue, nothing else..

Could be a mac thing? Unfortunately I don't have a PC on hand to test with.

Thanks

 

ObjectDB Version: 2.2.8

OS: OSX 10.6.8

JVM:

java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03-384-10M3425)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02-384, mixed mode)

#2

Apologies, 

  In my haste I omitted that turning off enhancements does NOT fix the issue in client/server mode. The issue persists until I remove the offending property update (ore disable the @PreUpdate).

 

Thanks

#3

I keep thinking this to myself and just based on some debugging I came to the assumptions that:

1) ObjectDB calls update() based on the @PreUpdate field due to state change detection

2) update() method modifies internal state of the object being persisted

3) ObjectDB picks up internal change

4) go to 1

 

However, it doesn't happen under all conditions - I think it is happening because the interceptor is the 'base' class? I have another class with a @PreUpdate (which updates some search meta-data List<String> based on updated state) that works just fine. So, could it be an issue that is just related to @EntityListeners (or @PreUpdate itself) that modifies a field on the base class of the entity hierarchy?

 

My listing of assumptions above is based on the following call trace: 

SimpleObjectDBTest$Company(SimpleObjectDBTest$BaseEntity).update() line: 145
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
ECI.invoke(Object) line: 95
EDS.i(int, Object) line: 241
PMImpl(EMImpl).fire(int, Object, UTY) line: 1083
PMImpl(EMImpl).bd(Object, UTY) line: 1036
PMImpl.bd(Object, UTY) line: 2572
ENT.Z() line: 1177
ENT.Y(UMR, boolean) line: 1041
ENT.beforeModifyMember(int) line: 971
SimpleObjectDBTest$BaseEntity.__odbSet_lastUpdatedDate(SimpleObjectDBTest$BaseEntity, Date) line: 1

Again this could all be my fault as I' modifying the internal state of the object prior to update and it makes sense in a way for this recursion to happen. Previously, I had this is a separate EntityListener but it was doing the same thing, regardless of whether the @EntityListener was defined in the base class or sub class.

 

Thanks

#4

Thank you for this bug report and for the test.

Please try build 2.2.8_01.

ObjectDB Support
#5

Tested this with simple test and in-app and it all works as expected.

 

Thank you

Reply