Community
Participate
Working Groups
Hi, i encounter some NPE with GenOperationImpl.isInvariant() method when unloading UML.genmodel resource from my ResourceSet. I tried to isolate in some simple code a way to reproduce the problem : see attached action code which loads the files UML.ecore & UML.genmodel in a ResourceSet and then unload them. The attached code does not give exactly the NullPointerException we got in our context (not at the same line of isInvariant() : line 1062, see bug 318391), but the cause is the same : related UML.ecore EObjects have been proxified. Of course, unloading UML.genmodel before UML.ecore avoids the issue in related attached code. But is it a wrong path to use the opposite order ? Thanks, Fabien.
Created attachment 175796 [details] Related code
Created attachment 175797 [details] related stack trace
The stack trace seeems to implicate a broken promise in the Ecore API somewhere. The documentation for org.eclipse.emf.ecore.resource.Resource.getURIFragment(EObject) says: * Returns the URI {@link URI#fragment fragment} that, * when passed to {@link #getEObject getEObject} will return the given object. * <p> * In other words, * the following is <code>true</code> for any object contained by a resource: *<pre> * Resource resource = eObject.eResource(); * eObject == resource.getEObject(resource.getURIFragment(eObject)) *</pre> In this case, the eobject argument is a proxy for an eobject defined in a resource that is no longer there. What possible value other than null could Resource.getURIFragment() return? At minimum, the answer should be clearly spelled out in the javadoc API. Although EMF itself is robust w.r.t. proxies, other EMF-based frameworks like EMF's genmodel/codegen may not be with downstream implications for other derivative frameworks like UML2's codegen. The stack trace clearly corroborates this point, see: org.eclipse.emf.codegen.ecore.genmodel.impl.GenTypedElementImpl.isEObjectType() EClassifier type = getEcoreTypedElement().getEType(); return type instanceof EClass && findGenClass((EClass)type).isEObject(); // GenTypeElementImpl, line 450 GenTypedElementImpl.getECoreTypedElement() is defined to return an ETypedElement; clearly this precludes returning InternalEObject proxies. It seems unreasonable to me to ask the EMF folks to make the genmodel/codegen frameworks robust for the case where a *.genmodel resource is in memory but its *.ecore resource is unloaded. It would be nice if the EMF Resource API supported the notion of resource dependencies, particularly w.r.t. respecting the order in which they have to be unloaded or at least clearly indicated in the API that this must be done in client frameworks/applications that use EMF.
(In reply to comment #3) > It seems unreasonable to me to ask the EMF folks to make the genmodel/codegen > frameworks robust for the case where a *.genmodel resource is in memory but its > *.ecore resource is unloaded. I'm not sure how unreasonable it is; adding a guard to avoid this case wouldn't be a bad idea... In any case, if this issue is to be fixed, EMF is the place to do it.
If if the name this produces really depends on things that can't be known anymore because the Ecore model is unloaded, adding a guard will just produce a wrong result for isInvariant in some cases and hence produce a wrong proxy, won't it?
(In reply to comment #5) > If if the name this produces really depends on things that can't be known > anymore because the Ecore model is unloaded, adding a guard will just produce a > wrong result for isInvariant in some cases and hence produce a wrong proxy, > won't it? Hmm, good point. In hindsight, I suppose the URI fragment for operations should not be based on information from another model (an unintended side-effect of the override in UML2). Unfortunately, I can't think of a way to work around this in UML2 without potentially breaking references from other UML2 generator models...
The GenModel doesn't contain useful identifying information that could be used for improved (less fragile) fragments. Relying on the Ecore model isn't a big problem even when unloading it first because the names in the Ecore model will still be available. The bottom line though is there's not much I can do for this bugzilla, other than to have another version of getName that UML2 doesn't override to rely on more complex navigation...
Given that a change in the base code would just mask the problem (return the wrong value which would produce the wrong name in UML) it seems better to fail and then to ensure that the genmodel itself is unloaded before the Ecore model it references.
Ok, we will take it in account in related 318391.