The behaviour of transactions in Forte is a little convoluted. The successful case is easy and works as expected, but if an exception escapes a transaction block then the whole transaction stack is aborted (ie Transaction.isActive = false during the exception handler of the transaction block and afterwards).
Consider the following code fragment:
begin transaction begin begin transactaion -- something that throws an exception -- end transaction exception when err : GenericException do -- handle exception, don't rethrow it -- end begin transaction -- Some SQL -- end transaction end transaction
When the first transaction is escaped by the unhandled exception, the whole transaction stack is aborted, not just the inner transaction. So the second inner transaction creates a new transaction (the root of the transaction stack) rather than a sub-ordinate tranasaction of the outer transaction. This transaction will commit or rollback in its own right. Thus what seems like an inner transaction can actually commit when a prior part of the transaction has failed. Of course, if the thread of execution ever hits the outer end transaction an exception will be raised.
Note that returning from inside a transaction behaves as if it executes the end of the transactions properly, including throwing an exception if there has been a non-caught exception thrown from one of the inner transactions.
Since the transaction manager needs to handle returns from inside transactions by commiting them (or throwing an exception as appropriate), there must be a finally block which calls endTransction(). If the transaction stack has been aborted, then we need to make a special case of this endTransaction call NOT throwing a UsageException, but any other calls on the transaction manager or a second call to the endTransaction method throwing an exception