Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Eclipse EMF Model Transaction Development Guide
Previous Page Home Next Page

Implementing Triggers

When they attempt to commit, Transactions use the EMF Validation Framework to validate the changes that have occurred during the time that they were active. If this validation finds problems with IStatus.ERROR severity or worse, then the transaction rolls back instead of committing, and the commit throws a RollbackException to the client.

However, client applications do not like it when their transactions are rolled back in this way. The assurance of data integrity is good, but a user's workflow generally is diverted. Given that these integrity constraints are essential to the health of the user's data, then, an application needs a way to be proactive in ensuring that they will be met. This mechanism is the pre-commit listener, better known as a trigger for its analogy to triggers in relational database management systems.

Trigger API
[ as SVG]

When a client commits a read/write transaction, the transaction first notifies pre-commit listeners that it is about to commit, invoking the transactionAboutToCommit(ResourceSetChangeEvent) call-back. The listeners respond by returning trigger Commands, if necessary, that the transaction executes to perform additional changes to bring the resource set contents back into a consistent state.

Triggers only return commands to be executed by the transaction. They cannot directly change the model because, like the post-commit listeners, they are called in a read-only transaction (nested within the read/write transaction that is committing). When the transaction has received all of the trigger commands from its listeners, it executes these commands in a nested read/write transaction. The pre-commit procedure is recursive; this transaction that executes the trigger commands will, itself, invoke pre-commit listeners to ensure integrity of the changes that the triggers effect. Also, all of the changes performed by triggers are validated in the final stage of the original transaction's commit.

If, for some reason, a trigger cannot provide the commands that it needs to ensure data integrity, then it may throw a RollbackException to force the transaction to roll back. For example, the trigger may be intended to keep the EMF resource set synchronized with some other data store. If that data store should become inaccessible, then the trigger cannot perform its function.

For details of the ResourceSetChangeEvent and the NotificationFilter API and statically registering listeners on editing domains, see the discussion of resource set listeners.

// trigger ensuring that all libraries have names
class MyListener extends ResourceSetListenerImpl {
    MyListener() { // only interested in changes to Library objects
        super(NotificationFilter.createNotifierTypeFilter(
                   EXTLibraryPackage.Literals.LIBRARY));
    }

    public Command transactionAboutToCommit(ResourceSetChangeEvent event)
           throws RollbackException {
           
        List commands = new ArrayList();
        Iterator iter = event.getNotifications().iterator();
        
        while (iter.hasNext()) {
            Notification next = (Notification) iter.next();
            Library library = (Library) next.getNotifier();
            if (library.getName() == null)
                commands.add(SetCommand.create(
                    event.getEditingDomain(), library,
                    EXTLibraryPackage.Literals.LIBRARY__NAME, "A library"));
        }

        return commands.isEmpty()? null : new CompoundCommand(commands);
    }
}

As for post-commit listeners, the EMF Transaction API provides a convenient abstract class that dispatches Notifications one by one to a trigger: the TriggerListener. A subclass needs only to implement the trigger() method to return a command in response to a notification. The TriggerListener class takes care of combining the results the results into an appropriate compound command.

class MyTriggerListener extends TriggerListener {
    MyListener() { // only interested in changes to Library objects
        super(NotificationFilter.createNotifierTypeFilter(
                   EXTLibraryPackage.Literals.LIBRARY));
    }

    protected Command trigger(TransactionalEditingDomain domain,
            Notification notification) throws RollbackException {
        
        Library library = (Library) next.getNotifier();
        if (library.getName() == null) {
            return SetCommand.create(domain, library,
                EXTLibraryPackage.Literals.LIBRARY__NAME, "A library");
        }

        return null;
    }
}

Copyright (c) 2006, 2007 IBM Corporation and others. All Rights Reserved.


 
 
  Published under the terms of the Eclipse Public License Version 1.0 ("EPL") Design by Interspire