Skip to main content
Version: 10.2.8

Retry failed Transactions

To use the ODF 2 framework more conveniently, you can apply the following techniques when working with transactional tasks and retrying failed Transactions.

Ready-to-use transactional tasks

The new TransactionalTask interface is now the easiest way to write a task that runs in a transactional context. The framework checks if a Transaction is present in the input and passes it to the output.

@BotTask
public class MyTransactionalTask implements TransactionalTask {

@Override
public boolean shouldRun(CurrentTransaction currentTransaction) {
return currentTransaction.getStatus()
.filter("STARTED"::equals)
.isPresent(); // this task will run only if transaction status is "STARTED"
}

@Override
public void run(CurrentTransaction transaction, TransactionResult result) {
// transaction.isPresent() is always true
// TransactionResult is populated with task input

transaction.setStatus("UPDATED");
// changes will be saved to datastore and applied to TransactionResult after this method finishes

result.setColumn("some_additional_column", "some value");
// you can add custom data to output
}

}

Transaction skipping up to specific task

A new mechanism allows tagging a Transaction with the name of the task it is intended for. All other tasks will just skip it, until it reaches its destination.

For the mechanism to work correctly, all the tasks in a Business Process (BP) must be based on BaseTransactionalTask. Out-of-the-box ODF 2 tasks based on AbstractTransactionConsumingTaskRunner support the feature.

@BotTask
public class OtherTransactionalTask implements TransactionalTask {

@Override
public void run(CurrentTransaction transaction, TransactionResult result) {
transaction.get().setSkipUntil("MyTransactionalTask");
// all the following tasks in the Business Process will skip this transaction
// until it reaches MyTransactionalTask
}

}

Error handling in sub-transactions

Error handling tasks based on AbstractPersistingErrorHandling can specify whether to propagate the error raised by a sub-transaction to its siblings.

public class MyErrorHandlingLogic extends AbstractPersistingErrorHandling {

// some code omitted for clarity

@Override
protected boolean shouldSetHasErrorStatusForSiblingTransactionsshouldSetHasErrorStatusForSiblingTransactions(Transaction transaction, Exception e, OdfTask odfTask) {
// returns true to fail all sibling sub-transaction; returns false to fail only current sub-transaction
}
}

Retrying of failed Transactions

Whether the error handling is done in the same BP or a separate one, Transaction skipping allows to organize retrying of failed Transactions in a couple of simple steps:

  1. Mark an erroneous Transaction with skip_until for the task that must be retried.

  2. Route the Transaction to the beginning of the BP that contains that task.

ODF 2 now offers a Monitor Task named TransactionGenerateAndCollectMonitorTask that performs two roles:

  • Polls for the data as usual.
  • Polls for existing Transactions with a specified error status, clears this status, and sends the Transactions into a BP.
example

So, if:

a. The error handling task sets a correct skip_until attribute for a failed Transaction and changes its error status to, for example, RETRY, and

b. The monitor at the start of the BP based on TransactionGenerateAndCollectMonitorTask looks for Transactions with the RETRY error status,

then a failed Transaction is collected by this monitor and sent into the BP with a cleared error status. It is skipped by all tasks until it reaches the desired task, and then it is processed as usual.

tip

See a detailed example for the architecture in odf2-example-project.