| Summary: | InvalidURI when loading non-existing resource from a resource set on demand | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [Modeling] EMF | Reporter: | Martin Fluegge <martin.fluegge> | ||||
| Component: | cdo.core | Assignee: | Project Inbox <emf.cdo-inbox> | ||||
| Status: | CLOSED WORKSFORME | QA Contact: | |||||
| Severity: | normal | ||||||
| Priority: | P1 | CC: | Ed.Merks, stepper | ||||
| Version: | 4.1 | ||||||
| Target Milestone: | --- | ||||||
| Hardware: | PC | ||||||
| OS: | Windows XP | ||||||
| Whiteboard: | |||||||
| Attachments: |
|
||||||
Created attachment 205249 [details]
Test v1
Attached a patch to reprocude the problem.
(In reply to comment #0) > Given the following URI: cdo://repo1/test1" the following call should create the > resource and return it: > > Resource resource = > resourceSet.getResource(URI.createURI("cdo://repo1/test1"), true); With createResource() you could expect that behaviour. With getResource() you must expect an exception if it doesn't exist, yet. The java doc from ResourceSetImpl "A resource set is expected to implement the following strategy in order to resolve the given URI to a resource. First it uses it's URI converter to normalize the URI and then to compare it with the normalized URI of each resource; if it finds a match, that resource becomes the result. Failing that, it delegates to allow the URI to be resolved elsewhere. For example, the package registry is used to resolve the namespace URI of a package to the static instance of that package. So the important point is that an arbitrary implementation may resolve the URI to any resource, not necessarily to one contained by this particular resource set. If the delegation step fails to provide a result, and if loadOnDemand is true, a resource is created and that resource becomes the result. *If loadOnDemand is true and the result resource is not loaded, it will be loaded before it is returned.*" With the current implementation we prevent the ResourceSet implementation from working correctly. From my point of view this is a serious issue. That's why I re-opened the bug. I think there is a bit more discussion or input need before closing this ;) Bummer! I should have read the docs. Since when I started to use EMF I've wondered what "loadOnDemand" means for getResource() and I've always ignored it because I cuold not make a sense of it. BTW. nobody has complained in 8 years of CDO! But you seem to be right, we should fallback to createResource(uri) if getResource(uri, false) would return null. And we should ask EMF why the parameter is not called "createOnDemand". If the resource set contains a resource that's already created but not yet loaded then it will be loaded during this process. Also keep in mind that creating a resource doesn't load it, so while you might argue to call it createAndLoadOnDemand or loadOrCreateAndLoadOnDemand, you can't really argue it should just be called createOnDemand... Oh my goodness! That beast should have been made a bit field or a number of boolean parameters ;-( Martin, I think you're misreading this last sentence: If loadOnDemand is true and the result resource is not loaded, it will be loaded before it is returned. This last step will (should) fail if the resource doesn't actually exist in the backing store. Of course the resource will exist in the resource set at this point, but it will have failed to load and the getErrors() will contain the reason(s) why. Ed, thanks for the clarification! Martin, with this information I think we can close this bug. Hi guys, I must admit that I somehow mixed some things because the creation process of a CDOResource was not 100% clear to me. Now I have learned that the CDOResourceFactoryImpl only creates an in-memory instance of a CDOResource which has no counterpart on the server site. I wrongly assummed that this should happens while the resource is created and thus was confused about the exception. Now the exception makes sense, since the resource in not yet created on the server site and the server cannot load it from the store. After discussion with Eike we came to the conclusion that it would be better to create the new CDOResource’s counterpart on the server site while the CDOResource is created. Thus the loading would not fail, because the resource already exists. As a result porting code from existing resource implementations to CDO would be easier for customer. Because this bug started with some confusion, Eike asked me to open a new bug for tracking the change of the creation process. Since his wish is my command, I filed Bug 361501 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=361501) ;) (In reply to comment #9) > After discussion with Eike we came to the conclusion that it would be better to > create the new CDOResource’s counterpart on the server site while the > CDOResource is created. I did emphasize on the opposite! To make it clear again: - createResource() is absolutely okay as it is. - getResource(uri, true) is currently not working as documented in the ResorceSet contract. Instead of *creating* a new *in-memory* resource and *not* loading it we're throwing an exception. *this* we may decide to change (although nobody ever complained about it). Not sure about the last comment... getResource(URI, true) should look for a resource already in the resource set, call it x if it's there. Failing that it should create a new resource call x. In either case, if that resource x isn't loaded, there should be an attempt to load it, which should fail if there is no underlying resource in the backing store. getResource(URI, true) should not create a new resource in the backing store. Only resource.save should do that. So creating a new resource involves creating a new in-memory one (using ResourceSet.create or a factory and adding it), populating it, and then calling save. Closing. |
Given the following URI: cdo://repo1/test1" the following call should create the resource and return it: Resource resource = resourceSet.getResource(URI.createURI("cdo://repo1/test1"), true); But instead the following exception is thrown: [ERROR] Invalid URI "cdo://repo1/test1": org.eclipse.emf.cdo.common.util.CDOException: No top level ResourceNode with the name test1 org.eclipse.emf.cdo.util.InvalidURIException: Invalid URI "cdo://repo1/test1": org.eclipse.emf.cdo.common.util.CDOException: No top level ResourceNode with the name test1 at org.eclipse.emf.internal.cdo.view.AbstractCDOView.registerProxyResource(AbstractCDOView.java:1071) at org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl.registerProxy(CDOResourceImpl.java:980) at org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl.load(CDOResourceImpl.java:904) at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLoad(ResourceSetImpl.java:255) at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLoadHelper(ResourceSetImpl.java:270) at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getResource(ResourceSetImpl.java:397) at org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_XXX_Test.testInvalidationNotification(Bugzilla_XXX_Test.java:38) 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:218) at org.eclipse.emf.cdo.tests.config.impl.ConfigTest.runBare(ConfigTest.java:526) 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:264) at junit.framework.TestSuite.runTest(TestSuite.java:243) at org.eclipse.emf.cdo.tests.config.impl.ConfigTestSuite$TestWrapper.runTest(ConfigTestSuite.java:119) at junit.framework.TestSuite.run(TestSuite.java:238) at junit.framework.TestSuite.runTest(TestSuite.java:243) at junit.framework.TestSuite.run(TestSuite.java:238) at junit.framework.TestSuite.runTest(TestSuite.java:243) at junit.framework.TestSuite.run(TestSuite.java:238) at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130) 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) Caused by: org.eclipse.emf.cdo.common.util.CDOException: No top level ResourceNode with the name test1 at org.eclipse.emf.internal.cdo.view.AbstractCDOView.getRootOrTopLevelResourceNodeID(AbstractCDOView.java:441) at org.eclipse.emf.internal.cdo.transaction.CDOTransactionImpl.getRootOrTopLevelResourceNodeID(CDOTransactionImpl.java:1025) at org.eclipse.emf.internal.cdo.view.AbstractCDOView.getResourceNodeID(AbstractCDOView.java:396) at org.eclipse.emf.internal.cdo.view.AbstractCDOView.getResourceNodeIDChecked(AbstractCDOView.java:363) at org.eclipse.emf.internal.cdo.view.AbstractCDOView.getResourceNodeID(AbstractCDOView.java:351) at org.eclipse.emf.internal.cdo.view.AbstractCDOView.registerProxyResource(AbstractCDOView.java:1060) ... 31 more