Transactional editing domains are specialized EditingDomains that add
transaction semantics to editing operations, in order to promote data integrity. This consists of
two primary controls: ResourceSet locking for coordination of concurrent
threads and automatic rollback of changes in case of violations of data integrity.
Creating Transactional Editing Domains
TransactionalEditingDomains
may be created by an application at run-time, using the static
Factory
instance. The factory can optionally create an editing domain on a ResourceSet
provided by the client, or it can create a default resource set. In either case, the
ResourceSet is thenceforward managed by transactions.
[
as SVG]
ResourceSet rset = getResourceSet(); // access some hypothetical resource set
TransactionalEditingDomain domain = TransactionalEditingDomain.Factory.INSTANCE
.createEditingDomain(rset);
// begin working with the editing domain
Registering Editing Domains
We saw above how transactional editing domains can be created at run-time. This is good for applications
that only need their own editing domain to edit their own EMF resources. However, what if an
application or a plug-in wants to share its editing domain with other applications, so that they may
cooperatively edit a common set of resources? The
TransactionalEditingDomain.Registry
provides the means by which an application can publish its editing domain under a unique identifier for
other to find and work with. The static TransactionalEditingDomain.Registry
instance is the most appropriate registry in which to do this:
TransactionalEditingDomain.Registry.INSTANCE.add("org.eclipse.example.MyDomain", domain);
Then, another application or editor can use this ID to look up the editing domain instance:
TransactionalEditingDomain shared = TransactionalEditingDomain.Registry.INSTANCE.getEditingDomain(
"org.eclipse.example.MyDomain");
// begin working with the editing domain
This now raises a problem that is fairly common with registries of shared objects in Eclipse: what if
the application that retrieves this editing domain from the registry needs to use it before
the provider of the domain has registered it? Or even before the provider has been activated? The
EMF Transaction API provides the
org.eclipse.emf.transaction.editingDomains
extension point on which to statically register an editing domain. Whenever any client application (and
this includes the one that registers the domain) wishes to access the registered editing domain, it
simply retrieves it from the registry by ID. On the first such access, the registry creates the editing
domain using the factory implementation referenced on the extension point. If no factory is specified,
then the default static instance is used:
<extension point="org.eclipse.emf.transaction.editingDomains">
<domain id="org.eclipse.example.MyDomain"
factory="org.eclipse.example.MyCustomFactory"/>
</extension>
// the factory implementation
public class MyCustomFactory extends TransactionalEditingDomainImpl.FactoryImpl {
public TransactionalEditingDomain createEditingDomain() {
TransactionalEditingDomain result = super.createEditingDomain();
// customize my editing domain in some way
// ...
return result;
}
}
The registry will invoke the zero-argument factory method to create the editing domain. The recommended
way to create an editing domain factory is to extend the default implementation, as above, and to
delegate the actual domain instantiation to the superclass. Otherwise, it is necessary to invoke the
FactoryImpl.mapResourceSet() method to ensure that the traceability between
the ResourceSet and the editing domain is established.
Finding an Object's Editing Domain
It will often happen that a client of the EMF Transaction API knows that an object or a
resource is in a transactional editing domain (perhaps because it requires this), but not
which editing domain. The
TransactionUtil
class provides utility methods that obtain the editing domain that manages an
EObject, a Resource, or a
ResourceSet.
EObject subject = getSubject(); // some object to operate on
TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(subject);
if (domain != null) {
// do something with the subject in a transaction
}
Sharing Objects and Resources with Other Resource Sets
An application that is working with multiple resource sets, some in transactional editing
domains and others not, may occasionally find that it needs to move objects and/or
resources from a non-transactional resource set to a transactional resource set or vice-versa.
When a resource or an object comes into a transactional context, it because subject to that
transactional editing domain and will continue to be even after it is removed from that
context. Even after it is moved into an otherwise non-transactional resource set, it will
continue to be managed by the editing domain that formerly contained it.
The
TransactionUtil
class provides static utilities that will dissociate an object or a resource from a
transactional editing domain that had managed it. After removing an object or a resource
from its container, the disconnectFromEditingDomain() method
breaks its ties to the editing domain. It is then free to be added to another transactional
editing domain or to a non-transactional resource set.
If the object or resource is not disconnected from its former transactional editing domain
when it is added to another transactional editing domain's resource set, then it will be
subject to both editing domains. Such an object can only safely be accessed in
simultaneous transactions on both editing domains. In practice, this is not feasible.
Resource resource = getResource(); // a resource to move to another resource set
TransactionalEditingDomain formerDomain = TransactionUtil.getEditingDomain(resource);
ResourceSet newResourceSet = getNewResourceSet(); // resource set to move to
newResourceSet.getResources().add(resource); // first, move the resource
if (domain != null) {
// then disconnect it from the former editing domain
TransactionUtil.disconnectFromEditingDomain(resource);
}
Disposing of Editing Domains
When an application has finished with an editing domain, or has finished with transactional
editing of the contents of a resource set, the editing domain can be deactivated by calling
the dispose() method.
domain.dispose();
A registered editing domain is first removed when the registry when it is disposed. In the
case that the editing domain is statically registered on the extension point, however, it
cannot be unregistered and, hence, cannot be disposed.
Copyright (c) 2006, 2007 IBM Corporation and others. All Rights Reserved.