Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF "Technology" (Ecore Tools, EMFatic, etc)  » [EMFStore] Sharing same EditingDomain between Eclipse Workspace and EMFStore Workspace(Experiencing problem with differing CommandStacks)
[EMFStore] Sharing same EditingDomain between Eclipse Workspace and EMFStore Workspace [message #1759424] Tue, 11 April 2017 15:22 Go to next message
Christopher Doane is currently offline Christopher DoaneFriend
Messages: 5
Registered: April 2017
Junior Member
Hi!

We are integrating EMFStore as a plugin to a customized version of Eclipse to add version control support for model-instances on a model-level instead of using our current workflow of utilizing textual-based version control systems like GIT to handle versioning of models. EMFStore appears to be a perfect candidate for this, and seems to be well built.

It seems that a common way of using EMFStore is to use the generated editor with Eclipse Client Platform to add and modify model elements directly inside EMFStore using the model API. We would like however to be able to use an external customized editor to make changes and only handle version control in EMFStore.

We previously were loading in the model from an xmi/xml file by creating a new resource for the file and taking out the root eobject of the model instance and adding it to a localproject. As shown in http:// eclipsesource.com/blogs/tutorials/emfstore-api-basics/ with localProject.getModelElements().add(rootEObject). This works great in terms of adding a serialized version of a model to EMFStore, yet since EMFStore seems to track changes done to the model through the model API, this makes EMFStore think that we have added an entirely new model every time we load from the serialized file (which makes sense as we create a new resource each time).

We then realized one could instead maybe share the same EditingDomain between the Eclipse Workspace and EMFStore's workspace and thus when a change occurs to EObjects in the external (external to EMFStore) model instance editor in Eclipse, then the change would also occur on EMFStore's model instance as these would be one and the same.

Some Background:

We first naively created a localproject from our EMFStore's workspace and then set the ESWorkspaceProviderImpl's EditingDomain to Eclipse's workspace one:

ESWorkspace workspace = ESWorkSpaceProvider.INSTANCE.getWorkspace();
workspace.addServer(server);
ESLocalProject _localProject = workspace.createLocalProject("Test localProject"); // we later move this to after the next line
TransactionalEditingDomain editingDomain = WorkspaceEditingDomainUtil.getAllEditingDomains().iterator().next();
ESWorkspaceProviderImpl.getInstance().setEditingDomain(editingDomain);

TransactionalEditingDomain storeEditingDomain = (TransactionalEditingDomain) ESWorkspaceProviderImpl.getInstance().getEditingDomain();
Resource resource = storeEditingDomain.getResourceSet().getResources().get(1);

Custom ar = (Custom)resource.getContents().get(0);
EObject rootPkg = ar.FetchArPackages().get(0);
... 
WorkspaceTransactionUtil.executeInWriteTransaction( storeEditingDomain,
	new Runnable() {
		@Override
		public void run() {									 		_localProject.getModelElements().add(rootPkg); 
		}
	}, "Loaded model instance in EMFStore local project from shared EditingDomain.");


This however resulted in our EObjects dissapearing from our custom model instance navigator and appearing in a TreeViewer where we display the contents of the _localProject in EMFStore. This showed that there were two EditingDomains as it seems that the same Resource contents can not be in two different EditingDomains at the same time (we might be wrong about this). We could see that there were two different EditingDomains by printing out and comparing it to the one now set in ESWorkspaceProviderImpl with:

AdapterFactoryEditingDomain.getEditingDomainFor(_localProject.getAllModelElements().iterator().next()).hashCode();


End Background.

So now we swap out EMFStore's workspace's EditingDomain before we create a new local project (so as to make sure localProject has the same EditingDomain as everything else), and when we go to add the root EObject from the shared EditingDomain (as shown above) we get the error in ProjectSpaceBase.init that we cannot cast the ExtendedWorkspaceEditingDomainFactory's EditingDomain's CommandStack to an ESCommandStack.

A small subset of the exception log:

java.lang.ClassCastException: org.eclipse.sphinx.emf.workspace.domain.factory.ExtendedWorkspaceEditingDomainFactory$1 cannot be cast to org.eclipse.emf.emfstore.client.changetracking.ESCommandStack 
at org.eclipse.emf.emfstore.internal.client.model.impl.ProjectSpaceBase.init(ProjectSpaceBase.java:652) 
at org.eclipse.emf.emfstore.internal.client.model.impl.ProjectSpaceBase.initResources(ProjectSpaceBase.java:887)
at org.eclipse.emf.emfstore.internal.client.model.impl.WorkspaceBase.createLocalProject(WorkspaceBase.java:109)


This makes sense as well, since we are now using the EditingDomain from Eclipse's workspace and its CommandStack does not implement ESCommandStack.

The problem:

This is where our problem lies, that we want to share the same EditingDomain between Eclipse and EMFStore so that the model instances are one and the same. Any changes to the model instance in the external editor will hopefully be detected in EMFStore as they share the same EditingDomain and Resources. The problem (we think) is that the CommandStacks are different, and one cannot simply change out the EditingDomain of ESWorkspaceProvider without making sure it implements ESCommandStack.

Our instinct is to create a new CommandStack that combines the functionality of both WorkspaceCommandStackImpl located in the org.eclipse.emf.workspace.impl package (http:// download.eclipse.org/modeling/emf/transaction/javadoc/workspace/1.2.1/org/eclipse/emf/workspace/impl/WorkspaceCommandStackImpl.html) with the functionality of EMFStoreTransactionalCommandStack located in the org.eclipse.emf.emfstore.internal.client.transaction package (http:// download.eclipse.org/emfstore/releases_18/javadoc/org/eclipse/emf/emfstore/internal/client/transaction/EMFStoreTransactionalCommandStack.html).

The problem is (from what we can gather) is that Eclipse or the custom version of Eclipse that we are adding to uses the WorkspaceEditingDomainUtil located in the org.eclipse.sphinx.emf.util package (http:// download.eclipse.org/sphinx/previews/javadoc/org/eclipse/sphinx/emf/util/WorkspaceEditingDomainUtil.html) to create an ExtendedWorkspaceEditingDomain (located in ExtendedWorkspaceEditingDomainFactory in the org.eclipse.sphinx.emf.workspace.domain.factorypackage) (http:// download.eclipse.org/sphinx/previews/javadoc/org/eclipse/sphinx/emf/workspace/domain/factory/ExtendedWorkspaceEditingDomainFactory.html) that is currently being used across everything. We only have access to the .class files of sphinx as of yet, and even if we were to get the source, the WorkspaceEditingDomainUtil class is labeled as final and coupled to other sphinx components.

Questions:

Is there any chance we could get some hints or help as to how we should go about sharing the same EditingDomain between Eclipse and EMFStore?

Is there a better way to share the same model instances between a model instance editor in Eclipse and EMFStore's Workspace's local project?

A second alternative:

We were also pondering the idea of maybe instead having two different EditingDomains: one for Eclipse and one for EMFStore. We would then attach a CommandStackListener to Eclipse's EditingDomain to trigger when a Command or change to the model instance occurred and then somehow mirror this change in the EditingDomain used in EMFStore.. however we are not sure about how to go about this yet. A thought is to do something like the following:

eclipseEditingDomain.getCommandStack().addCommandStackListener(new CommandStackListener(){
  @Override
  public void commandStackChanged(EventObject event) {
	Command recentcommand = ((CommandStack) event.getSource()).getMostRecentCommand();
	IWorkspaceCommandStack emfStoreCommandStack = (IWorkspaceCommandStack) emfStoreEditingDomain.getCommandStack(); // probably not right
	emfStoreCommandStack.execute(recentcommand);
	}			
});


We have not worked much with the second alternative as we would ideally prefer to instead share the same EditingDomain and CommandStack.

Any help would be greatly appreciated!

Friendly Regards,
Christopher Doane
Re: [EMFStore] Sharing same EditingDomain between Eclipse Workspace and EMFStore Workspace [message #1759774 is a reply to message #1759424] Tue, 18 April 2017 11:45 Go to previous messageGo to next message
Edgar Mueller is currently offline Edgar MuellerFriend
Messages: 17
Registered: March 2016
Junior Member
Hi Christopher,

thanks for detailed explanation. Do you actually need emfstore transaction support? If not, wouldn't it be possible to implement your own CommandStack/EditingDomain analogously to the one we provide in the org.eclipse.emf.emfstore.client.transaction bundle, i.e. create classes that implement ESEditingDomainProvider and ESCommandStack (+ extension point registration) and within the implementation of the necessary methods then delegate to the respective counterparts of sphinx instead of inheriting from them? Or did I miss something here?

Cheers,
Edgar
Re: [EMFStore] Sharing same EditingDomain between Eclipse Workspace and EMFStore Workspace [message #1759941 is a reply to message #1759774] Thu, 20 April 2017 08:27 Go to previous messageGo to next message
Christopher Doane is currently offline Christopher DoaneFriend
Messages: 5
Registered: April 2017
Junior Member
Hi Edgar!

Thanks for the reply!

Yes in theory that should work.

We were working on mirroring Commands on both the Eclipse's EditingDomain and EMFStore's EditingDomain (the second idea of keeping two separate domains) just before we received your message. We do this by adding an EContentAdapter to the model instance Resource that we want EMFStore to version. Then we override notifyChanged and find the position of the effected EObject in the Eclipse EObject hierarchy and then create a Command (ex: AddCommand, RemoveCommand, SetCommand, etc) that we then perform on the corresponding EObject located in the same position in the EObject hierarchy in EMFStore.

We now have some basic support for adds, however this is turning out to be a bunch of code to implement support for every Command. So we will instead focus on what you have named above.

We are working on swapping out where WorkspaceEditingDomainManager (http:// download.eclipse.org/sphinx/updates/0.9.x/javadoc/org/eclipse/sphinx/emf/workspace/domain/WorkspaceEditingDomainManager.html) and ExtendedWorkspaceEditingDomainFactory (http:// download.eclipse.org/sphinx/previews/javadoc/org/eclipse/sphinx/emf/workspace/domain/factory/ExtendedWorkspaceEditingDomainFactory.html) from Sphinx is used and called upon with our own implementations, and delegate like you say. We have also implemented a CommandStack that now implements ESCommandStack and should contain the functionality of the other CommandStack previously used in Eclipse.

Exactly where the globally used EditingDomain is created in Eclipse is proving to be a bit mysterious to us. We think that it may be fetched with WorkspaceEditingDomainManager's getEditingDomainMapping (which we are now swapping out), and suspect that it is created within DefaultWorkspaceEditingDomainMapping's createEditingDomain (http:// download.eclipse.org/sphinx/previews/javadoc/org/eclipse/sphinx/emf/workspace/domain/mapping/DefaultWorkspaceEditingDomainMapping.html).

[removed on edit]

Otherwise, I will get back to you with more details as we continue to work. I think we are on the right path but request that this thread be kept open till we have figured it out. Will post again if there are additional questions or when we are able to solve it.

Edit: We were able to identify where the global EditingDomain was created within the custom Eclipse application. We are now working with registering our editingDomainProvider in EMFStore. We have added our new class as an extension to our plugin and specify its class field to the location of our java file (plugin.xml -> extensions -> add -> org. eclipse.emf.emfstore.client.editingDomainProvider -> class*: our. class.location). We got the following Exception on any code that uses EMFStore's workspace:

Workspace Initialization failed, shutting down
java.lang.NullPointerException
	at org.eclipse.emf.emfstore.internal.client.model.util.AbstractEMFStoreCommand.aRun(AbstractEMFStoreCommand.java:108)
	at org.eclipse.emf.emfstore.internal.client.model.util.EMFStoreCommand.run(EMFStoreCommand.java:60)
	at org.eclipse.emf.emfstore.client.util.RunESCommand.run(RunESCommand.java:145)
	at org.eclipse.emf.emfstore.internal.client.model.ESWorkspaceProviderImpl.load(ESWorkspaceProviderImpl.java:334)
	at org.eclipse.emf.emfstore.internal.client.model.ESWorkspaceProviderImpl.initialize(ESWorkspaceProviderImpl.java:522)
	at org.eclipse.emf.emfstore.internal.client.model.ESWorkspaceProviderImpl.getInstance(ESWorkspaceProviderImpl.java:177)
	at org.eclipse.emf.emfstore.client.ESWorkspaceProvider.<clinit>(ESWorkspaceProvider.java:32)
	at org.eclipse.emf.emfstore.internal.client.model.impl.api.ESServerImpl.login(ESServerImpl.java:230)
	at com.arccore.versioncontrol.model.VCEngine.loginLocalEMFStore(VCEngine.java:689)
	at com.arccore.versioncontrol.model.VCEngine.initLocalEMFStore(VCEngine.java:179)
	at com.arccore.versioncontrol.model.VCModelView$2.handleEvent(VCModelView.java:118)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4353)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1061)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4172)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3761)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1151)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1032)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:148)
	at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:636)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:579)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:135)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:380)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:235)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:648)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:603)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1465)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1438)


