Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 322687

Summary: Deadlock in a single thread fetch join test
Product: z_Archived Reporter: Andrei Ilitchev <andrei.ilitchev>
Component: EclipselinkAssignee: Tom Ware <tom.ware>
Status: CLOSED INVALID QA Contact:
Severity: normal    
Priority: P2 CC: eclipselink.orm-inbox, gordon.yorke, michael.f.obrien, tom.ware
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
See Also: https://bugs.eclipse.org/bugs/show_bug.cgi?id=262157
Whiteboard:

Description Andrei Ilitchev CLA 2010-08-13 15:52:29 EDT
Observed in JUnitJPQLComplexTestSuite.complexOneToOneFetchJoinTest:
execution hangs forever while executing the query:

    String ejbqlString = "SELECT m FROM Man m LEFT JOIN FETCH m.partnerLink";
    List<Man> result = em.createQuery(ejbqlString).getResultList();

To get the issue PartnerLink entity should be altered so that geManId and getWomanId annotated as read only (instead of @Transient):

@Entity
@Table(name="MW")
@IdClass(org.eclipse.persistence.testing.models.jpa.advanced.PartnerLinkPK.class)
public class PartnerLink {
    private Man man;
    private Woman woman;

	public PartnerLink() {}
	@Id
    @OneToOne(cascade=PERSIST, fetch=LAZY)
	@JoinColumn(name="M")
	public Man getMan() { 
        return man; 
    }
    @Column(name="M", insertable=false, updatable=false)
	public Integer getManId() {
        return (getMan() == null) ? null : getMan().getId();
    }
    
    @Id
    @OneToOne(cascade=PERSIST, fetch=LAZY)
	@JoinColumn(name="W")
	public Woman getWoman() { 
        return woman; 
    }
    
    @Column(name="W", insertable=false, updatable=false)
	public Integer getWomanId() {
        return (getWoman() == null) ? null : getWoman().getId();
    }
...
}

The issue caused by the read lock acquired for PartnerLink object at:
Thread [Thread-4] (Suspended (breakpoint at line 247 in ConcurrencyManager))	
	ConcurrencyManager.acquireReadLock() line: 247	
	ConcurrencyManager.acquireReadLockNoWait() line: 262	
	CacheKey.acquireReadLockNoWait() line: 196	
	WriteLockManager.acquireLockAndRelatedLocks(Object, Map, Map, CacheKey, ClassDescriptor, AbstractSession, UnitOfWorkImpl) line: 127	
	WriteLockManager.checkAndLockObject(Object, Map, Map, DatabaseMapping, AbstractSession, UnitOfWorkImpl) line: 440	
	WriteLockManager.traverseRelatedLocks(Object, Map, Map, ClassDescriptor, AbstractSession, UnitOfWorkImpl) line: 225	
	WriteLockManager.acquireLockAndRelatedLocks(Object, Map, Map, CacheKey, ClassDescriptor, AbstractSession, UnitOfWorkImpl) line: 142	
	WriteLockManager.acquireLocksForClone(Object, ClassDescriptor, CacheKey, AbstractSession, UnitOfWorkImpl) line: 73	
	RepeatableWriteUnitOfWork(UnitOfWorkImpl).cloneAndRegisterObject(Object, CacheKey, CacheKey, ClassDescriptor) line: 976	
	ObjectBuilder.buildWorkingCopyCloneNormally(ObjectBuildingQuery, AbstractRecord, UnitOfWorkImpl, Object, ClassDescriptor, JoinedAttributeManager) line: 618	
	ObjectBuilder.buildObjectInUnitOfWork(ObjectBuildingQuery, JoinedAttributeManager, AbstractRecord, UnitOfWorkImpl, Object, ClassDescriptor) line: 555	
	ObjectBuilder.buildObject(ObjectBuildingQuery, AbstractRecord, JoinedAttributeManager) line: 495	
	ObjectBuilder.buildObject(ObjectLevelReadQuery, AbstractRecord) line: 454	
	ReadAllQuery(ObjectLevelReadQuery).buildObject(AbstractRecord) line: 721	
	ReadAllQuery.registerResultInUnitOfWork(Object, UnitOfWorkImpl, AbstractRecord, boolean) line: 726	
	ReadAllQuery.executeObjectLevelReadQuery() line: 423	
	ReadAllQuery(ObjectLevelReadQuery).executeDatabaseQuery() line: 1074	
	ReadAllQuery(DatabaseQuery).execute(AbstractSession, AbstractRecord) line: 764	
	ReadAllQuery(ObjectLevelReadQuery).execute(AbstractSession, AbstractRecord) line: 1034	
	ReadAllQuery.execute(AbstractSession, AbstractRecord) line: 383	
	ReadAllQuery(ObjectLevelReadQuery).executeInUnitOfWork(UnitOfWorkImpl, AbstractRecord) line: 1112	
	RepeatableWriteUnitOfWork(UnitOfWorkImpl).internalExecuteQuery(DatabaseQuery, AbstractRecord) line: 2910	
	RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord, int) line: 1301	
	RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord) line: 1283	
	RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, List) line: 1257	
	EJBQueryImpl<X>.executeReadQuery() line: 479	
	EJBQueryImpl<X>.getResultList() line: 714	
	JUnitJPQLComplexTestSuite.complexOneToOneFetchJoinTest() line: 1054	
	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	
	JUnitJPQLComplexTestSuite(TestCase).runTest() line: 168	
	JUnitJPQLComplexTestSuite(TestCase).runBare() line: 134	
	JUnitJPQLComplexTestSuite(JUnitTestCase).runBare() line: 466	
	TestResult$1.protect() line: 110	
	TestResult.runProtected(Test, Protectable) line: 128	
	TestResult.run(TestCase) line: 113	
	JUnitJPQLComplexTestSuite(TestCase).run(TestResult) line: 124	
	TestExecutor.execute(Test) line: 248	
	TestExecutor.runTest(Test) line: 671	
	SynchronizedTestExecutor.run() line: 61	


