org.eclipse.emf.transaction
Interface TransactionalEditingDomain

All Superinterfaces:
EditingDomain
All Known Subinterfaces:
InternalTransactionalEditingDomain
All Known Implementing Classes:
TransactionalEditingDomainImpl

public interface TransactionalEditingDomain
extends EditingDomain

An extension of the EditingDomain API that applies transactional semantics to reading and writing the contents of an EMF ResourceSet.

Editing domains can be created in one of two ways: dynamically, using a TransactionalEditingDomain.Factory or statically by registration on the org.eclipse.emf.transaction.editingDomains extension point. The latter mechanism is the preferred way to define editing domains that can be shared with other applications. To create a new editing domain in code, simply invoke the static factory instance:

     TransactionalEditingDomain domain = TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain();
     ResourceSet rset = domain.getResourceSet();

     // or, create our own resource set and initialize the domain with it
     rset = new MyResourceSetImpl();
     domain = TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain(rset);
 

To share a named editing domain with other applications, the editing domain registry can be used to obtain domains by ID, creating them if necessary. Editing domain IDs are configured on an extension point providing the factory implementation that the registry uses to initialize them:

     <!-- In the plugin.xml -->
     <extension point="org.eclipse.emf.transaction.editingDomains">
     <editingDomain
           id="com.example.MyEditingDomain"
           factory="com.example.MyEditingDomainFactory"/>
     </extension>

     // in code, access the registered editing domain by:

     TransactionalEditingDomain myDomain = TransactionalEditingDomain.Registry.INSTANCE.getEditingDomain(
             "com.example.MyEditingDomain");
 

See the package documentation for further details of editing domain usage.

As of the EMF Transaction 1.2 release, editing domains may optionally be Adaptable to a variety of optional extension interfaces or "facets." It is recommended to implement the Adaptable interface and support adaptation to these interfaces to benefit from the services that they offer.

See Also:
TransactionalCommandStack, Transaction, ResourceSetListener

Nested Class Summary
static interface TransactionalEditingDomain.DefaultOptions
           Adapter interface provided by TransactionalEditingDomains that support the notion of default transaction options.
static interface TransactionalEditingDomain.Factory
          Interface defining the protocol for creating transactional editing domains.
static interface TransactionalEditingDomain.Registry
          An ID-based registry of shareable TransactionalEditingDomain instances.
 
Method Summary
 void addResourceSetListener(ResourceSetListener l)
          Adds a resource set listener to me, to receive notifications of changes to the resource set when transactions commit.
 RunnableWithResult<?> createPrivilegedRunnable(Runnable runnable)
          Wraps the specified runnable to give it access to the currently active transaction.
 void dispose()
          Disposes of this editing domain and any resources that it has allocated.
 String getID()
          Obtains my unique ID.
 void removeResourceSetListener(ResourceSetListener l)
          Removes a resource set listener from me.
 Object runExclusive(Runnable read)
          Runs an operation that requires exclusive access to my resource set, for reading.
 void setID(String id)
          Sets my unique ID.
 void yield()
          Temporarily yields access to another read-only transaction.
 
Methods inherited from interface org.eclipse.emf.edit.domain.EditingDomain
createCommand, createOverrideCommand, createResource, getChildren, getClipboard, getCommandStack, getNewChildDescriptors, getOptimizeCopy, getParent, getResourceSet, getRoot, getTreePath, isControllable, isReadOnly, loadResource, setClipboard, treeIterator
 

Method Detail

getID

String getID()
Obtains my unique ID. This is the ID under which I am registered in the TransactionalEditingDomain.Registry (if I am registered).

Returns:
my unique identifier
See Also:
TransactionalEditingDomain.Registry.getEditingDomain(String)

setID

void setID(String id)
Sets my unique ID. If I am currently registered in the TransactionalEditingDomain.Registry, then I am re-registered under this new ID. However, if I am registered statically on the org.eclipse.emf.transaction.editingDomains extension point, then my ID cannot be changed.

Parameters:
id - my new unique identifier
Throws:
IllegalArgumentException - if I am a statically registered domain
See Also:
getID(), TransactionalEditingDomain.Registry.add(String, TransactionalEditingDomain)

addResourceSetListener

void addResourceSetListener(ResourceSetListener l)
Adds a resource set listener to me, to receive notifications of changes to the resource set when transactions commit. This method has no effect if the specified listeners is already attached to me.

Parameters:
l - a new resource set listener
Throws:
IllegalArgumentException - if the listener declares both that it wants only pre-commit events and that it wants only post-commit events (a logical contradiction)
See Also:
ResourceSetListener.isPrecommitOnly(), ResourceSetListener.isPostcommitOnly()