Edit Edit: We were able to identify why we were unable to initialize an EMFStore Workspace. We had to create a resourceSetProvider (+ register it) as well that fetched the correct resourceSet from the Workspace used in Eclipse so that the custom editingDomainProvider implementation would work. So the above is now solved. We now share the same EditingDomain and CommandStack between both Eclipse and EMFStore, which is great.

We now experience the following Exception when attempting to share our ESLocalProject with the local EMFStore ESServer:

Sharing Project:..java.lang.RuntimeException: Save of resource emfstore://workspaces/default/projectspaces/_gwhFgCaGEeec4rqw9fgcPQ/projectspace failed.
	at org.eclipse.emf.emfstore.internal.client.model.impl.ResourcePersister.saveDirtyResources(ResourcePersister.java:181)
	at org.eclipse.emf.emfstore.internal.client.model.impl.ProjectSpaceBase.save(ProjectSpaceBase.java:1267)
	at org.eclipse.emf.emfstore.internal.client.model.controller.ShareController.run(ShareController.java:89)
	at org.eclipse.emf.emfstore.internal.client.model.controller.ShareController.run(ShareController.java:1)
	at org.eclipse.emf.emfstore.internal.client.model.connectionmanager.ServerCall.run(ServerCall.java:249)
	at org.eclipse.emf.emfstore.internal.client.model.connectionmanager.SessionManager.executeCall(SessionManager.java:149)
	at org.eclipse.emf.emfstore.internal.client.model.connectionmanager.SessionManager.execute(SessionManager.java:68)
	at org.eclipse.emf.emfstore.internal.client.model.connectionmanager.ServerCall.execute(ServerCall.java:269)
	at org.eclipse.emf.emfstore.internal.client.model.impl.ProjectSpaceBase.shareProject(ProjectSpaceBase.java:1370)
	at org.eclipse.emf.emfstore.internal.client.model.impl.api.ESLocalProjectImpl$20.call(ESLocalProjectImpl.java:607)
	at org.eclipse.emf.emfstore.internal.client.model.impl.api.ESLocalProjectImpl$20.call(ESLocalProjectImpl.java:1)
	at org.eclipse.emf.emfstore.client.util.RunESCommand$WithException$1.doRun(RunESCommand.java:61)
	at org.eclipse.emf.emfstore.internal.client.model.util.EMFStoreCommandWithResult.commandBody(EMFStoreCommandWithResult.java:31)
	at org.eclipse.emf.emfstore.internal.client.model.util.AbstractEMFStoreCommand.execute(AbstractEMFStoreCommand.java:64)
	at org.eclipse.emf.workspace.EMFCommandOperation.doExecute(EMFCommandOperation.java:119)
	at org.eclipse.emf.workspace.AbstractEMFOperation.execute(AbstractEMFOperation.java:150)
	at org.eclipse.core.commands.operations.DefaultOperationHistory.execute(DefaultOperationHistory.java:513)
	at org.eclipse.emf.workspace.impl.WorkspaceCommandStackImpl.doExecute(WorkspaceCommandStackImpl.java:208)
	at org.eclipse.emf.transaction.impl.AbstractTransactionalCommandStack.execute(AbstractTransactionalCommandStack.java:165)
	at com.arccore.versioncontrol.model.VCExtendedWorkspaceEditingDomainFactory$1.execute(VCExtendedWorkspaceEditingDomainFactory.java:60)
	at org.eclipse.emf.emfstore.internal.client.model.util.AbstractEMFStoreCommand.aRun(AbstractEMFStoreCommand.java:108)
	at org.eclipse.emf.emfstore.internal.client.model.util.EMFStoreCommandWithResult.run(EMFStoreCommandWithResult.java:59)
	at org.eclipse.emf.emfstore.client.util.RunESCommand$WithException.runWithResult(RunESCommand.java:78)
	at org.eclipse.emf.emfstore.internal.client.model.impl.api.ESLocalProjectImpl.shareProject(ESLocalProjectImpl.java:605)
	at com.arccore.versioncontrol.model.VCEngine.shareProject(VCEngine.java:869)
	at com.arccore.versioncontrol.model.VCEngine.localProjectInit(VCEngine.java:240)
	at com.arccore.versioncontrol.model.VCEngine.populateLocalProjectSharedDomain(VCEngine.java:282)
	at com.arccore.versioncontrol.model.VCModelView$3.handleEvent(VCModelView.java:176)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4353)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1061)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4172)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3761)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1151)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1032)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:148)
	at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:636)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:579)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:135)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:380)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:235)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:648)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:603)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1465)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1438)