When Eclipselink attempts to acquire lock for the same PartnerLink object it hangs forever because of the unrelease read lock:
Thread [Thread-4] (Suspended)	
	ConcurrencyManager.acquire(boolean) line: 93	
	CacheKey.acquire() line: 113	
	FullIdentityMap(AbstractIdentityMap).acquireLock(Object, boolean) line: 107	
	IdentityMapManager.acquireLock(Object, Class, boolean, ClassDescriptor) line: 142	
	IdentityMapAccessor.acquireLock(Object, Class, boolean, ClassDescriptor) line: 92	
	IdentityMapAccessor.acquireLock(Object, Class, ClassDescriptor) line: 83	
	ObjectBuilder.buildObject(boolean, ObjectBuildingQuery, AbstractRecord, AbstractSession, Object, ClassDescriptor, JoinedAttributeManager) line: 685	
	ObjectBuilder.buildObject(ObjectBuildingQuery, AbstractRecord, JoinedAttributeManager) line: 497	
	ObjectBuilder.buildObject(ObjectLevelReadQuery, AbstractRecord) line: 454	
	ReadObjectQuery(ObjectLevelReadQuery).buildObject(AbstractRecord) line: 721	
	ReadObjectQuery.executeObjectLevelReadQuery() line: 453	
	ReadObjectQuery(ObjectLevelReadQuery).executeDatabaseQuery() line: 1074	
	ReadObjectQuery(DatabaseQuery).execute(AbstractSession, AbstractRecord) line: 764	
	ReadObjectQuery(ObjectLevelReadQuery).execute(AbstractSession, AbstractRecord) line: 1034	
	ReadObjectQuery.execute(AbstractSession, AbstractRecord) line: 412	
	ServerSession(AbstractSession).internalExecuteQuery(DatabaseQuery, AbstractRecord) line: 2402	
	ServerSession(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord, int) line: 1301	
	ServerSession(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord) line: 1283	
	NoIndirectionPolicy.valueFromQuery(ReadQuery, AbstractRecord, AbstractSession) line: 299	
	OneToOneMapping(ForeignReferenceMapping).valueFromRowInternal(AbstractRecord, JoinedAttributeManager, ObjectBuildingQuery, AbstractSession) line: 1848	
	OneToOneMapping.valueFromRowInternal(AbstractRecord, JoinedAttributeManager, ObjectBuildingQuery, AbstractSession) line: 1622	
	OneToOneMapping(ForeignReferenceMapping).valueFromRow(AbstractRecord, JoinedAttributeManager, ObjectBuildingQuery, AbstractSession) line: 1738	
	OneToOneMapping(DatabaseMapping).readFromRowIntoObject(AbstractRecord, JoinedAttributeManager, Object, ObjectBuildingQuery, AbstractSession) line: 1283	
	ObjectBuilder.buildAttributesIntoObject(Object, AbstractRecord, ObjectBuildingQuery, JoinedAttributeManager, boolean) line: 342	
	ObjectBuilder.buildObject(boolean, ObjectBuildingQuery, AbstractRecord, AbstractSession, Object, ClassDescriptor, JoinedAttributeManager) line: 704	
	ObjectBuilder.buildObject(ObjectBuildingQuery, AbstractRecord, JoinedAttributeManager) line: 497	
	ObjectBuilder.buildObject(ObjectLevelReadQuery, AbstractRecord) line: 454	
	ReadObjectQuery(ObjectLevelReadQuery).buildObject(AbstractRecord) line: 721	
	ReadObjectQuery.executeObjectLevelReadQuery() line: 453	
	ReadObjectQuery(ObjectLevelReadQuery).executeDatabaseQuery() line: 1074	
	ReadObjectQuery(DatabaseQuery).execute(AbstractSession, AbstractRecord) line: 764	
	ReadObjectQuery(ObjectLevelReadQuery).execute(AbstractSession, AbstractRecord) line: 1034	
	ReadObjectQuery.execute(AbstractSession, AbstractRecord) line: 412	
	ServerSession(AbstractSession).internalExecuteQuery(DatabaseQuery, AbstractRecord) line: 2402	
	ServerSession(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord, int) line: 1301	
	ServerSession(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord) line: 1283	
	QueryBasedValueHolder.instantiate(AbstractSession) line: 85	
	QueryBasedValueHolder.instantiate() line: 75	
	QueryBasedValueHolder(DatabaseValueHolder).getValue() line: 83	
	PartnerLink._persistence_get_woman() line: not available	
	PartnerLink.getWoman() line: 43	
	PartnerLink.getWomanId() line: 48	
	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	
	MethodAttributeAccessor.getAttributeValueFromObject(Object, Object[]) line: 74	
	MethodAttributeAccessor.getAttributeValueFromObject(Object) line: 53	
	DirectToFieldMapping(DatabaseMapping).getAttributeValueFromObject(Object) line: 497	
	DirectToFieldMapping(AbstractDirectMapping).buildCloneValue(Object, Object, AbstractSession) line: 229	
	DirectToFieldMapping(AbstractDirectMapping).buildClone(Object, Object, UnitOfWorkImpl) line: 219	
	ObjectBuilder.populateAttributesForClone(Object, Object, UnitOfWorkImpl) line: 3150	
	RepeatableWriteUnitOfWork(UnitOfWorkImpl).populateAndRegisterObject(Object, Object, CacheKey, CacheKey, ClassDescriptor) line: 3690	
	RepeatableWriteUnitOfWork(UnitOfWorkImpl).cloneAndRegisterObject(Object, CacheKey, CacheKey, ClassDescriptor) line: 1005	
	RepeatableWriteUnitOfWork(UnitOfWorkImpl).cloneAndRegisterObject(Object, CacheKey, ClassDescriptor) line: 914	
	UnitOfWorkIdentityMapAccessor.getAndCloneCacheKeyFromParent(Object, Class, boolean, ClassDescriptor) line: 181	
	UnitOfWorkIdentityMapAccessor.getFromIdentityMap(Object, Class, boolean, ClassDescriptor) line: 120	
	UnitOfWorkIdentityMapAccessor(IdentityMapAccessor).getFromIdentityMap(Object, Class, ClassDescriptor) line: 367	
	RepeatableWriteUnitOfWork(UnitOfWorkImpl).registerExistingObject(Object, ClassDescriptor) line: 3936	
	RepeatableWriteUnitOfWork(UnitOfWorkImpl).registerExistingObject(Object) line: 3894	
	OneToOneMapping(ObjectReferenceMapping).buildCloneForPartObject(Object, Object, Object, UnitOfWorkImpl, boolean) line: 67	
	NoIndirectionPolicy.cloneAttribute(Object, Object, Object, UnitOfWorkImpl, boolean) line: 72	
	OneToOneMapping(ForeignReferenceMapping).buildClone(Object, Object, UnitOfWorkImpl) line: 181	
	ObjectBuilder.populateAttributesForClone(Object, Object, UnitOfWorkImpl) line: 3150	
	RepeatableWriteUnitOfWork(UnitOfWorkImpl).populateAndRegisterObject(Object, Object, CacheKey, CacheKey, ClassDescriptor) line: 3690	
	RepeatableWriteUnitOfWork(UnitOfWorkImpl).cloneAndRegisterObject(Object, CacheKey, CacheKey, ClassDescriptor) line: 1005	
	ObjectBuilder.buildWorkingCopyCloneNormally(ObjectBuildingQuery, AbstractRecord, UnitOfWorkImpl, Object, ClassDescriptor, JoinedAttributeManager) line: 618	
	ObjectBuilder.buildObjectInUnitOfWork(ObjectBuildingQuery, JoinedAttributeManager, AbstractRecord, UnitOfWorkImpl, Object, ClassDescriptor) line: 555	
	ObjectBuilder.buildObject(ObjectBuildingQuery, AbstractRecord, JoinedAttributeManager) line: 495	
	ObjectBuilder.buildObject(ObjectLevelReadQuery, AbstractRecord) line: 454	
	ReadAllQuery(ObjectLevelReadQuery).buildObject(AbstractRecord) line: 721	
	ReadAllQuery.registerResultInUnitOfWork(Object, UnitOfWorkImpl, AbstractRecord, boolean) line: 726	
	ReadAllQuery.executeObjectLevelReadQuery() line: 423	
	ReadAllQuery(ObjectLevelReadQuery).executeDatabaseQuery() line: 1074	
	ReadAllQuery(DatabaseQuery).execute(AbstractSession, AbstractRecord) line: 764	
	ReadAllQuery(ObjectLevelReadQuery).execute(AbstractSession, AbstractRecord) line: 1034	
	ReadAllQuery.execute(AbstractSession, AbstractRecord) line: 383	
	ReadAllQuery(ObjectLevelReadQuery).executeInUnitOfWork(UnitOfWorkImpl, AbstractRecord) line: 1112	
	RepeatableWriteUnitOfWork(UnitOfWorkImpl).internalExecuteQuery(DatabaseQuery, AbstractRecord) line: 2910	
	RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord, int) line: 1301	
	RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, AbstractRecord) line: 1283	
	RepeatableWriteUnitOfWork(AbstractSession).executeQuery(DatabaseQuery, List) line: 1257	
	EJBQueryImpl<X>.executeReadQuery() line: 479	
	EJBQueryImpl<X>.getResultList() line: 714	
	JUnitJPQLComplexTestSuite.complexOneToOneFetchJoinTest() line: 1054	
	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	
	JUnitJPQLComplexTestSuite(TestCase).runTest() line: 168	
	JUnitJPQLComplexTestSuite(TestCase).runBare() line: 134	
	JUnitJPQLComplexTestSuite(JUnitTestCase).runBare() line: 466	
	TestResult$1.protect() line: 110	
	TestResult.runProtected(Test, Protectable) line: 128	
	TestResult.run(TestCase) line: 113	
	JUnitJPQLComplexTestSuite(TestCase).run(TestResult) line: 124	
	TestExecutor.execute(Test) line: 248	
	TestExecutor.runTest(Test) line: 671	
	SynchronizedTestExecutor.run() line: 61
Comment 1 Gordon Yorke CLA 2010-08-16 10:30:47 EDT
This appears to be the same bug as :
https://bugs.eclipse.org/bugs/show_bug.cgi?id=262157
Comment 2 Tom Ware CLA 2010-10-06 10:49:36 EDT
It turns out this occurs because the way getWomandId() is written.

If you write the method this way:

   @Column(name="W", insertable=false, updatable=false)
   public Integer getWomanId() {
       return (getWoman() == null) ? null : getWoman().getId();
   }

You are not actually mapping womanId in PartnerLink, you are just using the mapping from Woman and there is no point in the @column annotation.  i.e. How does the @Column annotation change the behavior of that method (other than causing a deadlock).  With or without the @Column, you would expect the method to return the same thing.  Writing the method this way and including @Column is an error in the model.
Comment 3 Eclipse Webmaster CLA 2022-06-09 10:07:16 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink