Transactions – the API

Modelio v3

Transaction management is available on the IModelingSession object. The IModelingSession object is the means for model access and model modifications. The current IModelingSession is the one which is bound to the model currently open in Modelio. It can be obtained from the Modelio instance.

A modeling session provides the following transaction creation method:

1class IModelingSession {
2    ...
3    public ITransaction createTransaction(String name);
4    ... 
5}

The returned transaction provides the following transaction management methods:

1public interface ITransaction extends AutoCloseable {
2    void commit();
3
4    void rollback();
5}

Warning: Never leave a transaction opened in the tool may be with the secret hope that someone will close it for you. When your code creates a transaction, it is responsible for closing it, either by a commit() or by a rollback().

For convenience ITransaction implements AutoCloseable so that it can be used in a try-with-resources statement. If commit() has not been called at the end of the statement, the transaction will be automatically rollbacked by its close() implementation.

A simple example

The following code snippet shows a typical use of a transaction to change the name of a Package:

 1IModelingSession session = Modelio.getInstance().getModelingSession();
 2Package myPackage = ...            // some code to get a Package instance 
 3
 4try (ITransaction t = session.createTransaction("Rename a package");) {
 5    
 6    myPackage.setName("new name");
 7
 8    t.commit();
 9}
  • line 4 – this construction known as try-with-resources will guarantees that the transaction will be properly closed in any circumstances (uncaught or unplanned exceptions occuring)
  • line 8 – if an uncaught exception occurs, this closing brace will automatically rollback and close the transaction created on line 3. Of course, this does not happen when everything is successful and when the transaction is sucessfully committed (line 16).

To ensure proper closing of transactions even when exceptions are thrown during model processing, we so highly recommend the use of the following ‘try with resources’ code pattern that this pattern can be thought as being mandatory.

Remark
Some exceptions may be raised by transaction management methods. This is not detailed here but has to be carefully dealt with by the Module developer in real life.

The proposed code snippet commits the transaction without any check that the resulting model is correct. This could violate the consistency rule of an ACID transaction. This is why, in Modelio, the commit() method will in any case audit the changes before committing them. If the audit succeeds, that is if no blocking errors are reported by the audit, the commit() operation will return true and the transaction will indeed be committed. If the audit fails, that is if there is at least one blocking error reported, the transaction will automatically rollback() and the commit() will fail, throwing an exception.

A more sophisticated example

In the following (quite stupid) code fragment a package is renamed . Prior to committing the transaction a check is made that no sibling package has the same name, allowing for deciding to commit() or to rollback() the transaction.

 1IModelingSession session = Modelio.getInstance().getModelingSession();
 2Package myPackage = ...         ;   // some code to get a Package instance 
 3String newName = "new name";
 4try (ITransaction t = session.createTransaction("Rename a package");) {
 5    myPackage.setName(newName);
 6
 7    int count = 0;
 8    for (ModelTree sibling : myPackage.getOwner().getOwnedElement()) {
 9        if (newName.equals(sibling.getName())) {
10            count++;
11        }
12    }
13
14    if ( count == 1 ) {
15        // Validate the transaction
16        t.commit();
17    } else {
18        // abort the transaction
19        t.rollback();
20    }
21} 

The above code fragment does not care about possibly thrown exceptions.
If not cared of, the exception processing may neglect to ‘close’ the transaction that was previously opened and which is possibly not yet closed (this depends on where the caught exception was thrown).
However, thanks to the ‘try with resource’ pattern (line 4) used here, the transaction is guaranteed to be finally rollbacked and closed should an uncaught exception be thrown. This is a major improvement compared to Modelio 2 where uncaught exceptions could lead to forever-opened transactions… Remember that unclosed transactions are evil…

Note: It remains of course possible to manually catch exceptions either within the processing code or at the ‘try’ level.