As always, we'll keep this post updated with our progress.

Friendly Regards,
Christopher Doane

[Updated on: Fri, 21 April 2017 12:17]

Report message to a moderator

Re: [EMFStore] Sharing same EditingDomain between Eclipse Workspace and EMFStore Workspace [message #1760059 is a reply to message #1759941] Fri, 21 April 2017 14:34 Go to previous messageGo to next message
Edgar Mueller is currently offline Edgar MuellerFriend
Messages: 17
Registered: March 2016
Junior Member
Hi Christopher,
no, there shouldn't be any addtional steps involved.
The line that causes the NPE is ESWorkspaceProviderImpl.getInstance().getEditingDomain().getCommandStack().execute(this), so I suppose getEditingDomain() returns null for some reason.
Could you check whether your editingDomainProvider is picked correctly in ESWorkspaceProviderImpl#createEditingDomain? getDomainProvider should return the class you've specified in the extension point.

Cheers,
Edgar
Re: [EMFStore] Sharing same EditingDomain between Eclipse Workspace and EMFStore Workspace [message #1760196 is a reply to message #1760059] Mon, 24 April 2017 13:28 Go to previous messageGo to next message
Christopher Doane is currently offline Christopher DoaneFriend
Messages: 5
Registered: April 2017
Junior Member
Hi Edgar!

Thanks for the feedback!

We think we have solved the NPE. We did this by implementing our own ResourceSetProvider as we think that there was previously no EditingDomain tied to the resourceSet given to createEditingDomain in ESWorkspaceProviderImpl. Instead of creating an editingDomain in ESWorkspaceProviderImpl we wanted to fetch the existing one from the Eclipse Workspace. We also didn't want to create a new resourceSet, and instead use the existing one on the Eclipse Workspace side as well.

Our EditingDomainProvider:
public class VCExtendedWorkspaceEditingDomainFactory extends ExtendedWorkspaceEditingDomainFactory implements ESEditingDomainProvider {

	/*
	 * Inherits most functions from ExtendedWorkspaceEditingDomainFactory. Rest is largely copied.
	 */
	public VCExtendedWorkspaceEditingDomainFactory(){
		super();
	}
	
	@Override
	public TransactionalEditingDomain createEditingDomain(Collection<IMetaModelDescriptor> metaModelDescriptors, ResourceSet resourceSet) {
		return createEditingDomain(metaModelDescriptors, resourceSet, createOperationHistory());
	}

	@Override
	public TransactionalEditingDomain createEditingDomain(Collection<IMetaModelDescriptor> metaModelDescriptors, ResourceSet resourceSet,
			IOperationHistory history) {

		// Create new WorkspaceCommandStack and TransactionalEditingDomain using given IOperationHistory and ResourceSet
		VCMergedCommandStack stack = new VCMergedCommandStack(history) {
			/*
			 * Overridden for passing {@link WorkspaceTransactionUtil#getDefaultTransactionOptions()} rather than
			 * <code>null</code> to {@link WorkspaceCommandStackImpl#execute(Command, Map<?, ?>)}.
			 */
			@SuppressWarnings("restriction")
			@Override
			public void execute(Command command) {
				try {
					execute(command, WorkspaceTransactionUtil.getDefaultTransactionOptions());
				} catch (InterruptedException e) {
					// just log it. Note that the transaction is already rolled back,
					// so handleError() will not find an active transaction
					org.eclipse.emf.transaction.internal.Tracing.catching(AbstractTransactionalCommandStack.class, "execute", e); //$NON-NLS-1$
					handleError(e);
				} catch (RollbackException e) {
					// just log it. Note that the transaction is already rolled back,
					// so handleError() will not find an active transaction
					org.eclipse.emf.transaction.internal.Tracing.catching(AbstractTransactionalCommandStack.class, "execute", e); //$NON-NLS-1$
					handleError(e);
				}
			}
		};
		System.out.println("About to create an extendedworkspaceeditingdomain in VCExtendedWorkspaceEditingDomainFactory!");
		TransactionalEditingDomain result = new ExtendedWorkspaceEditingDomain(new ComposedAdapterFactory(
				ComposedAdapterFactory.Descriptor.Registry.INSTANCE), stack, resourceSet);

		// Do default initialization
		mapResourceSet(result);

		// Add IEditingDomainProvider adapter which EMF.Edit needs for retrieving EditingDomain from ResourceSet
		resourceSet.eAdapters().add(new AdapterFactoryEditingDomain.EditingDomainProvider(result));

		// Give the specified meta-model descriptors to the newly created editing domain
		((ExtendedWorkspaceEditingDomain) result).getMetaModelDescriptors().addAll(metaModelDescriptors);

		firePostCreateEditingDomain(metaModelDescriptors, result);
		return result;
	}	
	
	/*
	 * Required to implement ESEditingDomainProvider.
	 * Called once when a Workspace is initialized in EMFStore's side.
	 */
	@Override   // Overriding to make sure that the default one on Eclipse side isn't used -> as it doesnt work for our case.
	public TransactionalEditingDomain getEditingDomain(ResourceSet resourceSet) {
		return WorkspaceEditingDomainUtil.getEditingDomain(resourceSet);
	}


Our ResourceSetProvider:
public class VCResourceSetProvider implements ESResourceSetProvider {

	@Override // For Usage in EMFStore side.
	public ResourceSet getResourceSet() {
		// Assumes only one resourceSet
		return WorkspaceEditingDomainUtil.getAllEditingDomains().iterator().next().getResourceSet();
	}

}


Placing a breakpoint in ESWorkspaceProviderImpl directly after setEditingDomain(createEditingDomain(resourceSet)) shows that we use our editingDomainProvider.
To double check this we print it out:
TransactionalEditingDomain ted = (TransactionalEditingDomain) ESWorkspaceProviderImpl.getInstance().getWorkspace().toInternalAPI().getEditingDomain();
		System.out.println("EditingDomain from ESWorkspaceProviderImpl: " + ted.getClass());
		
		if(ted.getCommandStack().equals(WorkspaceEditingDomainUtil.getAllEditingDomains().iterator().next().getCommandStack()) 
				&& ted.getCommandStack() instanceof VCMergedCommandStack )
		{
			System.out.println("Correct EditingDomain/CommandStack used.");
		}
		
		// As well as checking from ESWorkspaceProviderImpl:
		TransactionalEditingDomain storeDomain = (TransactionalEditingDomain) ESWorkspaceProviderImpl.getInstance().getEditingDomain();
		if(storeDomain.getCommandStack().equals(WorkspaceEditingDomainUtil.getAllEditingDomains().iterator().next().getCommandStack()) 
				&& storeDomain.getCommandStack() instanceof VCMergedCommandStack )
		{
			System.out.println("Correct EditingDomain/CommandStack used by ESWorkspaceProviderImpl.");
		}
Console:
EditingDomain from ESWorkspaceProviderImpl: class org.eclipse.sphinx.emf.workspace.domain.factory.ExtendedWorkspaceEditingDomainFactory$ExtendedWorkspaceEditingDomain
Correct EditingDomain/CommandStack used.
Correct EditingDomain/CommandStack used by ESWorkspaceProviderImpl.


Checking to make sure that Eclipse Workspace's ResourceSet is the same as the one in our ESLocalProjectImpl's ResourceSet directly after localProject's creation:
System.out.println("!# Eclipse Workspace resourceSet: " + WorkspaceEditingDomainUtil.getAllEditingDomains().iterator().next().getResourceSet().hashCode());
			System.out.println("!# localProject's resourceSet: " + ESLocalProjectImpl.class.cast(localProject).toInternalAPI().getResourceSet().hashCode());
Console:
!# Eclipse Workspace resourceSet: 1742232927
!# localProject's resourceSet: 1742232927


This may or may not be the right way of going about things. Are we thinking wrong when we add a resourceSetProvider that fetches the existing editingDomain's resourceSet?

With this we no longer get a NPE, however we do have issues with ResourcePersister when running ModelUtil.saveResource(resource, WorkspaceUtil.getResourceLogger()); on line 178 of EMFStore's ResourcePersister. We now fail to save our projectspace resource.

A save is performed on the resource representation of ProjectSpace which is in the form of an XMIResourceImpl just before the localProject is shared to EMFStore's server. This however fails.

Trace:
Local project is not shared. Attempting to share with server..
Sharing Project:..java.lang.RuntimeException: Save of resource emfstore://workspaces/default/projectspaces/_fH4a8CjPEeehSJrbJH5EKw/projectspace failed.
	at org.eclipse.emf.emfstore.internal.client.model.impl.ResourcePersister.saveDirtyResources(ResourcePersister.java:181)
	at org.eclipse.emf.emfstore.internal.client.model.impl.ProjectSpaceBase.save(ProjectSpaceBase.java:1267)
	at org.eclipse.emf.emfstore.internal.client.model.controller.ShareController.run(ShareController.java:89)
	at org.eclipse.emf.emfstore.internal.client.model.controller.ShareController.run(ShareController.java:1)
	at org.eclipse.emf.emfstore.internal.client.model.connectionmanager.ServerCall.run(ServerCall.java:249)
	at org.eclipse.emf.emfstore.internal.client.model.connectionmanager.SessionManager.executeCall(SessionManager.java:149)
	at org.eclipse.emf.emfstore.internal.client.model.connectionmanager.SessionManager.execute(SessionManager.java:68)
	at org.eclipse.emf.emfstore.internal.client.model.connectionmanager.ServerCall.execute(ServerCall.java:269)
	at org.eclipse.emf.emfstore.internal.client.model.impl.ProjectSpaceBase.shareProject(ProjectSpaceBase.java:1370)
	at org.eclipse.emf.emfstore.internal.client.model.impl.api.ESLocalProjectImpl$20.call(ESLocalProjectImpl.java:607)
	at org.eclipse.emf.emfstore.internal.client.model.impl.api.ESLocalProjectImpl$20.call(ESLocalProjectImpl.java:1)
	at org.eclipse.emf.emfstore.client.util.RunESCommand$WithException$1.doRun(RunESCommand.java:61)
	at org.eclipse.emf.emfstore.internal.client.model.util.EMFStoreCommandWithResult.commandBody(EMFStoreCommandWithResult.java:31)
	at org.eclipse.emf.emfstore.internal.client.model.util.AbstractEMFStoreCommand.execute(AbstractEMFStoreCommand.java:64)
	at org.eclipse.emf.workspace.EMFCommandOperation.doExecute(EMFCommandOperation.java:119)
	at org.eclipse.emf.workspace.AbstractEMFOperation.execute(AbstractEMFOperation.java:150)
	at org.eclipse.core.commands.operations.DefaultOperationHistory.execute(DefaultOperationHistory.java:513)
	at org.eclipse.emf.workspace.impl.WorkspaceCommandStackImpl.doExecute(WorkspaceCommandStackImpl.java:208)
	at org.eclipse.emf.transaction.impl.AbstractTransactionalCommandStack.execute(AbstractTransactionalCommandStack.java:165)
	at com.arccore.versioncontrol.model.VCExtendedWorkspaceEditingDomainFactory$1.execute(VCExtendedWorkspaceEditingDomainFactory.java:60)
	at org.eclipse.emf.emfstore.internal.client.model.util.AbstractEMFStoreCommand.aRun(AbstractEMFStoreCommand.java:108)
	at org.eclipse.emf.emfstore.internal.client.model.util.EMFStoreCommandWithResult.run(EMFStoreCommandWithResult.java:59)
	at org.eclipse.emf.emfstore.client.util.RunESCommand$WithException.runWithResult(RunESCommand.java:78)
	at org.eclipse.emf.emfstore.internal.client.model.impl.api.ESLocalProjectImpl.shareProject(ESLocalProjectImpl.java:605)
	at com.arccore.versioncontrol.model.VCEngine.shareProject(VCEngine.java:905)
	at com.arccore.versioncontrol.model.VCEngine.localProjectInit(VCEngine.java:276)
	at com.arccore.versioncontrol.model.VCEngine.populateLocalProjectSharedDomain(VCEngine.java:318)
	at com.arccore.versioncontrol.model.VCModelView$3.handleEvent(VCModelView.java:176)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4353)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1061)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4172)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3761)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1151)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1032)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:148)
	at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:636)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:579)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:135)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:380)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:235)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:648)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:603)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1465)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1438)


