Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » [CDO] Notification disabled while instanciating objects from repo?
icon5.gif  [CDO] Notification disabled while instanciating objects from repo? [message #774303] Tue, 03 January 2012 16:58 Go to next message
Alexandre Borgoltz is currently offline Alexandre Borgoltz
Messages: 14
Registered: July 2009
Location: France
Junior Member
Hi,

I am migrating an existing EMF model from XML files to a CDO repo.
I have migrated the .genmodel using CDO's migrator ("dynamic feature delegation").

Everything's doing quite good so far. Except we are facing some "regression" in the behaviour of our model. The reason for that is that we have custom Adapters (listeners) attached to our model objects at constructor time.
public MyModel() {
  super();
  eAdapters().add(new AdapterImpl() {

	@Override
	public void notifyChanged(Notification msg) {
	  //do something when this is modified...
	}			
			
  });
}

The problem: these adapters are not notified while CDO is instanciating the object. Even if I override eDeliver() to force it to always return true.

Technically, my adapters are not notified when the following code is executed
session=...
view=...
resource=...
MyModel myObject = (MyModel) resource.getContents().get(0);
//until there no notification


Yet of course, they are notified if I subsequentely call my model's setters and getters explicitely:
//next line generate a notification
myObject.setAttribute1(...);


I must add that the behaviour is OK if I use the legacy mode - which calls my setters and triggers notifications, thanks to the overrinding of eDeliver().


My question: why doesn't CDO trigger notification when materializing the objects? Analogously why is notification disabled then restored during e.g. LegacyCDOWrapper.revisionToInstance()?
What can I do to turn it on?



  protected void revisionToInstance()
  {    

    ...

    boolean deliver = instance.eDeliver();
    if (deliver)
    {
      instance.eSetDeliver(false);
    }

    ...

    }
    finally
    {
      if (deliver)
      {
        instance.eSetDeliver(true);
      }

      ...
    }
  }


