Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » EMF resource load - SAXParser loading map twice
EMF resource load - SAXParser loading map twice [message #1826275] Wed, 22 April 2020 14:52 Go to next message
Paul Hennessey is currently offline Paul HennesseyFriend
Messages: 9
Registered: April 2020
Junior Member
Question copied over from Stack Overflow:

I'm having problems with persistence in EMF. The problem occurs when I add an element to a file that contains a map of elements. The process is:

- Load file
- Add element
- Save file

The first time I add an element, it works fine. But if I try to add another, it duplicates the list before adding the new element. All subsequent uses also duplicate the list.

EXAMPLE

I start with a file that looks like this. (The XML is simplified - as a new user, I can't embed links in posts, and it interprets my full XML as links :)

     <primary resources>
        <elements map key="1">
          <value id ="1">
            <keywords tags="foo">
          </value>
        </elements map>
      </primary resources>


If I add a new element, I end up with a file that looks like this, which is correct:

     <primary resources>
        <elements map key="1">
          <value id ="1">
            <keywords tags="foo">
          </value>
        </elements map>
        <elements map key="2">
          <value id ="2">
            <keywords tags="bar">
          </value>
        </elements map>
      </primary resources>


However, if I then add another element, I get this, which is incorrect:

     <primary resources>
        <elements map key="1">
          <value id ="1">
            <keywords tags="foo">
          </value>
        </elements map>
        <elements map key="2">
          <value id ="2">
            <keywords tags="bar">
          </value>
        </elements map>
        <elements map key="1">
          <value id ="1">
            <keywords tags="foo">
          </value>
        </elements map>
        <elements map key="2">
          <value id ="2">
            <keywords tags="bar">
          </value>
        </elements map>
        <elements map key="3">
          <value id ="3">
            <keywords tags="foo">
          </value>
        </elements map>
      </primary resources>


When I debug the code, the problem seems to be happening somewhere in the parser. I'm using the Java SE-11 System library, and the parser is

com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl

Has anyone else had problems like this?
Re: EMF resource load - SAXParser loading map twice [message #1826281 is a reply to message #1826275] Wed, 22 April 2020 18:01 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

That rings a bell. I suspect it is a bug that was fixed recently ? 6 months ago. What version of EMF are you using?

Regards

Ed Willink
Re: EMF resource load - SAXParser loading map twice [message #1826284 is a reply to message #1826281] Wed, 22 April 2020 18:27 Go to previous messageGo to next message
Paul Hennessey is currently offline Paul HennesseyFriend
Messages: 9
Registered: April 2020
Junior Member
Hi Ed - we're using framework version 2.20.0v20191028-0905.
Re: EMF resource load - SAXParser loading map twice [message #1826292 is a reply to message #1826284] Thu, 23 April 2020 04:22 Go to previous messageGo to next message
Ed Merks is currently online Ed MerksFriend
Messages: 33137
Registered: July 2009
Senior Member
No, this doesn't ring a bell. Also, nothing significant has changed in org.eclipse.emf.ecore.xmi in several years. It also seems unlikely that the SAX implementation is buggy in some version of Java.

You mention debugging the parser, but you show XML with "duplicates". At some point did you have XML without duplicates that was loaded in memory and had duplicates at that point in memory? When you saved, and there were no duplicates in memory, did the saved XML itself then contain duplicates at some point? I.e., what specifically did you load without duplicates that had duplicates in memory. Or what specifically did you save that was correct in memory but the resulting saved XML had duplicates. Or perhaps some part of your processing step to add something actually added duplicates...


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: EMF resource load - SAXParser loading map twice [message #1826295 is a reply to message #1826292] Thu, 23 April 2020 05:31 Go to previous messageGo to next message
Paul Hennessey is currently offline Paul HennesseyFriend
Messages: 9
Registered: April 2020
Junior Member
The very first time I load the file, there is no problem. If there are two elements
in the file, I see two elements in memory.

index.php/fa/37917/0/

If I then add a new element, I see three elements in memory. I then save the model, and see three elements in the file.

I then load the file again, and now I see six elements in memory.

index.php/fa/37918/0/

If I add a new element and save, there are now seven elements in the file.
Re: EMF resource load - SAXParser loading map twice [message #1826299 is a reply to message #1826295] Thu, 23 April 2020 07:41 Go to previous messageGo to next message
German Vega is currently offline German VegaFriend
Messages: 104
Registered: December 2015
Location: Grenoble, France
Senior Member
Hello,

What strikes me in your debugging session is that you have two different resources loaded in memory (CoreServicesResourceImpl id=114 and id=186) but they share the same in memory elementsMap (ECoreEmap id=139). So this explains the observed behavior.

The question is how did you end up with two different resources sharing the same elementsMap?

can you share the code of your loadModel() method ?
Re: EMF resource load - SAXParser loading map twice [message #1826300 is a reply to message #1826299] Thu, 23 April 2020 07:53 Go to previous messageGo to next message
Paul Hennessey is currently offline Paul HennesseyFriend
Messages: 9
Registered: April 2020
Junior Member
Ah, I hadn't noticed that.

Here is my LoadModel method:

public CoreServicesResources LoadModel() throws IOException 
{	
    CoreServicesResources coreServicesResources;
    PrimaryResources primaryResources;
		
    ResourceSet resourceSet = new ResourceSetImpl();
    resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("model", new XMIResourceFactoryImpl());
		
    File elements = new File(ResourcesPlugin.getWorkspace().getRoot().getProject(DEFAULT_PROJECT_NAME).getLocationURI().getPath().toString() + "/elements.model");	    
    URI fileURI = URI.createFileURI(elements.getAbsolutePath());				
    Resource resource = resourceSet.createResource(fileURI);	    
	    
    // If there is a model file, load it
    if(resourceSet.getURIConverter().exists(fileURI, null))
    {
        resource.load(null);
        coreServicesResources = (CoreServicesResources)resource.getContents().get(0);			
    }
    else // else construct empty model
    {	    			
        coreServicesResources = CoreFactory.eINSTANCE.createCoreServicesResources();
        primaryResources = CoreFactory.eINSTANCE.createPrimaryResources();	
        coreServicesResources.setPrimaryResources(primaryResources);
    }

    resourceSet.getResources().remove(resource); 	    
    return coreServicesResources;
}
Re: EMF resource load - SAXParser loading map twice [message #1826304 is a reply to message #1826300] Thu, 23 April 2020 08:31 Go to previous messageGo to next message
Ed Merks is currently online Ed MerksFriend
Messages: 33137
Registered: July 2009
Senior Member
Perhaps put a breakpoint in StringToMapElementImpl's construcgtor. Then you will see where instances are all being created, including ones created by the parser right before it adds it to the map. While loading (again?), make sure that the first StringToMapElementImpl instance created while loading and added to the map is being added to an empty map. If your serialization only contains 3 entries you should of course see only three instances created, not 6.

Ed Merks
Professional Support: https://www.macromodeling.com/
Re: EMF resource load - SAXParser loading map twice [message #1826307 is a reply to message #1826300] Thu, 23 April 2020 08:50 Go to previous messageGo to next message
German Vega is currently offline German VegaFriend
Messages: 104
Registered: December 2015
Location: Grenoble, France
Senior Member
Hello,

Well, I have two comments, but they do not seem to be in anyway related to the problem at hand :

1) You seems to be running your code inside an eclipse plugin, why are you registering manually the XMI resource factory in your resource set? Normally the generated factory should be automatically registered in the global registry.

2) why are you using file URIs, instead of platform resources URIs ?. Your model seems to be located in the workspace.

Coming back to the duplicates problem, if the problem doesn't come from the way you load the resource, maybe it is the way you add the elements. I am not familiar with the use of maps in emf models (I personally have never used) but if you want to share your code perhaps a second pair of eyes may help spot some problem.

Otherwise, we better wait for Ed's reactions
Re: EMF resource load - SAXParser loading map twice [message #1826312 is a reply to message #1826304] Thu, 23 April 2020 10:54 Go to previous messageGo to next message
Paul Hennessey is currently offline Paul HennesseyFriend
Messages: 9
Registered: April 2020
Junior Member
Here are the results of another debugging session, this time with a breakpoint in the StringToElementMapImpl constructor, as Ed suggested.

The file contains one element e1.

I load the file, and add element e2. At this point the model in memory looks like this:

index.php/fa/37919/0/

I save the model to file, and then load the file again.

I have a breakpoint inside the StringToElementMapImpl ctor, so I can check to see how the map is looking at this stage. It should be empty, but it is not:

index.php/fa/37920/0/

Interestingly, as German pointed out earlier, although the coreResources object is new, the primaryResources (and the elementsMap inside) have the same id. I don't know why that is - in our model coreResources has an EReference to primaryResources, and the Containment property is set to true.
  • Attachment: snip1.PNG
    (Size: 68.04KB, Downloaded 330 times)
  • Attachment: snip2.PNG
    (Size: 100.41KB, Downloaded 339 times)
Re: EMF resource load - SAXParser loading map twice [message #1826321 is a reply to message #1826312] Thu, 23 April 2020 13:23 Go to previous messageGo to next message
German Vega is currently offline German VegaFriend
Messages: 104
Registered: December 2015
Location: Grenoble, France
Senior Member
Hi Paul,

Your problem sparked my curiosity, so I made a small project trying to recreate your problem, you will find it attached to this post.

For me it is working as expected in EMF 2.20 and 2.21

I defined an ecore model similar to yours ... now I know how maps work in EMF :) .. and added a menu entry to start the test.

just right-click on a project and you will find the menu

index.php/fa/37923/0/

I copied a variation of your code in class test.mypackage.MyHandler, and made my own versions of adding to the map and saving.

Everything seems to be working as expected. Can you test my project in your configuration ?
  • Attachment: testmap.zip
    (Size: 40.85KB, Downloaded 58 times)
  • Attachment: testmap.png
    (Size: 67.87KB, Downloaded 318 times)

[Updated on: Thu, 23 April 2020 13:27]

Report message to a moderator

Re: EMF resource load - SAXParser loading map twice [message #1826322 is a reply to message #1826321] Thu, 23 April 2020 13:42 Go to previous messageGo to next message
Paul Hennessey is currently offline Paul HennesseyFriend
Messages: 9
Registered: April 2020
Junior Member
Thanks German, that's great - I'll let you know how I get on.

Re: EMF resource load - SAXParser loading map twice [message #1826323 is a reply to message #1826321] Thu, 23 April 2020 13:49 Go to previous messageGo to next message
Ed Merks is currently online Ed MerksFriend
Messages: 33137
Registered: July 2009
Senior Member
I would also suggest setting a breakpoint on the constructor of PrimarlyResourcesImpl. A new one should be created during loading. But to me it looks like it's reusing an object from earlier. I.e., it's the same PrimaryResourcesImpl instance, but with a newer CoreServericesResourceImpl as the container. You might override org.eclipse.emf.ecore.impl.MinimalEObjectImpl.eBasicSetContainer(InternalEObject) in PrimaryResourcesImpl temporarily to set a breakpoint there to see when this object is being moved from one container to another.

Ed Merks
Professional Support: https://www.macromodeling.com/
Re: EMF resource load - SAXParser loading map twice [message #1826326 is a reply to message #1826321] Thu, 23 April 2020 14:16 Go to previous messageGo to next message
Paul Hennessey is currently offline Paul HennesseyFriend
Messages: 9
Registered: April 2020
Junior Member
Hi German - I've imported your project into my workspace, but can't see your new menu item - is there something I need to do to enable it?
Re: EMF resource load - SAXParser loading map twice [message #1826328 is a reply to message #1826326] Thu, 23 April 2020 14:31 Go to previous messageGo to next message
German Vega is currently offline German VegaFriend
Messages: 104
Registered: December 2015
Location: Grenoble, France
Senior Member
Hi Paul, there is nothing to do, you will find the menu in the runtime eclipse that you launch for debugging (not in the development eclipse where you imported my project)
Re: EMF resource load - SAXParser loading map twice [message #1826337 is a reply to message #1826328] Thu, 23 April 2020 17:01 Go to previous messageGo to next message
Paul Hennessey is currently offline Paul HennesseyFriend
Messages: 9
Registered: April 2020
Junior Member
Hi German,

Well, your test application works perfectly. I can't see any difference between your model and mine, nor can I see any difference between the code.

Next I need to try Ed's suggestion of putting a break on the primary resources ctor - but that will have to wait for another day.

Thanks for your help today!
Re: EMF resource load - SAXParser loading map twice [message #1826344 is a reply to message #1826337] Thu, 23 April 2020 18:16 Go to previous messageGo to next message
German Vega is currently offline German VegaFriend
Messages: 104
Registered: December 2015
Location: Grenoble, France
Senior Member
Hi Paul,

This is really weird as this is proven emf functionality and I cannot see the problem in your code.

If your project is not private I can take a look at it, just share it here or if you prefer you can contact me privately via https://www.linkedin.com/in/germanvega
Re: EMF resource load - SAXParser loading map twice [message #1826348 is a reply to message #1826344] Thu, 23 April 2020 20:05 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

There is no justification for keeping something so simple private. You just waste all of our time by forcing us to guess at how you have done something interestingly impossible. Please attach a zipped project.

Another hazard that might explain bogus entries is that an EMap is actually an EList and not a Map at all, consequently the API offers the List add and addAll methods that take Map.Entry arguments and check for uniqueness based on the Map.Entry object rather than the Map.Entry key. You should check that no code is accidentally calling add or addAll.

Regards

Ed Willink

Re: EMF resource load - SAXParser loading map twice [message #1826375 is a reply to message #1826348] Fri, 24 April 2020 07:25 Go to previous message
Paul Hennessey is currently offline Paul HennesseyFriend
Messages: 9
Registered: April 2020
Junior Member
Ah - found the problem.

I had originally thought that primaryResources was going to be loaded once and held in memory as a singleton. So to make that happen I overrode createPrimaryResources in CoreFactoryImpl.java. Here's the offending code:

	/**
	 * <!-- begin-user-doc -->
	 * Overridden the default in order to create a singleton.
	 * <!-- end-user-doc --
	 */
	@Override	
	public PrimaryResources createPrimaryResources() {
		if (primaryResources == null) {
			primaryResources = new PrimaryResourcesImpl();
		}
		return primaryResources;
	}


I'd completely forgotten that I'd done that! It wasn't until I started putting breakpoints around the PrimaryResources constructor that I found it again. I deleted my method, regenerated the code and now everything's fine.

Many thanks to everyone for taking the time to help me out with this, I really appreciate it.
Previous Topic:How to 'force' loading of uml resource with incorrect reference
Next Topic:ECore model evolution and versioning
Goto Forum:
  


Current Time: Fri Apr 19 09:13:10 GMT 2024

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

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

Back to the top