Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » [EMF Transactions] Modifying removed transactional objects
[EMF Transactions] Modifying removed transactional objects [message #424062] Wed, 15 October 2008 15:32 Go to next message
Mario Winterer is currently offline Mario WintererFriend
Messages: 136
Registered: July 2009
Senior Member
Hi!

I've noticed today that an object that was removed from its container is
still connected to the editing domain (i.e. the TransactionalChangeRecorder
is still attached), which might be necessary to make undo/redo work properly
(isn't it?).

But since the object does not have a resource, the editing domain cannot be
retrieved by calling

TransactionUtil.getEditingDomain(removedObject);

This situation causes some problems for us:
+ it is not possible to modify the object outside of a transaction because
it is still transactional (ok, so let's use a command)
+ in case of multiple editing domains, it is not clear, which editing domain
to choose for executing this command (which editing domain is "responsible"
for that object now?)
+ it is not possible to distinguish between a "free object" (object that has
never been in a resource/editing domain) and a "removed transactional
object" (object that has been in a resource inside a transactional editing
domain but was removed from its container).

Because of this, the following (generic setter) method fails if executed on
a removed object, and I do not have any idea how to make it work:

void transactionalSet(EObject eObject, EStructuralFeature feature) throws
InterruptedException, RollbackException {
TransactionalEditingDomain domain =
TransactionUtil.getEditingDomain(eObject); // will return null for removed
transactional objects
if (domain == null) {
eObject.eSet(feature, newValue); // will throw an exception on
removed transactional objects
} else {
Command cmd = SetCommand.create(domain, eObject, feature, newValue);
((TransactionalCommandStack) domain.getCommandStack()).execute(cmd,
null);
}
}

Is there any support for those "removed transactional objects".
Re: [EMF Transactions] Modifying removed transactional objects [message #424064 is a reply to message #424062] Wed, 15 October 2008 15:55 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: cdamus.zeligsoft.com

Hi, Mario,

See some replies in-line, below.

HTH,

Christian


Mario Winterer wrote:
> Hi!
>
> I've noticed today that an object that was removed from its container is
> still connected to the editing domain (i.e. the
> TransactionalChangeRecorder is still attached), which might be necessary
> to make undo/redo work properly (isn't it?).

Yes, because the editing domain doesn't know that the object won't
become attached again to another container in the same resource set.

Generally, in an EMF-based application, an object remains "alive" (or
"in play" in sports jargon) as long as it is still referenced by other
elements or it has adapters attached to it. Complete destruction of an
object requires removal of all of its adapters.

To disconnect an object from a transactional editing domain if it really
is not going to be used in that context any longer, you can use the
appropriate utilities in the TransactionUtil class.


> But since the object does not have a resource, the editing domain cannot
> be retrieved by calling
>
> TransactionUtil.getEditingDomain(removedObject);

Hmm, yes, this should probably be enhanced for the case of a detached
object. We should be able to trace the editing domain via the first
attached TransactionChangeRecorder.

Would you care to raise an enhancement request?


> This situation causes some problems for us:
> + it is not possible to modify the object outside of a transaction
> because it is still transactional (ok, so let's use a command)

Unless it really doesn't belong in that domain anymore, in which case
disconnecting it is advisable.


> + in case of multiple editing domains, it is not clear, which editing
> domain to choose for executing this command (which editing domain is
> "responsible" for that object now?)

Yikes! An object should *never* be in multiple editing domains
simultaneously. That requires transactions in *all* domains in order to
edit it.


> + it is not possible to distinguish between a "free object" (object that
> has never been in a resource/editing domain) and a "removed
> transactional object" (object that has been in a resource inside a
> transactional editing domain but was removed from its container).

The enhanced TransactionUtil API would cover that.


> Because of this, the following (generic setter) method fails if executed
> on a removed object, and I do not have any idea how to make it work:
>
> void transactionalSet(EObject eObject, EStructuralFeature feature)
> throws InterruptedException, RollbackException {
> TransactionalEditingDomain domain =
> TransactionUtil.getEditingDomain(eObject); // will return null for
> removed transactional objects
> if (domain == null) {
> eObject.eSet(feature, newValue); // will throw an exception on
> removed transactional objects
> } else {
> Command cmd = SetCommand.create(domain, eObject, feature, newValue);
> ((TransactionalCommandStack)
> domain.getCommandStack()).execute(cmd, null);
> }
> }

Hmmm. I'd be a little worried about utilities like this, in any case.
Why would you want changes to some objects to be on the command-stack
but not others? This doesn't appear to be a coherent editing strategy.
If there is any dependency between some of these changes and changes
made subsequently, then your data will be messed up if not all of the
changes are on the stack.


> Is there any support for those "removed transactional objects".
Re: [EMF Transactions] Modifying removed transactional objects [message #424069 is a reply to message #424064] Wed, 15 October 2008 18:13 Go to previous messageGo to next message
Mario Winterer is currently offline Mario WintererFriend
Messages: 136
Registered: July 2009
Senior Member
Thanks for the quick response.
My comments are below.

"Christian W. Damus" <cdamus@zeligsoft.com> schrieb im Newsbeitrag
news:gd53or$tjl$1@build.eclipse.org...
> Hi, Mario,
>
> See some replies in-line, below.
>
> HTH,
>
> Christian
>
>
> Mario Winterer wrote:
>> Hi!
>>
>> I've noticed today that an object that was removed from its container is
>> still connected to the editing domain (i.e. the
>> TransactionalChangeRecorder is still attached), which might be necessary
>> to make undo/redo work properly (isn't it?).
>
> Yes, because the editing domain doesn't know that the object won't become
> attached again to another container in the same resource set.
>
> Generally, in an EMF-based application, an object remains "alive" (or "in
> play" in sports jargon) as long as it is still referenced by other
> elements or it has adapters attached to it. Complete destruction of an
> object requires removal of all of its adapters.
>
> To disconnect an object from a transactional editing domain if it really
> is not going to be used in that context any longer, you can use the
> appropriate utilities in the TransactionUtil class.
>
>
>> But since the object does not have a resource, the editing domain cannot
>> be retrieved by calling
>>
>> TransactionUtil.getEditingDomain(removedObject);
>
> Hmm, yes, this should probably be enhanced for the case of a detached
> object. We should be able to trace the editing domain via the first
> attached TransactionChangeRecorder.
>
> Would you care to raise an enhancement request?

Ok. I'll do so. I think this feature would solve our problems...

>> This situation causes some problems for us:
>> + it is not possible to modify the object outside of a transaction
>> because it is still transactional (ok, so let's use a command)
>
> Unless it really doesn't belong in that domain anymore, in which case
> disconnecting it is advisable.
>
>
>> + in case of multiple editing domains, it is not clear, which editing
>> domain to choose for executing this command (which editing domain is
>> "responsible" for that object now?)
>
> Yikes! An object should *never* be in multiple editing domains
> simultaneously. That requires transactions in *all* domains in order to
> edit it.

Sorry for this ambiguity - of course the object is not in multiple editing
domains, but there might be more than one single editing domain "somewhere",
so given an object o it is not possible to say (with the given methods) if o
belongs to editing domain A or editing domain B, even if it is still "in
play".

>> + it is not possible to distinguish between a "free object" (object that
>> has never been in a resource/editing domain) and a "removed transactional
>> object" (object that has been in a resource inside a transactional
>> editing domain but was removed from its container).
>
> The enhanced TransactionUtil API would cover that.

OK. So you'd prefer to add an additional method to TransactionUtil instead
of changing the behaviour of getEditingDomain(EObject) to return an editing
domain even if the object is detached?

>> Because of this, the following (generic setter) method fails if executed
>> on a removed object, and I do not have any idea how to make it work:
>>
>> void transactionalSet(EObject eObject, EStructuralFeature feature) throws
>> InterruptedException, RollbackException {
>> TransactionalEditingDomain domain =
>> TransactionUtil.getEditingDomain(eObject); // will return null for
>> removed transactional objects
>> if (domain == null) {
>> eObject.eSet(feature, newValue); // will throw an exception on
>> removed transactional objects
>> } else {
>> Command cmd = SetCommand.create(domain, eObject, feature,
>> newValue);
>> ((TransactionalCommandStack)
>> domain.getCommandStack()).execute(cmd, null);
>> }
>> }
>
> Hmmm. I'd be a little worried about utilities like this, in any case. Why
> would you want changes to some objects to be on the command-stack but not
> others? This doesn't appear to be a coherent editing strategy. If there
> is any dependency between some of these changes and changes made
> subsequently, then your data will be messed up if not all of the changes
> are on the stack.

Of course, all objects that are attached to an editing domain will be
modified on the command stack (this is what the code does: if an object is
attached, execute a command); and usually, all of our objects are attached
to an editing domain. But newly created objects (that are not attached to a
container yet) cannot (and need not) be changed on the command stack. So we
sometimes first modify a new object (without commands) and then use one
single command to attach it to the container (in opposite to first attaching
it and then modifying it which is more expensive and requires a command
chain). The method above just simplifies this technique as it is sometimes
not obvious if the modified object(-graph) is already attached.

Another szenario is a user preview of model changes. Therefore we make a
copy of the model (EcoreUtil.copy()) and "simulate" the changes using the
copy. After the user confirms the changes, they are applied on the read
model. Because no undo/redo or transaction support is required for the
simulation, the changes are not executed on a command stack (in fact, the
copy is not even attached to any editing domain), but indeed they are so
when applied to the real model.

I appreciate any discussions of our techniques and strategies.
Re: [EMF Transactions] Modifying removed transactional objects [message #424071 is a reply to message #424069] Wed, 15 October 2008 18:46 Go to previous message
Eclipse UserFriend
Originally posted by: cdamus.zeligsoft.com

Hi, Mario,

Some more follow-up in-line, below.

cW

Mario Winterer wrote:
> Thanks for the quick response.
> My comments are below.
>
> "Christian W. Damus" <cdamus@zeligsoft.com> schrieb im Newsbeitrag
> news:gd53or$tjl$1@build.eclipse.org...
>> Hi, Mario,

-----8<-----

>>> But since the object does not have a resource, the editing domain
>>> cannot be retrieved by calling
>>>
>>> TransactionUtil.getEditingDomain(removedObject);
>>
>> Hmm, yes, this should probably be enhanced for the case of a detached
>> object. We should be able to trace the editing domain via the first
>> attached TransactionChangeRecorder.
>>
>> Would you care to raise an enhancement request?
>
> Ok. I'll do so. I think this feature would solve our problems...

Thanks! And I'm glad to be able to help. :-)

-----8<-----

>> Yikes! An object should *never* be in multiple editing domains
>> simultaneously. That requires transactions in *all* domains in order
>> to edit it.
>
> Sorry for this ambiguity - of course the object is not in multiple
> editing domains, but there might be more than one single editing domain
> "somewhere", so given an object o it is not possible to say (with the
> given methods) if o belongs to editing domain A or editing domain B,
> even if it is still "in play".

Ah, right. That's good. From your history in this newsgroup, it's
clear that you have enough experience to know better :-D


>>> + it is not possible to distinguish between a "free object" (object
>>> that has never been in a resource/editing domain) and a "removed
>>> transactional object" (object that has been in a resource inside a
>>> transactional editing domain but was removed from its container).
>>
>> The enhanced TransactionUtil API would cover that.
>
> OK. So you'd prefer to add an additional method to TransactionUtil
> instead of changing the behaviour of getEditingDomain(EObject) to return
> an editing domain even if the object is detached?

No, actually I was just thinking of improving the existing
getEditingDomain(EObject) implementation. No new API.


>>> Because of this, the following (generic setter) method fails if
>>> executed on a removed object, and I do not have any idea how to make
>>> it work:
>>>
>>> void transactionalSet(EObject eObject, EStructuralFeature feature)
>>> throws InterruptedException, RollbackException {
>>> TransactionalEditingDomain domain =
>>> TransactionUtil.getEditingDomain(eObject); // will return null for
>>> removed transactional objects
>>> if (domain == null) {
>>> eObject.eSet(feature, newValue); // will throw an exception on
>>> removed transactional objects
>>> } else {
>>> Command cmd = SetCommand.create(domain, eObject, feature,
>>> newValue);
>>> ((TransactionalCommandStack)
>>> domain.getCommandStack()).execute(cmd, null);
>>> }
>>> }
>>
>> Hmmm. I'd be a little worried about utilities like this, in any case.
>> Why would you want changes to some objects to be on the command-stack
>> but not others? This doesn't appear to be a coherent editing
>> strategy. If there is any dependency between some of these changes and
>> changes made subsequently, then your data will be messed up if not all
>> of the changes are on the stack.
>
> Of course, all objects that are attached to an editing domain will be
> modified on the command stack (this is what the code does: if an object
> is attached, execute a command); and usually, all of our objects are
> attached to an editing domain. But newly created objects (that are not
> attached to a container yet) cannot (and need not) be changed on the
> command stack. So we sometimes first modify a new object (without
> commands) and then use one single command to attach it to the container
> (in opposite to first attaching it and then modifying it which is more
> expensive and requires a command chain). The method above just
> simplifies this technique as it is sometimes not obvious if the modified
> object(-graph) is already attached.

So, this will only apply to objects that have never yet been attached.
That's OK. Until it is in the resource set and attached to the editing
domain, it's safe to assume that an object cannot have been observed by
any client, so changes won't matter. There's no problem with an object
that springs into being fully-formed, like Aphrodite out of the foam.


> Another szenario is a user preview of model changes. Therefore we make a
> copy of the model (EcoreUtil.copy()) and "simulate" the changes using
> the copy. After the user confirms the changes, they are applied on the
> read model. Because no undo/redo or transaction support is required for
> the simulation, the changes are not executed on a command stack (in
> fact, the copy is not even attached to any editing domain), but indeed
> they are so when applied to the real model.

Again, this is a controlled and overtly non-transactional context, so
there should be no problem.


> I appreciate any discussions of our techniques and strategies.

It sounds like you've thought it through, and I don't see any problems.
The code snippet looked like a red flag, but on closer inspection,
it's just red herring. I suppose the only other suggestion would be
careful documentation of the preconditions for such a utility ... I
expect you've already covered that. :-)
Previous Topic:EMF Transaction: Problems with InterruptedException
Next Topic:Generating Edit Code into the Model Project
Goto Forum:
  


Current Time: Fri Apr 19 20:17:23 GMT 2024

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

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

Back to the top