Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » [Xcore/2] circular dependencies
[Xcore/2] circular dependencies [message #1102266] Thu, 05 September 2013 15:24 Go to next message
Meinte Boersma is currently offline Meinte BoersmaFriend
Messages: 434
Registered: July 2009
Location: Leiden, Netherlands
Senior Member
I know this topic has been discussed here earlier, but Xcore breathes a little bit of new life into it Wink
(After all, Xcore makes creating models productive enough to encounter this kind of stuff again.)

The problem is not really with Xcore, apart from the fact that Xcore doesn't flag the problem.
The actual problem lies with the way the <packageName>PackageImpl are generated: their init() implementations only register the package under the nsURI after full creation, which entails calling initializePackageContents() which may need package instances that haven't been registered at that point in time yet. There are no infinite loops, but the required packages variables may simply be null.

To fix this completely, I think it could be enough that all package instances are registered and their createPackageContents() called before initializePackageContents is called on any of them.


Re: [Xcore/2] circular dependencies [message #1102299 is a reply to message #1102266] Thu, 05 September 2013 16:03 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 31923
Registered: July 2009
Senior Member
Meinte,

I couldn't reproduce such a problem. I have A.xcore

@GenModel(testsDirectory="/abc.tests/src")
package a

import b.B

class A
{
refers B b
}

class C extends B
{
}

and B.xcore

package b

import a.A

class B extends A
{
refers A a
}

In the generated example I write this code:


APackage.eINSTANCE.eResource().save(System.err, null);
BPackage.eINSTANCE.eResource().save(System.err, null);


And it writes out the following, so all seems to be there.

<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="a"
nsURI="a" nsPrefix="a">
<eClassifiers xsi:type="ecore:EClass" name="A">
<eStructuralFeatures xsi:type="ecore:EReference" name="b"
eType="ecore:EClass b#//B"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="C" eSuperTypes="b#//B"/>
</ecore:EPackage>
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="b"
nsURI="b" nsPrefix="b">
<eClassifiers xsi:type="ecore:EClass" name="B" eSuperTypes="a#//A">
<eStructuralFeatures xsi:type="ecore:EReference" name="a"
eType="ecore:EClass a#//A"/>
</eClassifiers>
</ecore:EPackage>

Of course such mutually dependent models need to be hosted in the same
bundle, otherwise the bundles would need to be mutually dependent, which
isn't allowed.

Are you using the Kepler version of Xcore? Is there some scenario I
missed in my example?



On 05/09/2013 5:24 PM, Meinte Boersma wrote:
> I know this topic has been discussed here earlier, but Xcore breathes
> a little bit of new life into it ;)
> (After all, Xcore makes creating models productive enough to encounter
> this kind of stuff again.)
>
> The problem is not really with Xcore, apart from the fact that Xcore
> doesn't flag the problem.
> The actual problem lies with the way the <packageName>PackageImpl are
> generated: their init() implementations only register the package
> under the nsURI after full creation, which entails calling
> initializePackageContents() which may need package instances that
> haven't been registered at that point in time yet. There are no
> infinite loops, but the required packages variables may simply be null.
>
> To fix this completely, I think it could be enough that all package
> instances are registered and their createPackageContents() called
> before initializePackageContents is called on any of them.
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: [Xcore/2] circular dependencies [message #1102353 is a reply to message #1102299] Thu, 05 September 2013 17:22 Go to previous messageGo to next message
Meinte Boersma is currently offline Meinte BoersmaFriend
Messages: 434
Registered: July 2009
Location: Leiden, Netherlands
Senior Member
My code is:
package a
import b.B
class A { contains B b }

package b
import c.C
class B { contains C c }

package c
import a.A
class C { refers A a }

Evaluation of any of the expressions <x>Package.eINSTANCE with x=A, B, or C (see the CircularDependencyTester main class) leads to a NPE.

Could you have a try with this?

Edit1:
(The Eclipse project is attached.)

Edit2:
I'm running on 4.2.2, so that's still Juno. I'll try it after upgrading to 4.3 as well.

Edit3:
Same result on Kepler 4.3.0. I was already running on EMF 2.9.1 (part of latest Xtend release).


[Updated on: Thu, 05 September 2013 17:48]

Report message to a moderator

Re: [Xcore/2] circular dependencies [message #1102386 is a reply to message #1102353] Thu, 05 September 2013 18:09 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 31923
Registered: July 2009
Senior Member
Meinte,

The package initialization code is quite different from that for my
example.

public static BPackage init()
{
if (isInited) return
(BPackage)EPackage.Registry.INSTANCE.getEPackage(BPackage.eNS_URI);

// Obtain or create and register package
BPackageImpl theBPackage =
(BPackageImpl)(EPackage.Registry.INSTANCE.get(eNS_URI) instanceof
BPackageImpl ? EPackage.Registry.INSTANCE.get(eNS_URI) : new
BPackageImpl());

isInited = true;

// Obtain or create and register interdependencies *** This isn't
present in your example &&&
APackageImpl theAPackage =
(APackageImpl)(EPackage.Registry.INSTANCE.getEPackage(APackage.eNS_URI)
instanceof APackageImpl ?
EPackage.Registry.INSTANCE.getEPackage(APackage.eNS_URI) :
APackage.eINSTANCE);


I think it's not recognizing them as co-dependant because it's three-way
circular. Please open a bugzilla and I'll have a closer look at what
needs to be fixed; it should generate code more like the above. (Your
suggestion of registering an incompletely initialized package sounds
like a bad idea; who knows who will gain access to that instance and
suffer failures as a result...


On 05/09/2013 7:22 PM, Meinte Boersma wrote:
> My code is:
>
> package a
> import b.B
> class A { contains B b }
>
> package b
> import c.C
> class B { contains C c }
>
> package c
> import a.A
> class C { refers A a }
>
> Evaluation of any of the expressions <x>Package.eINSTANCE with x=A, B, or C leads to a NPE.
>
> Could you have a try with this? (The Eclipse project is attached.)


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: [Xcore/2] circular dependencies [message #1102405 is a reply to message #1102386] Thu, 05 September 2013 18:32 Go to previous messageGo to next message
Meinte Boersma is currently offline Meinte BoersmaFriend
Messages: 434
Registered: July 2009
Location: Leiden, Netherlands
Senior Member
Done: https://bugs.eclipse.org/bugs/show_bug.cgi?id=416656

You're right: registering unfinished product is probably a recipe for disaster Wink Maybe one could use a "local registry" during construction?


Re: [Xcore/2] circular dependencies [message #1102422 is a reply to message #1102405] Thu, 05 September 2013 18:51 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 31923
Registered: July 2009
Senior Member
Meinte,

I think they just need to be recognized as "InterDependencies" so that
this part is generated:

<%if (!genPackage.getPackageInterDependencies().isEmpty()) {%>
// Obtain or create and register interdependencies
<%for (GenPackage interdep :
genPackage.getPackageInterDependencies()) {%>
<%=interdep.getImportedPackageClassName()%>
<%=genPackage.getPackageInstanceVariable(interdep)%> =
(<%=interdep.getImportedPackageClassName()%>)(<%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.getEPackage(<%=interdep.getImportedPackageInterfaceName()%>.eNS_URI)
instanceof <%=interdep.getImportedPackageClassName()%> ?
<%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.getEPackage(<%=interdep.getImportedPackageInterfaceName()%>.eNS_URI)
: <%=interdep.getImportedPackageInterfaceName()%>.eINSTANCE);
<%}%>

<%}%

That's the case for my simpler example but not for the one you
provided. I'll have a close look and see what's needed...


On 05/09/2013 8:32 PM, Meinte Boersma wrote:
> Done: https://bugs.eclipse.org/bugs/show_bug.cgi?id=416656
>
> You're right: registering unfinished product is probably a recipe for
> disaster ;) Maybe one could use a "local registry" during construction?


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: [Xcore/2] circular dependencies [message #1103008 is a reply to message #1102422] Fri, 06 September 2013 09:38 Go to previous messageGo to next message
Meinte Boersma is currently offline Meinte BoersmaFriend
Messages: 434
Registered: July 2009
Location: Leiden, Netherlands
Senior Member
Great, thanks! Smile

(And I hope the solution will indeed be as simple as triggering that emitter code.)


Re: [Xcore/2] circular dependencies [message #1741563 is a reply to message #1103008] Thu, 25 August 2016 20:37 Go to previous message
Maged Elaasar is currently offline Maged ElaasarFriend
Messages: 23
Registered: September 2013
Junior Member
Has this been fixed? I am running into this issue with cycle dependency in Xcore (I am using the Neon release):
I have the following packages:
package a
import b.B
class A {
   refers B b
}

package b
import a.A
import c.C
class B {
   refers A a
   refers C c
}

package c
import b.B
class C {
   refers B b
}

I get the following code generated when I clean the project that contains the three packages forcing code generation for the three packages.
public static APackage init() {
   ... 
   // Obtain or create and register interdependencies
   BPackageImpl theBPackage = ...

   // Create package meta-data objects
   theAPackage.createPackageContents();
   theBPackage.createPackageContents();

   // Initialize created meta-data
   theAPackage.initializePackageContents();
   theBPackage.initializePackageContents();
   ...
}

public static BPackage init() {
   ...
    // Obtain or create and register interdependencies
   APackageImpl theAPackage = ...
   CPackageImpl theCPackage = ...

   // Create package meta-data objects
   theBPackage.createPackageContents();
   theAPackage.createPackageContents();
   theCPackage.createPackageContents();

   // Initialize created meta-data
   theBPackage.initializePackageContents();
   theAPackage.initializePackageContents();
   theCPackage.initializePackageContents();
   ...
}

public static CPackage init() {
   ...
    // Obtain or create and register interdependencies
   BPackageImpl theBPackage = ...

   // Create package meta-data objects
   theCPackage.createPackageContents();
   theBPackage.createPackageContents();

   // Initialize created meta-data
   theCPackage.initializePackageContents();
   theBPackage.initializePackageContents();
   ...
}

However, if I then do a dummy change to package A and save it, I get package A looking like this (which is more correct):
public static APackage init() {
   ... 
   // Obtain or create and register interdependencies
   BPackageImpl theBPackage = ...
   CPackageImpl theCPackage = ...

   // Create package meta-data objects
   theAPackage.createPackageContents();
   theBPackage.createPackageContents();
   theCPackage.createPackageContents();

   // Initialize created meta-data
   theAPackage.initializePackageContents();
   theBPackage.initializePackageContents();
   theCPackage.initializePackageContents();
   ...
}

However, doing the same to package C does not result in a similar change. What is interesting is that switching the order of properties (a and c) in class B would switch the package that would generate correctly after a resave.

[Updated on: Fri, 26 August 2016 19:29]

Report message to a moderator

Previous Topic:Memory leak with EditingDomainActionBarContributor?
Next Topic:sorting the serialized objects in xml
Goto Forum:
  


Current Time: Fri Jun 25 08:13:21 GMT 2021

Powered by FUDForum. Page generated in 0.01699 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top