removeResourceSetListener

void removeResourceSetListener(ResourceSetListener l)
Removes a resource set listener from me. This method has no effect if the listener is not currently attached to me.

Parameters:
l - a resource set listener to remove

runExclusive

Object runExclusive(Runnable read)
                    throws InterruptedException
Runs an operation that requires exclusive access to my resource set, for reading. The specified runnable is executed in a read-only transaction. If the runnable implements the RunnableWithResult interface, then its result is returned after it completes. Moreover, (and this is a very good reason to implement this extension interface), if the transaction rolls back on commit, then the RunnableWithResult is provided with the error status indicating this condition. Even read-only transactions can roll back when, for example, another thread concurrently modifies the model (in violation of the transaction protocol), and it is important to know when corrupted data may have been read.

Note that this method will block the current thread until exclusive access to the resource set can be obtained. However, it is safe to call this method on the Eclipse UI thread because special precaution is taken to ensure that liveness is maintained (using mechanisms built into the Job Manager).

Note: Since the 1.2 release, the TransactionUtil.runExclusive(TransactionalEditingDomain, RunnableWithResult) utility provides type-safe execution of runnables returning results and should be preferred over this API.

Parameters:
read - a read-only operation to execute
Returns:
the result of the read operation if it is a RunnableWithResult and the transaction did not roll back; null, otherwise
Throws:
InterruptedException - if the current thread is interrupted while waiting for access to the resource set
See Also:
TransactionUtil#runExclusive(RunnableWithResult), Transaction.commit()

yield

void yield()
Temporarily yields access to another read-only transaction. The TransactionalEditingDomain supports any number of pseudo-concurrent read-only transactions. Transactions that are expected to be long-running should yield frequently, as a task running in a progress monitor is expected to check for cancellation frequently. However, there is a higher cost (in time) associated with yielding, so it should not be overdone.

Only read-only transactions may yield, and only the transaction that is currently active in the editing domain may yield. The yielding transaction may be nested, but not within a read/write transaction at any depth.

Upon yielding, some other read-only transaction that is attempting to start or to return from a yield will take control of the editing domain. Control is never yielded to a read/write transaction (not even to a read-only transaction nested in a read/write) because this would introduce dirty reads (transactions reading uncommitted changes). If there are no other read-only transactions to receive the transfer of control, then the call returns immediately. Otherwise, control is transferred in FIFO fashion to waiting transactions.


createPrivilegedRunnable

RunnableWithResult<?> createPrivilegedRunnable(Runnable runnable)
Wraps the specified runnable to give it access to the currently active transaction. This is useful for two or more cooperating threads to share a transaction (read-only or read-write), executing code in the a runnable on one thread in the context of another thread's transaction.

For example, in an Eclipse UI application, this might be used when a long-running task in a modal context thread needs to synchronously execute some operation on the UI thread, which operation needs to read or write the editing domain. e.g.,

     Runnable uiBoundAction = // ...
     Runnable privileged = domain.createPrivilegedRunnable(uiBoundAction);
     Display.syncExec(privileged);
 

Note that it is critically important that this mechanism only be used to share a transaction with another thread synchronously. Or, more generally, during the execution of the privileged runnable, the thread that originally owned the transaction no longer does, and may not access the editing domain. Upon completion of the privileged runnable, the transaction is returned to its original owner.

Also, the resulting runnable may only be executed while the currently active transaction remains active. Any attempt to execute the runnable after this transaction has committed or while a nested transaction is active will result in an IllegalStateException.

Note: Since the 1.2 release, the TransactionUtil.createPrivilegedRunnable(TransactionalEditingDomain, RunnableWithResult) utility provides type-safe privileged access for runnables returning results and should be preferred over this API.

Type Parameters:
T - the result type of the RunnableWithResult if such is the read argument
Parameters:
runnable - a runnable to execute in the context of the active transaction, on any thread
Returns:
the privileged runnable. If the wrapped runnable is a RunnableWithResult, then the privileged runnable will inherit its result when it completes
Throws:
IllegalStateException - on an attempt by a thread that does not own the active transaction to create a privileged runnable. This prevents "theft" of transactions by malicious code. Note also that this implies an exception if there is no active transaction at the time of this call
See Also:
TransactionUtil.createPrivilegedRunnable(TransactionalEditingDomain, RunnableWithResult)

dispose

void dispose()
Disposes of this editing domain and any resources that it has allocated. Editing domains must be disposed when they are no longer in use, but only by the client that created them (in case of sharing of editing domains).

Note that editing domains registered on the extension point may not be disposed.


Copyright 2002, 2007 IBM Corporation and others.
All Rights Reserved.