use of io.seata.tm.api.transaction.TransactionInfo in project seata by seata.
the class DbAndReportTcStateLogStore method beginTransaction.
protected void beginTransaction(StateMachineInstance machineInstance, ProcessContext context) {
if (sagaTransactionalTemplate != null) {
StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
TransactionInfo transactionInfo = new TransactionInfo();
transactionInfo.setTimeOut(stateMachineConfig.getTransOperationTimeout());
transactionInfo.setName(Constants.SAGA_TRANS_NAME_PREFIX + machineInstance.getStateMachine().getName());
try {
GlobalTransaction globalTransaction = sagaTransactionalTemplate.beginTransaction(transactionInfo);
machineInstance.setId(globalTransaction.getXid());
context.setVariable(DomainConstants.VAR_NAME_GLOBAL_TX, globalTransaction);
Map<String, Object> machineContext = machineInstance.getContext();
if (machineContext != null) {
machineContext.put(DomainConstants.VAR_NAME_GLOBAL_TX, globalTransaction);
}
} catch (ExecutionException e) {
String xid = null;
if (e.getTransaction() != null) {
xid = e.getTransaction().getXid();
}
throw new EngineExecutionException(e, e.getCode() + ", TransName:" + transactionInfo.getName() + ", XID: " + xid + ", Reason: " + e.getMessage(), FrameworkErrorCode.TransactionManagerError);
} finally {
if (Boolean.TRUE.equals(context.getVariable(DomainConstants.VAR_NAME_IS_ASYNC_EXECUTION))) {
RootContext.unbind();
RootContext.unbindBranchType();
}
}
}
}
use of io.seata.tm.api.transaction.TransactionInfo in project seata by seata.
the class TransactionTemplateTest method init.
@BeforeEach
public void init() throws Exception {
// mock transactionManager
TransactionManager transactionManager = mock(TransactionManager.class);
when(transactionManager.begin(null, null, DEFAULT_NAME, DEFAULT_TIME_OUT)).thenReturn(DEFAULT_XID);
when(transactionManager.commit(DEFAULT_XID)).thenReturn(GlobalStatus.Committed);
when(transactionManager.rollback(DEFAULT_XID)).thenReturn(GlobalStatus.Rollbacked);
when(transactionManager.getStatus(DEFAULT_XID)).thenReturn(GlobalStatus.Begin);
TransactionManagerHolder.set(transactionManager);
// mock transactionalExecutor
transactionalExecutor = Mockito.mock(TransactionalExecutor.class);
TransactionInfo txInfo = new TransactionInfo();
txInfo.setTimeOut(DEFAULT_TIME_OUT);
txInfo.setName(DEFAULT_NAME);
when(transactionalExecutor.getTransactionInfo()).thenReturn(txInfo);
}
use of io.seata.tm.api.transaction.TransactionInfo in project seata by seata.
the class TransactionTemplateTest method testRollBackRules.
private TransactionHook testRollBackRules(Set<RollbackRule> rollbackRules, Throwable throwable) throws Throwable {
TransactionHook transactionHook = Mockito.mock(TransactionHook.class);
// mock txInfo
TransactionInfo txInfo = new TransactionInfo();
txInfo.setTimeOut(DEFAULT_TIME_OUT);
txInfo.setName(DEFAULT_NAME);
txInfo.setRollbackRules(rollbackRules);
when(transactionalExecutor.getTransactionInfo()).thenReturn(txInfo);
when(transactionalExecutor.execute()).thenThrow(throwable);
TransactionHookManager.registerHook(transactionHook);
TransactionalTemplate template = new TransactionalTemplate();
try {
template.execute(transactionalExecutor);
} catch (Exception e) {
// catch rollback exception
}
return transactionHook;
}
use of io.seata.tm.api.transaction.TransactionInfo in project seata by seata.
the class TransactionalTemplate method execute.
/**
* Execute object.
*
* @param business the business
* @return the object
* @throws TransactionalExecutor.ExecutionException the execution exception
*/
public Object execute(TransactionalExecutor business) throws Throwable {
// 1. Get transactionInfo
TransactionInfo txInfo = business.getTransactionInfo();
if (txInfo == null) {
throw new ShouldNeverHappenException("transactionInfo does not exist");
}
// 1.1 Get current transaction, if not null, the tx role is 'GlobalTransactionRole.Participant'.
GlobalTransaction tx = GlobalTransactionContext.getCurrent();
// 1.2 Handle the transaction propagation.
Propagation propagation = txInfo.getPropagation();
SuspendedResourcesHolder suspendedResourcesHolder = null;
try {
switch(propagation) {
case NOT_SUPPORTED:
// If transaction is existing, suspend it.
if (existingTransaction(tx)) {
suspendedResourcesHolder = tx.suspend();
}
// Execute without transaction and return.
return business.execute();
case REQUIRES_NEW:
// If transaction is existing, suspend it, and then begin new transaction.
if (existingTransaction(tx)) {
suspendedResourcesHolder = tx.suspend();
tx = GlobalTransactionContext.createNew();
}
// Continue and execute with new transaction
break;
case SUPPORTS:
// If transaction is not existing, execute without transaction.
if (notExistingTransaction(tx)) {
return business.execute();
}
// Continue and execute with new transaction
break;
case REQUIRED:
// else continue and execute with new transaction.
break;
case NEVER:
// If transaction is existing, throw exception.
if (existingTransaction(tx)) {
throw new TransactionException(String.format("Existing transaction found for transaction marked with propagation 'never', xid = %s", tx.getXid()));
} else {
// Execute without transaction and return.
return business.execute();
}
case MANDATORY:
// If transaction is not existing, throw exception.
if (notExistingTransaction(tx)) {
throw new TransactionException("No existing transaction found for transaction marked with propagation 'mandatory'");
}
// Continue and execute with current transaction.
break;
default:
throw new TransactionException("Not Supported Propagation:" + propagation);
}
// 1.3 If null, create new transaction with role 'GlobalTransactionRole.Launcher'.
if (tx == null) {
tx = GlobalTransactionContext.createNew();
}
// set current tx config to holder
GlobalLockConfig previousConfig = replaceGlobalLockConfig(txInfo);
try {
// 2. If the tx role is 'GlobalTransactionRole.Launcher', send the request of beginTransaction to TC,
// else do nothing. Of course, the hooks will still be triggered.
beginTransaction(txInfo, tx);
Object rs;
try {
// Do Your Business
rs = business.execute();
} catch (Throwable ex) {
// 3. The needed business exception to rollback.
completeTransactionAfterThrowing(txInfo, tx, ex);
throw ex;
}
// 4. everything is fine, commit.
commitTransaction(tx);
return rs;
} finally {
// 5. clear
resumeGlobalLockConfig(previousConfig);
triggerAfterCompletion();
cleanUp();
}
} finally {
// If the transaction is suspended, resume it.
if (suspendedResourcesHolder != null) {
tx.resume(suspendedResourcesHolder);
}
}
}
use of io.seata.tm.api.transaction.TransactionInfo in project seata by seata.
the class AppTest method main.
/**
* The entry point of application.
*
* @param args the input arguments
*/
public static void main(String[] args) throws Throwable {
TMClient.init(APPLICATION_ID, TX_SERVICE_GROUP);
RMClient.init(APPLICATION_ID, TX_SERVICE_GROUP);
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("basic-test-context.xml");
final JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");
jdbcTemplate.update("delete from undo_log");
jdbcTemplate.update("delete from user0");
jdbcTemplate.update("insert into user0 (id, name, gmt) values (1, 'user0', '2019-01-01')");
jdbcTemplate.update("delete from user1");
final MyBusinessException bizException = new MyBusinessException("mock bizException");
TransactionalTemplate transactionalTemplate = new TransactionalTemplate();
try {
transactionalTemplate.execute(new TransactionalExecutor() {
@Override
public Object execute() throws Throwable {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Exception Rollback Business Begin ...");
}
jdbcTemplate.update("update user0 set name = 'xxx' where id = ?", new Object[] { 1 });
jdbcTemplate.update("insert into user1 (id, name, gmt) values (1, 'user1', '2019-01-01')");
throw bizException;
}
@Override
public TransactionInfo getTransactionInfo() {
TransactionInfo txInfo = new TransactionInfo();
txInfo.setTimeOut(TX_TIME_OUT);
txInfo.setName(TX_NAME);
return txInfo;
}
});
} catch (TransactionalExecutor.ExecutionException e) {
TransactionalExecutor.Code code = e.getCode();
if (code == TransactionalExecutor.Code.RollbackDone) {
Throwable businessEx = e.getOriginalException();
if (businessEx instanceof MyBusinessException) {
Assertions.assertEquals(((MyBusinessException) businessEx).getBusinessErrorCode(), bizException.businessErrorCode);
}
} else {
Assertions.assertFalse(false, "Not expected," + e.getMessage());
}
}
new ApplicationKeeper(context).keep();
}
Aggregations