What are some general things that could cause a resource's persistence save method to fail?

Thanks again Edgar.

Friendly Regards,
Christopher Doane
Re: [EMFStore] Sharing same EditingDomain between Eclipse Workspace and EMFStore Workspace [message #1760253 is a reply to message #1760196] Tue, 25 April 2017 08:34 Go to previous messageGo to next message
Christopher Doane is currently offline Christopher DoaneFriend
Messages: 5
Registered: April 2017
Junior Member
Ok we think that the problem above may be due to the URIConverter within the ResourceSet coming from the Eclipse Workspace not being able to parse the emfstore protocol. we have found that an exception occurs on unknown protocol in URL for the protocol emfstore:\\URL. This has most likely to do with that our ResourceSet taken from the Eclipse Workspace doesnt have a URIConverter that works in EMFStore. It appears that EMFStore provides its own implementation of a URIConverter when it creates a ResourceSet (http:// download.eclipse.org/emfstore/releases_17/javadoc/org/eclipse/emf/emfstore/internal/client/provider/XMIClientURIConverter.html).
Re: [EMFStore] Sharing same EditingDomain between Eclipse Workspace and EMFStore Workspace [message #1760278 is a reply to message #1760253] Tue, 25 April 2017 13:06 Go to previous messageGo to next message
Christopher Doane is currently offline Christopher DoaneFriend
Messages: 5
Registered: April 2017
Junior Member
Ah, we were naive.

Source of the issue was that our ResourceSetProvider that we had registered at the EMFStore extension point was using the URIConverter that came with the ResourceSet in the shared EditingDomain from the Eclipse Workspace. This URIConverter obviously doesn't understand EMFStore resources.
In EMFStore's default ResourceSetProvider: ClientXMIResourceSetProvider (http:// download.eclipse.org/emfstore/releases_18/javadoc/org/eclipse/emf/emfstore/internal/client/provider/ClientXMIResourceSetProvider.html) the resourceSet's URIConverter is set to an XMIClientURIConverter so that EMFStore resource URIs are understood.

Quickly swapping out the existing URIConverter and ResourceFactoryRegistry in the shared ResourceSet with EMFStore's URIConverter and ResourceFactoryRegistry gives good results. However we have now totally swapped out the old URIConverter, and the old one is most likely needed for some specific features in certain EMF objects. This we could verify when certain eobjects were created in the project navigator.

We now plan to merge the functionality of EMFStore's URIConverter with the existing URIConverter that is used in our custom version of Eclipse into a new URIConverter.

Could this be the wrong path to take? Should we instead do something with the extension_parser or protocol_parser extension point in org.eclipse.emf.ecore?

We will keep this thread updated with progress.

Cheers,
Christopher
Re: [EMFStore] Sharing same EditingDomain between Eclipse Workspace and EMFStore Workspace [message #1760436 is a reply to message #1760278] Thu, 27 April 2017 07:47 Go to previous message
Edgar Mueller is currently offline Edgar MuellerFriend
Messages: 17
Registered: March 2016
Junior Member
Yes, this sounds like the right approach. Maybe it also helps if you take a look at EMFStore's mongo integration where we registered additional URIConverters for a given ResourceSet, see org.eclipse.emf.emfstore.mongodb.client.MongoDBClientResourceSetProvider and org.eclipse.emf.emfstore.mongodb.server.MongoDBServerResourceSetProvider.
Previous Topic:[EMF Forms] - Custom Control Area
Next Topic:[EMFStore] e4 RCP
Goto Forum:
  


Current Time: Mon Sep 25 22:35:47 GMT 2017

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

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