I thank you in advance for your answer!
Re: [CDO] Notification disabled while instanciating objects from repo? [message #774639 is a reply to message #774303] Wed, 04 January 2012 10:23 Go to previous messageGo to next message
Eike Stepper is currently offline Eike Stepper
Messages: 5522
Registered: July 2009
Senior Member
Am 03.01.2012 17:58, schrieb Alexandre Borgoltz:
> Hi,
> I am migrating an existing EMF model from XML files to a CDO repo.
> I have migrated the .genmodel using CDO's migrator ("dynamic feature delegation").
>
> Everything's doing quite good so far. Except we are facing some "regression" in the behaviour of our model. The reason
> for that is that we have custom Adapters (listeners) attached to our model objects at constructor time.
> public MyModel() {
> super();
> eAdapters().add(new AdapterImpl() {
>
> @Override
> public void notifyChanged(Notification msg) {
> //do something when this is modified...
Although I don't know exactly what this "something" is, it strikes me that this is uncommon (maybe poor) design. Can't
you compute lazily instead?

> }
>
> });
> }
>
> The problem: these adapters are not notified while CDO is instanciating the object. Even if I override eDeliver() to
> force it to always return true.
>
> Technically, my adapters are not notified when the following code is executed
>
> session=...
> view=...
> resource=...
> MyModel myObject = (MyModel) resource.getContents().get(0);
> //until there no notification
No, because at this point the object is not logically modified.
>
>
> Yet of course, they are notified if I subsequentely call my model's setters and getters explicitely:
>
> //next line generate a notification
> myObject.setAttribute1(...);
>
>
> I must add that the behaviour is OK if I use the legacy mode - which calls my setters and triggers notifications,
> thanks to the overrinding of eDeliver().
That's not the intended usage and it may well corrupt certain aspects of CDO or CDO's legacy mode.

>
>
> My question: why doesn't CDO trigger notification when materializing the objects?
Because that's not considered a *change* of the logical object (with a well-defined long-term and multi-branch lifecycle).

> Analogously why is notification disabled then restored during e.g. LegacyCDOWrapper.revisionToInstance()?
For exactly the reason outlined above. CDO synchronizes the persistent lifecycle of a logical object with an in-memory
Java/EMF technical object. Adapters must only "see" the logical changes, that's why all resource implementations,
including CDO, turn off eDeliver during technical changes such as loading. We'd have to ask Martin about the legacy mode
but I guess it even relies on controlling eDeliver because it's based on adapters, too.

> What can I do to turn it on?
Not much, I fear. Maybe I'd have to understand your use case better to give advice for an alternative design.

Cheers
/Eike

----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper




>
>
>
>
> protected void revisionToInstance()
> {
> ...
>
> boolean deliver = instance.eDeliver();
> if (deliver)
> {
> instance.eSetDeliver(false);
> }
>
> ...
>
> }
> finally
> {
> if (deliver)
> {
> instance.eSetDeliver(true);
> }
>
> ...
> }
> }
>
>
> I thank you in advance for your answer!
Re: [CDO] Notification disabled while instanciating objects from repo? [message #774709 is a reply to message #774303] Wed, 04 January 2012 12:43 Go to previous messageGo to next message
Martin Fluegge is currently offline Martin Fluegge
Messages: 141
Registered: July 2009
Senior Member
> Analogously why is notification disabled then restored during e.g. LegacyCDOWrapper.revisionToInstance()?

revisionToInstance() is called every time an object is synchronized. This usually happens when internal operations are invoked. We do not want to fire notification when this happens.

> What can I do to turn it on?

Nothing. It cannot be turned on.

Cheers,

Martin
Re: [CDO] Notification disabled while instanciating objects from repo? [message #774792 is a reply to message #774639] Wed, 04 January 2012 16:18 Go to previous messageGo to next message
Alexandre Borgoltz is currently offline Alexandre Borgoltz
Messages: 14
Registered: July 2009
Location: France
Junior Member
Hey Eike, thanks for your reply - I'll try to make myself understood a little bit better... Take a deep breath! Wink

Eike Stepper wrote on Wed, 04 January 2012 11:23
Am 03.01.2012 17:58, schrieb Alexandre Borgoltz:
> [...] we have custom Adapters (listeners) attached to our model objects at constructor time.
> public MyModel() {
> super();
> eAdapters().add(new AdapterImpl() {
>
> @Override
> public void notifyChanged(Notification msg) {
> //do something when this is modified...
Although I don't know exactly what this "something" is, it strikes me that this is uncommon (maybe poor) design. Can't
you compute lazily instead?


Hope my design isn't that poor - or that you will help enrich it a bit! Smile

The reason for these adapters is that we have implemented derived features - and they're computed lazily actually.
And we want notifications fired for them, when the features they depend on are modified.
I just respected the official EMF Recipe called "Derived Attribute Notifier" - see /EMF/Recipes#Recipe:_Derived_Attribute_Notifier at wiki.eclipse.org

Eike Stepper wrote on Wed, 04 January 2012 11:23

> [...]
> The problem: these adapters are not notified while CDO is instanciating the object.
> [...]
No, because at this point the object is not logically modified.

I am unsure I understand what logically means. The fact is I did not consider that Adapters should be notified only for logical changes - and I am not sure the EMF Recipe I followed does neither.


Here's my -potentially wrong, and very humble- point of view:
My code somehow always looks like

EObject myModel = MyFrameWork.getAHoldOnMyModel(...);


And I see -at least- 3 differents ways of implementing the getAHoldOnMyModel() method.


  1. low-level, manual, based on EMF Factory + calls of setter methods
  2. using a "classical" resource (typically XML/XMI)
  3. using a CDO resource


Sample illustration of 1.

  MyModel model1 = MyModel1Factory.createMyModel();
  model1.setDummy("dummy");
  model1.setDummy2("dummy too");
  //...


Sample illustration of 2.

  ResourceSet rs = new ResourceSetImpl();
  Resource r = rs.createResource(xmlFileURI);
  MyModel model1 = (MyModel) r.getContents().get(0);


Sample illustration of 3.

  CDOSession session = ...;
  CDOView view = session.openView();
  Resource resource = view.getOrCreateResource("...");
  MyModel model1 = (MyModel) resource.getContents().get(0);



So we have three different ways of getting an instance of our model, and I'd tend to beleive it would be quite enjoyable if these 3 ways were seamlessly interchangeable. Meaning that once you have your EObject instance, it should be seamless wether it comes from CDO or an XMIResource or whatever.

The fact is : "my" adapters are notified in methods 1. and 2. but not with 3. (CDO)... CDO is not seamless Sad

Eike Stepper wrote on Wed, 04 January 2012 11:23


> [...]
> thanks to the overrinding of eDeliver().
That's not the intended usage and it may well corrupt certain aspects of CDO or CDO's legacy mode.

Yes, of course. It was just to underline that the legacy mode triggers notification but disables explicitely their delivery whereas native mode does not even trigger notifications. I was awaiting CDO to populate my model through the "classic" EMF way : setters or eSet, thus triggering notifications, even if disabling their delivery. The test I did by overriding eDeliver() shows it's not exactly the case...

Eike Stepper wrote on Wed, 04 January 2012 11:23

[...]Adapters must only "see" the logical changes, that's why all resource implementations,
including CDO, turn off eDeliver during technical changes such as loading.[...]

Well, as explained above, my tests show that XMLResourceImpl does notify my eAdapters during loading (cf below)!

Illustration: (I can provide you with the sources)
I have added a simple adapter in the constructor of my model. It throws a RuntimeException whenever it is notified - of course throwing the exception is just for the demo...:

public MyModelImpl() {
	eAdapters().add(new AdapterImpl() {
	
	  @Override
	  public void notifyChanged(Notification msg) {
	  	  throw new RuntimeException("The Adapter was called");
	  }});
}


I then load an instance of MyModel using a standard XMI resource - see the following snippet : the exception is thrown, proving the adapter is notified during loading.

//The following code outputs "OK : The adapter was called".
//It would output "KO - Adapters not called" if there was no notification.

public static void main(String[] args) {
		
	try {
		//Register our Package
		BidonPackage.eINSTANCE.eClass();
		
		//Register the resource factory
		Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
		Map<String, Object> m = reg.getExtensionToFactoryMap();
		m.put("xmi", new XMIResourceFactoryImpl());
		
		String path = "file:/path/to/my/file.xmi";
		ResourceSet rs = new ResourceSetImpl();
		Resource r = rs.getResource(URI.createURI(path), true);
		System.out.println(r.getContents().get(0));
		System.out.println("KO - Adapters not called");
	} catch (Throwable t) {
		System.out.println("OK : " + t.getCause().getCause().getMessage());
	}
	
}



If you read this line, it means you had the courage to go through it all : congrats (and respect) !! Smile

Conclusion - at last!:

  • it somehow surprises me that CDO's behaviour during loading seems different from e.g. XMl/XMI resource loading. Is it something I do/understand wrong?
  • How else can I acheive notification firing for my derived features?


Thank you much for reading!

PS: I guess complete sample code would help. Don't hesistate to ask me.
Re: [CDO] Notification disabled while instanciating objects from repo? [message #774840 is a reply to message #774792] Wed, 04 January 2012 18:40 Go to previous messageGo to next message
Eike Stepper is currently offline Eike Stepper
Messages: 5522
Registered: July 2009
Senior Member
Am 04.01.2012 17:18, schrieb Alexandre Borgoltz:
> Hey Eike, thanks for your reply - I'll try to make myself understood a little bit better... Take a deep breath! ;)
>
> Eike Stepper wrote on Wed, 04 January 2012 11:23
>> Am 03.01.2012 17:58, schrieb Alexandre Borgoltz:
>> > [...] we have custom Adapters (listeners) attached to our model objects at constructor time.
>> > public MyModel() {
>> > super();
>> > eAdapters().add(new AdapterImpl() {
>> >
>> > @Override
>> > public void notifyChanged(Notification msg) {
>> > //do something when this is modified...
>> Although I don't know exactly what this "something" is, it strikes me that this is uncommon (maybe poor) design.
>> Can't you compute lazily instead?
>
>
> Hope my design isn't that poor - or that you will help enrich it a bit! :)
>
> The reason for these adapters is that we have implemented derived features - and they're computed lazily actually. And
> we want notifications fired for them, when the features they depend on are modified. I just respected the official EMF
> Recipe called "Derived Attribute Notifier" - see /EMF/Recipes#Recipe:_Derived_Attribute_Notifier at wiki.eclipse.org
Where in that example/snippet is the eDeliver() method overridden? Or is the XMLResource.OPTION_DISABLE_NOTIFY involved?

>
> Eike Stepper wrote on Wed, 04 January 2012 11:23
>> > [...]
>> > The problem: these adapters are not notified while CDO is instanciating the object. > [...]
>> No, because at this point the object is not logically modified.
>
> I am unsure I understand what logically means. The fact is I did not consider that Adapters should be notified only
> for logical changes - and I am not sure the EMF Recipe I followed does neither.
>
>
> Here's my -potentially wrong, and very humble- point of view:
> My code somehow always looks like
>
> EObject myModel = MyFrameWork.getAHoldOnMyModel(...);
>
> And I see -at least- 3 differents ways of implementing the getAHoldOnMyModel() method.
>
>
> low-level, manual, based on EMF Factory + calls of setter methods
> using a "classical" resource (typically XML/XMI)
> using a CDO resource
>
>
> Sample illustration of 1.
>
>
> MyModel model1 = MyModel1Factory.createMyModel();
> model1.setDummy("dummy");
> model1.setDummy2("dummy too");
> //...
>
>
> Sample illustration of 2.
>
>
> ResourceSet rs = new ResourceSetImpl();
> Resource r = rs.createResource(xmlFileURI);
> MyModel model1 = (MyModel) r.getContents().get(0);
>
>
> Sample illustration of 3.
>
>
> CDOSession session = ...;
> CDOView view = session.openView();
> Resource resource = view.getOrCreateResource("...");
> MyModel model1 = (MyModel) resource.getContents().get(0);
>
>
>
> So we have three different ways of getting an instance of our model, and I'd tend to beleive it would be quite
> enjoyable if these 3 ways were seamlessly interchangeable. Meaning that once you have your EObject instance, it should
> be seamless wether it comes from CDO or an XMIResource or whatever.
>
> The fact is : "my" adapters are notified in methods 1. and 2. but not with 3. (CDO)... CDO is not seamless :(
Of course CDO is not seamless for all aspects. For example some aspects of EMF have not been designed for distributed
models (e.g. remote deletion notification is missing). If the resource to be loaded contains 5000 billion objects it
would also not be seamless because only your third scenario could ever load that resource and let you navigate it.

While we certainly must (and want to) accept that some things are not seamless, we can discuss if we can make CDO a bit
more seamless in this regard. A general problem I see with your many adapters that keep references to other objects is
that it does not scale very well. It can easily (load and) keep your entire object graph into memory. Even worse, the
default strong reference policy of a CDOView (see CDOView.Options.setStrongReferencePolicy) prevents object with
adapters from being unloaded. But if you want to be seamless with a technology (EMF) that does not have this property,
well... ;-)

I have a solution for CDO native objects in mind. Can you please submit a bugzilla to discuss problems and track progress?

>
> Eike Stepper wrote on Wed, 04 January 2012 11:23
>> > [...] > thanks to the overrinding of eDeliver().
>> That's not the intended usage and it may well corrupt certain aspects of CDO or CDO's legacy mode.
>
> Yes, of course. It was just to underline that the legacy mode triggers notification but disables explicitely their
> delivery whereas native mode does not even trigger notifications. I was awaiting CDO to populate my model through the
> "classic" EMF way : setters or eSet, thus triggering notifications, even if disabling their delivery. The test I did
> by overriding eDeliver() shows it's not exactly the case...
>
> Eike Stepper wrote on Wed, 04 January 2012 11:23
>> [...]Adapters must only "see" the logical changes, that's why all resource implementations, including CDO, turn off
>> eDeliver during technical changes such as loading.[...]
>
> Well, as explained above, my tests show that XMLResourceImpl does notify my eAdapters during loading (cf below)!
>
> Illustration: (I can provide you with the sources)
> I have added a simple adapter in the constructor of my model. It throws a RuntimeException whenever it is notified -
> of course throwing the exception is just for the demo...:
>
>
> public MyModelImpl() {
> eAdapters().add(new AdapterImpl() {
>
> @Override
> public void notifyChanged(Notification msg) {
> throw new RuntimeException("The Adapter was called");
> }});
> }
>
>
> I then load an instance of MyModel using a standard XMI resource - see the following snippet : the exception is
> thrown, proving the adapter is notified during loading.
>
>
> //The following code outputs "OK : The adapter was called".
> //It would output "KO - Adapters not called" if there was no notification.
>
> public static void main(String[] args) {
>
> try {
> //Register our Package
> BidonPackage.eINSTANCE.eClass();
>
> //Register the resource factory
> Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
> Map<String, Object> m = reg.getExtensionToFactoryMap();
> m.put("xmi", new XMIResourceFactoryImpl());
>
> String path = "file:/path/to/my/file.xmi";
> ResourceSet rs = new ResourceSetImpl();
> Resource r = rs.getResource(URI.createURI(path), true);
> System.out.println(r.getContents().get(0));
> System.out.println("KO - Adapters not called");
> } catch (Throwable t) {
> System.out.println("OK : " + t.getCause().getCause().getMessage());
> }
>
> }
>
>
>
> If you read this line, it means you had the courage to go through it all : congrats (and respect) !! :)
>
> Conclusion - at last!:
>
> it somehow surprises me that CDO's behaviour during loading seems different from e.g. XMl/XMI resource loading. Is it
> something I do/understand wrong?
It's not surprising at all because object loading and unloading itself is very different in CDO.

Cheers
/Eike

----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper


> How else can I acheive notification firing for my derived features?
>
>
> Thank you much for reading!
>
> PS: I guess complete sample code would help. Don't hesistate to ask me.
>
Re: [CDO] Notification disabled while instanciating objects from repo? [message #775084 is a reply to message #774840] Thu, 05 January 2012 09:52 Go to previous messageGo to next message
Alexandre Borgoltz is currently offline Alexandre Borgoltz
Messages: 14
Registered: July 2009
Location: France
Junior Member
Eike Stepper wrote on Wed, 04 January 2012 19:40

I have a solution for CDO native objects in mind.
Can you please submit a bugzilla to discuss problems and track progress?

bugzilla submitted! Title: "[CDO] Allow Adapters to be notified during loading" ID: 367905

Re: [CDO] Notification disabled while instanciating objects from repo? [message #775087 is a reply to message #775084] Thu, 05 January 2012 09:57 Go to previous message
Alexandre Borgoltz is currently offline Alexandre Borgoltz
Messages: 14
Registered: July 2009
Location: France
Junior Member
Eike has commited a solution already Smile
see https://bugs.eclipse.org/bugs/show_bug.cgi?id=367905

Eike Stepper 2012-01-05 04:32:39 EST

I'm adding the following new API:

- CDOView.Options.isLoadNotificationEnabled()
- CDOView.Options.setLoadNotificationEnabled(boolean)

The default value is false (i.e. the former behaviour)


Thank you so much Eike. I am checking out the last version and will let you know when my tests are over.
Previous Topic:How to get factory class name for parameter
Next Topic:Modeling Symposium
Goto Forum:
  


Current Time: Wed Sep 17 05:46:18 GMT 2014

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

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