Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-dev] Need help understanding why invalid objectstill returned without refresh when read via UOW

Hi Sebastien,

Let me see if I understand what you are doing. Please correct the things that are not correct.

1. You execute a query for Object A in a UOW
2. Object A has a relationship to Object B with no indirection
3. Object A exists in the UOW's parent cache, but has not been registered in the UOW yet
4. Object A has been invalidated in the UOW's parent cache
5. Your query returns a version of Object A that points to an invalidated version of Object B
6. You are expecting Object B to be refreshed

-Tom

Sebastien Tardif wrote:
It seems to be a regression; our old unit tests are failing different ways.

We execute a query via UOW. A child of the returned object is returned stale; we can see that it is stale in the cache by calling API and by debugging the CacheKey.

From the stack you can confirm that the stale child object is retrieved from the session cache and not the UOW because of this -> getAndCloneCacheKeyFromParent

Where in "Traversing a direct relationship" does the refresh supposed to occur?

We rarely use indirection in our application, so this relation was direct relationship.

So far I did notice this strange behavior in the following code:

Extract from TopLink source code class UnitOfWorkImpl. In some scenario collection getNewObjectsCloneToOriginal doesn’t have the object but getNewObjectsOriginalToClone has it! So the expression [if (original != *null*)], which seems an insignificant optimization, is creating an issue when the assumption that both getNewObjectsCloneToOriginal() and getNewObjectsOriginalToClone() are always in sync is not true.

// Remove object from the new object cache
// PERF: Avoid initialization of new objects if none.

     *if* (hasNewObjects()) {

          Object original = getNewObjectsCloneToOriginal().remove(object);

            *if* (original != *null*) {

                getNewObjectsOriginalToClone().remove(original);

            }

     }

-----Original Message-----
From: eclipselink-dev-bounces@xxxxxxxxxxx [mailto:eclipselink-dev-bounces@xxxxxxxxxxx] On Behalf Of Tom Ware
Sent: Tuesday, May 19, 2009 11:20 AM
To: Dev mailing list for Eclipse Persistence Services
Subject: Re: [eclipselink-dev] Need help understanding why invalid objectstill returned without refresh when read via UOW

Hi Sebastien,

What, specifically are you doing when you see this issue? From the stack

trace, I see you are executing some kind of a query. What kind of query? Is

the behavior always the same, or does it depend on whether the object returned

by your query is already registered in the UnitOfWork?

In general, the getFromIdentityMap code in UnitOfWork is designed to always

return a value whether or not the object is invalidated in other levels of

caching in order to maintain identity within the transaction the UnitOfWork

represents.

In the bug you mention below, we adjusted the behavior of the UnitOfWork as a

whole to deal better with a list of circumstances list in the bug:

--

When an object is registered in a UnitOfWork through:

a) Direct query execution against the UOW

b) Session.read* calls (which execute a query)

c) Traversing a direct relationship

d) traversing an indirect relationship

--

Has this behavior actually changed or have you encountered a new variant of

the use case. (i.e. is it possible to write code that succeeds on TopLink 10.x

and fails on EclipseLink 1.1.1)

From your questions: The comment should definitely be updated and depending

on what we determine from our discussion about this issue, it is possible that

we will want to update the code path you are seeing in your stack trace. The

list above from the TopLink bug-fix provides a list of areas where we would like

to be doing the refresh for you.

-Tom

