I can confirm that the issue is that the _broker is returning null when I receive this error, isPersistent never get called as a result. I haven't yet worked out what in he broker is causing it to return null. My entity manager is never being closed during the session as I am only testing as a single user as I am keeping the entity manager open for each session since creating a new entity manager is expensive, well at least when using the subclassing enhancer.
Thanks to your sample I was able to get the build time enhancement working, finally! Thank you! I'm now trying to replicate the issue again to try to see what's going on. I am still finding that the majority of the time I am getting the exception in org.apache.openjpa.kernel.AttachStrategy.getReference, now I'm just waiting till it throws the exception again in SingleFieldManager. Still doesn't make sense to me why the same process and data is throwing different exceptions though. -----Original Message----- From: Daryl Stultz [mailto:[email protected]] Sent: Thursday, 17 September 2009 9:40 PM To: [email protected] Subject: Re: SingleFieldManager crash On Wed, Sep 16, 2009 at 11:41 PM, C N Davies <[email protected]> wrote: > I've put a try catch around my code that is triggering the issue, I've written the following code to assist my debugging: private void collectJpaDebug(String name, Object object, StringBuffer sb, EntityManager em) { sb.append(name + ": " + object); try { if (object != null) { sb.append("-"); OpenJPAEntityManager emo = (OpenJPAEntityManager) em; sb.append("EM:"); sb.append(emo.isDetached(object) ? "D" : "d"); sb.append(emo.isDirty(object) ? "X" : "x"); sb.append(emo.isNewlyPersistent(object) ? "N" : "n"); sb.append(emo.isPersistent(object) ? "P" : "p"); sb.append(emo.isRemoved(object) ? "R" : "r"); sb.append(emo.isTransactional(object) ? "T" : "t"); EntityManagerImpl emi = (EntityManagerImpl) em; final Broker broker = emi.getBroker(); sb.append(" BK:"); sb.append(broker.isDetachedNew() ? "C" : "c"); sb.append(broker.isDirty(object) ? "X" : "x"); sb.append(broker.isNew(object) ? "N" : "n"); sb.append(broker.isPersistent(object) ? "P" : "p"); sb.append(broker.isDeleted(object) ? "R" : "r"); sb.append(broker.isTransactional(object) ? "T" : "t"); OpenJPAStateManager sm = broker.getStateManager(object); sb.append(" SM:"); if (sm != null) { sb.append(sm.isDetached() ? "D" : "d"); sb.append(sm.isDirty() ? "X" : "x"); sb.append(sm.isNew() ? "N" : "n"); sb.append(sm.isPersistent() ? "P" : "p"); sb.append(sm.isProvisional() ? "V" : "v"); sb.append(sm.isDeleted() ? "R" : "r"); sb.append(sm.isTransactional() ? "T" : "t"); } else { sb.append("null"); } } } catch (Throwable exc) { sb.append(exc); } sb.append("\n"); } This generates a number of "flags" for the various properties. So for this case: EntityManager em = getEm(); A a = em.find(A.class, 1); // EM:dxnPrt BK:cxnPrt SM:dxnPvrt em.close(); em = getEm(); // a different em // EM:Dxnprt BK:cxnprt SM:null a = new A(); // EM:dxnprt BK:cxnprt SM:null a.setId(1); // EM:dxnprt BK:cxnprt SM:null I've added the resulting "flags" after the operations. It seems the only time an object has a state manager is when it is currently managed. Detached objects have no sm. I guess I had the "feeling" the state manager was part of the enhanced object, but it looks like it's in the em. So going back to the code of SingleFieldManager: *private* *void* preFlushPC(ValueMetaData vmd, Object obj, *boolean* logical, OpCallbacks call) { *if* (obj == *null*) *return*; OpenJPAStateManager sm; *if* (vmd.getCascadePersist() == ValueMetaData.*CASCADE_NONE*) { *if* (!_broker.isDetachedNew() && _broker.isDetached(obj)) *return*; // allow but ignore sm = _broker.getStateManager(obj); *if* (sm == *null* || !sm.isPersistent()) *throw* *new* InvalidStateException( *_loc*.get("cant-cascade-persist", vmd)) .setFailedObject(obj); } *else* { I think it's fair to say that it's failing on sm == null rather than !sm.isPersistent() since the FailedObject is at least detached and possibly "unmanaged" altogether (whatever that means). Since my debugging always returns on the blue line, the question is now why, once in a great while, does it now think that the object is not detached (read: not formerly managed by a different em). There's also the possiblility that _broker.isDetachedNew() is wrong - I don't know what that means yet. -- Daryl Stultz _____________________________________ 6 Degrees Software and Consulting, Inc. http://www.6degrees.com mailto:[email protected]
