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

Bug 320837

Summary: [Legacy] Legacy fails when loading a contained object before its container
Product: [Modeling] EMF Reporter: Martin Fluegge <martin.fluegge>
Component: cdo.legacyAssignee: Martin Fluegge <martin.fluegge>
Status: CLOSED FIXED QA Contact: Eike Stepper <stepper>
Severity: normal    
Priority: P3 Flags: stepper: review+
Version: 4.0   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
Test v1
none
Patch v1
none
Test+Fix v2 - ready to be committed
none
Test+Fix v3 - ready to be committed none

Description Martin Fluegge CLA 2010-07-25 04:44:14 EDT
When loading a contained object before ist container legacy crashes with the following exception:


java.lang.IllegalStateException: Failing event PREPARE in state CLEAN for CDOLegacyWrapper[OID3, org.eclipse.emf.cdo.tests.legacy.model4.impl.ContainedElementNoOppositeImpl] (data=Pair[CDOTransaction[3:1], []])
	at org.eclipse.net4j.util.fsm.FiniteStateMachine.process(FiniteStateMachine.java:153)
	at org.eclipse.emf.internal.cdo.CDOStateMachine.prepare(CDOStateMachine.java:229)
	at org.eclipse.emf.internal.cdo.CDOStateMachine.attach(CDOStateMachine.java:191)
	at org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl.attached(CDOResourceImpl.java:827)
	at org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl.attached(CDOResourceImpl.java:818)
	at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eBasicSetContainer(BasicEObjectImpl.java:1342)
	at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eInverseAdd(BasicEObjectImpl.java:1423)
	at org.eclipse.emf.cdo.tests.legacy.model4.impl.RefSingleContainedNPLImpl.setElement(RefSingleContainedNPLImpl.java:121)
	at org.eclipse.emf.cdo.tests.legacy.model4.impl.RefSingleContainedNPLImpl.eSet(RefSingleContainedNPLImpl.java:180)
	at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eSet(BasicEObjectImpl.java:1081)
	at org.eclipse.emf.internal.cdo.CDOLegacyWrapper.revisionToInstanceFeature(CDOLegacyWrapper.java:554)
	at org.eclipse.emf.internal.cdo.CDOLegacyWrapper.revisionToInstance(CDOLegacyWrapper.java:423)
	at org.eclipse.emf.internal.cdo.CDOLegacyWrapper.cdoInternalPostLoad(CDOLegacyWrapper.java:298)
	at org.eclipse.emf.internal.cdo.view.CDOViewImpl.cleanObject(CDOViewImpl.java:1179)
	at org.eclipse.emf.internal.cdo.view.CDOViewImpl.createObject(CDOViewImpl.java:1130)
	at org.eclipse.emf.internal.cdo.view.CDOViewImpl.getObject(CDOViewImpl.java:1005)
	at org.eclipse.emf.internal.cdo.transaction.CDOTransactionImpl.getObject(CDOTransactionImpl.java:878)
	at org.eclipse.emf.internal.cdo.transaction.CDOTransactionImpl.getObject(CDOTransactionImpl.java:1)
	at org.eclipse.emf.internal.cdo.CDOLegacyWrapper.getEObjectFromPotentialID(CDOLegacyWrapper.java:796)
	at org.eclipse.emf.internal.cdo.CDOLegacyWrapper.revisionToInstanceContainment(CDOLegacyWrapper.java:456)
	at org.eclipse.emf.internal.cdo.CDOLegacyWrapper.revisionToInstance(CDOLegacyWrapper.java:419)
	at org.eclipse.emf.internal.cdo.CDOLegacyWrapper.cdoInternalPostLoad(CDOLegacyWrapper.java:298)
	at org.eclipse.emf.internal.cdo.view.CDOViewImpl.cleanObject(CDOViewImpl.java:1179)
	at org.eclipse.emf.internal.cdo.view.CDOViewImpl.createObject(CDOViewImpl.java:1130)
	at org.eclipse.emf.internal.cdo.view.CDOViewImpl.getObject(CDOViewImpl.java:1005)
	at org.eclipse.emf.internal.cdo.transaction.CDOTransactionImpl.getObject(CDOTransactionImpl.java:878)
	at org.eclipse.emf.internal.cdo.view.CDOViewImpl.getObject(CDOViewImpl.java:1048)
	at org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_320690_Tests.testLockRefTargets(Bugzilla_320690_Tests.java:60)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at junit.framework.TestCase.runTest(TestCase.java:168)
	at org.eclipse.net4j.util.tests.AbstractOMTest.runBare(AbstractOMTest.java:150)
	at org.eclipse.emf.cdo.tests.config.impl.ConfigTest.runBare(ConfigTest.java:422)
	at junit.framework.TestResult$1.protect(TestResult.java:110)
	at junit.framework.TestResult.runProtected(TestResult.java:128)
	at junit.framework.TestResult.run(TestResult.java:113)
	at junit.framework.TestCase.run(TestCase.java:124)
	at org.eclipse.net4j.util.tests.AbstractOMTest.run(AbstractOMTest.java:196)
	at junit.framework.TestSuite.runTest(TestSuite.java:232)
	at org.eclipse.emf.cdo.tests.config.impl.ConfigTestSuite$TestWrapper.runTest(ConfigTestSuite.java:126)
	at junit.framework.TestSuite.run(TestSuite.java:227)
	at junit.framework.TestSuite.runTest(TestSuite.java:232)
	at junit.framework.TestSuite.run(TestSuite.java:227)
	at junit.framework.TestSuite.runTest(TestSuite.java:232)
	at junit.framework.TestSuite.run(TestSuite.java:227)
	at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)


I ran through the problem and it seems that the caus of the problem can be described as follows:

If the contained element is loaded, the wrapper will be created by CDO, set to state CLEAN and afterwards cdoInternalPostLoad() will be called which sets the information from the revision to the instance. 

Thereby the container of the element is set. This lead to a creation of the container object, which itself transforms the revision data to its instance. This leads to setting the contained object to its related feature in the container.

At this point the contained elements resource is null wherefore it will be attached to the containers resource (BasicEObjectImpl, 1342). This results in attaching the object to the CDOResource and processing an ATTACH operation in the CDOStateMachine. Remember that the contained object which should be attached to the resource it already in state CLEAN. So, the state machine denies preparing it. 

This does not happen if the container is loaded before, because the contained object will be created during the containers creation.
Comment 1 Martin Fluegge CLA 2010-07-25 09:19:48 EDT
Created attachment 175174 [details]
Test v1

Here is a small test to reproduce the problem.
Comment 2 Martin Fluegge CLA 2010-07-25 10:31:06 EDT
Created attachment 175176 [details]
Patch v1

Split seconds before my head was going to explode I found the solution. 

Feels like I have an unlimited number of containment cycles in my head. 

Here is the patch?

And now it?s Time for a nap ;)
Comment 3 Eike Stepper CLA 2010-07-25 11:57:19 EDT
Created attachment 175177 [details]
Test+Fix v2 - ready to be committed
Comment 4 Eike Stepper CLA 2010-07-25 12:25:20 EDT
Created attachment 175178 [details]
Test+Fix v3 - ready to be committed
Comment 5 Martin Fluegge CLA 2010-07-25 13:06:49 EDT
Committed to HEAD.
Comment 6 Eike Stepper CLA 2011-06-23 03:41:52 EDT
Available in R20110608-1407