TransactionContext { public void start() throws TransactionFailureException { currentTx = txClient.startShort(); for (TransactionAware txAware : txAwares) { try { txAware.startTx(currentTx); } catch (Throwable e) { String message = String.format("Unable to start transaction-aware '%s' for transaction %d. ", txAware.getTransactionAwareName(), currentTx.getTransactionId()); LOG.warn(message, e); txClient.abort(currentTx); throw new TransactionFailureException(message, e); } } } TransactionContext(TransactionSystemClient txClient, TransactionAware... txAwares);  TransactionContext(TransactionSystemClient txClient, Iterable<TransactionAware> txAwares); boolean addTransactionAware(TransactionAware txAware); boolean removeTransactionAware(TransactionAware txAware); void start(); void finish(); void abort(); void checkpoint(); @Nullable Transaction getCurrentTransaction(); void abort(TransactionFailureException cause);  }
@Test public void testStartAndRollbackFailure() throws TransactionFailureException, InterruptedException { ds1.failStartTxOnce = InduceFailure.ThrowException; TransactionContext context = newTransactionContext(ds1, ds2); try { context.start(); Assert.fail("start failed - exception should be thrown"); } catch (TransactionFailureException e) { Assert.assertEquals("start failure", e.getCause().getMessage()); } Assert.assertTrue(ds1.started); Assert.assertFalse(ds2.started); Assert.assertFalse(ds1.checked); Assert.assertFalse(ds2.checked); Assert.assertFalse(ds1.committed); Assert.assertFalse(ds2.committed); Assert.assertFalse(ds1.postCommitted); Assert.assertFalse(ds2.postCommitted); Assert.assertFalse(ds1.rolledBack); Assert.assertFalse(ds2.rolledBack); Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Aborted); }