Sebastien Tardif wrote:

 The original issue was fixed in TopLink 10.x under bug/patch 6865193 -

 INVALID OBJECTS IN CACHE SHOULD BE REFRESHED WHEN REGISTERED IN UOW.







 But now I'm testing my production application using EclipseLink 1.1.1

 RC1 and the bug is back. Simple test case doesn't fail! So besides

 answering questions below, if someone wants to have a live trace session

 on my desktop using my application for test case that's a possibility.







 In the stack below getAndCloneCacheKeyFromParent is called with

 shouldReturnInvalidatedObjects ==  true while the object is invalid, so

 the code in getAndCloneCacheKeyFromParent still return the object

 because of this condition:



 if ((cacheKey != null) && (shouldReturnInvalidatedObjects ||

 !descriptor.getCacheInvalidationPolicy().isInvalidated(cacheKey))) {







 Strangely the caller passing true for shouldReturnInvalidatedObjects has

 this comment:



 //Bug#4613774  In the parent session, only return the object if it has

 not been Invalidated



        return getAndCloneCacheKeyFromParent(primaryKey, theClass,

 shouldReturnInvalidatedObjects, descriptor);







 True is hardcoded in the code of line 327:



 *public* Object getFromIdentityMap(Vector primaryKey, Class theClass,

 ClassDescriptor descriptor) {



        *return* getFromIdentityMap(primaryKey, theClass, *true*,

 descriptor);



    }







 So the questions are:



 1-    Does the following comment wrong? only return the object if it has

 not been Invalidated



 2-    Should line 327 be modified to pass false?



 3-    Where is the responsibility to refresh the invalid object?







Daemon Thread [WebContainer : 0] (Suspended)




 UnitOfWorkIdentityMapAccessor.getAndCloneCacheKeyFromParent(Vector,

Class, boolean, ClassDescriptor) line: 136



      UnitOfWorkIdentityMapAccessor.getFromIdentityMap(Vector, Class,

boolean, ClassDescriptor) line: 110





UnitOfWorkIdentityMapAccessor(IdentityMapAccessor).getFromIdentityMap(Vector,

Class, ClassDescriptor) line: 327



       UnitOfWorkImpl.registerExistingObject(Object, ClassDescriptor)

line: 3781



UnitOfWorkImpl.registerExistingObject(Object) line: 3741




 OneToOneMapping(ObjectReferenceMapping).buildCloneForPartObject(Object,

Object, Object, UnitOfWorkImpl, boolean) line: 68



      NoIndirectionPolicy.cloneAttribute(Object, Object, Object,

UnitOfWorkImpl, boolean) line: 72



      OneToOneMapping(ForeignReferenceMapping).buildClone(Object,

Object, UnitOfWorkImpl) line: 156



      ObjectBuilder.populateAttributesForClone(Object, Object,

 UnitOfWorkImpl) line: 2627



      UnitOfWorkImpl.populateAndRegisterObject(Object, Object, CacheKey,

CacheKey, ClassDescriptor) line: 3537



      UnitOfWorkImpl.cloneAndRegisterObject(Object, CacheKey, CacheKey,

ClassDescriptor) line: 923



      UnitOfWorkImpl.cloneAndRegisterObject(Object, CacheKey,

 ClassDescriptor) line: 832




 UnitOfWorkIdentityMapAccessor.getAndCloneCacheKeyFromParent(Vector,

Class, boolean, ClassDescriptor) line: 171



      UnitOfWorkIdentityMapAccessor.getFromIdentityMap(Vector, Class,

boolean, ClassDescriptor) line: 110





UnitOfWorkIdentityMapAccessor(IdentityMapAccessor).getFromIdentityMap(Vector,

Class, ClassDescriptor) line: 327



      UnitOfWorkImpl.registerExistingObject(Object, ClassDescriptor)

line: 3781



UnitOfWorkImpl.registerExistingObject(Object) line: 3741




 ReadObjectQuery(ObjectBuildingQuery).registerIndividualResult(Object,

UnitOfWorkImpl, JoinedAttributeManager) line: 362



      ObjectBuilder.buildWorkingCopyCloneNormally(ObjectBuildingQuery,

 AbstractRecord, UnitOfWorkImpl, Vector, ClassDescriptor,

JoinedAttributeManager) line: 584



      ObjectBuilder.buildObjectInUnitOfWork(ObjectBuildingQuery,

 JoinedAttributeManager, AbstractRecord, UnitOfWorkImpl, Vector,

ClassDescriptor) line: 544



      ObjectBuilder.buildObject(ObjectBuildingQuery, AbstractRecord,

JoinedAttributeManager) line: 485



      ObjectBuilder.buildObject(ObjectLevelReadQuery, AbstractRecord)

line: 437



      ReadObjectQuery(ObjectLevelReadQuery).buildObject(AbstractRecord)

line: 569



      ReadObjectQuery.registerResultInUnitOfWork(Object, UnitOfWorkImpl,

AbstractRecord, boolean) line: 712



ReadObjectQuery.executeObjectLevelReadQuery() line: 436



      ReadObjectQuery(ObjectLevelReadQuery).executeDatabaseQuery() line:

 928



      ReadObjectQuery(DatabaseQuery).execute(AbstractSession,

AbstractRecord) line: 664



      ReadObjectQuery(ObjectLevelReadQuery).execute(AbstractSession,

AbstractRecord) line: 889



      ReadObjectQuery.execute(AbstractSession, AbstractRecord) line:

397




 ReadObjectQuery(ObjectLevelReadQuery).executeInUnitOfWork(UnitOfWorkImpl,

AbstractRecord) line: 952



      UnitOfWorkImpl.internalExecuteQuery(DatabaseQuery, AbstractRecord)

 line: 2755



      UnitOfWorkImpl(AbstractSession).executeQuery(DatabaseQuery,

 AbstractRecord, int) line: 1181





 ------------------------------------------------------------------------



 _______________________________________________

 eclipselink-dev mailing list

 eclipselink-dev@xxxxxxxxxxx

 https://dev.eclipse.org/mailman/listinfo/eclipselink-dev

_______________________________________________

eclipselink-dev mailing list

eclipselink-dev@xxxxxxxxxxx

https://dev.eclipse.org/mailman/listinfo/eclipselink-dev


------------------------------------------------------------------------

_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev


Back to the top