Search in sources :

Example 1 with TransactionInfo

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();
            }
        }
    }
}
Also used : TransactionInfo(io.seata.tm.api.transaction.TransactionInfo) GlobalTransaction(io.seata.tm.api.GlobalTransaction) DbStateMachineConfig(io.seata.saga.engine.config.DbStateMachineConfig) DefaultStateMachineConfig(io.seata.saga.engine.impl.DefaultStateMachineConfig) StateMachineConfig(io.seata.saga.engine.StateMachineConfig) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException) ExecutionException(io.seata.tm.api.TransactionalExecutor.ExecutionException) EngineExecutionException(io.seata.saga.engine.exception.EngineExecutionException)

Example 2 with TransactionInfo

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);
}
Also used : TransactionManager(io.seata.core.model.TransactionManager) TransactionInfo(io.seata.tm.api.transaction.TransactionInfo) BeforeEach(org.junit.jupiter.api.BeforeEach)

Example 3 with TransactionInfo

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;
}
Also used : TransactionHook(io.seata.tm.api.transaction.TransactionHook) TransactionInfo(io.seata.tm.api.transaction.TransactionInfo)

Example 4 with TransactionInfo

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);
        }
    }
}
Also used : GlobalLockConfig(io.seata.core.model.GlobalLockConfig) TransactionException(io.seata.core.exception.TransactionException) Propagation(io.seata.tm.api.transaction.Propagation) SuspendedResourcesHolder(io.seata.tm.api.transaction.SuspendedResourcesHolder) ShouldNeverHappenException(io.seata.common.exception.ShouldNeverHappenException) TransactionInfo(io.seata.tm.api.transaction.TransactionInfo)

Example 5 with TransactionInfo

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();
}
Also used : ClassPathXmlApplicationContext(org.springframework.context.support.ClassPathXmlApplicationContext) TransactionalExecutor(io.seata.tm.api.TransactionalExecutor) TransactionInfo(io.seata.tm.api.transaction.TransactionInfo) JdbcTemplate(org.springframework.jdbc.core.JdbcTemplate) TransactionalTemplate(io.seata.tm.api.TransactionalTemplate) ApplicationKeeper(io.seata.common.ApplicationKeeper)

Aggregations

TransactionInfo (io.seata.tm.api.transaction.TransactionInfo)5 ApplicationKeeper (io.seata.common.ApplicationKeeper)1 ShouldNeverHappenException (io.seata.common.exception.ShouldNeverHappenException)1 TransactionException (io.seata.core.exception.TransactionException)1 GlobalLockConfig (io.seata.core.model.GlobalLockConfig)1 TransactionManager (io.seata.core.model.TransactionManager)1 StateMachineConfig (io.seata.saga.engine.StateMachineConfig)1 DbStateMachineConfig (io.seata.saga.engine.config.DbStateMachineConfig)1 EngineExecutionException (io.seata.saga.engine.exception.EngineExecutionException)1 DefaultStateMachineConfig (io.seata.saga.engine.impl.DefaultStateMachineConfig)1 GlobalTransaction (io.seata.tm.api.GlobalTransaction)1 TransactionalExecutor (io.seata.tm.api.TransactionalExecutor)1 ExecutionException (io.seata.tm.api.TransactionalExecutor.ExecutionException)1 TransactionalTemplate (io.seata.tm.api.TransactionalTemplate)1 Propagation (io.seata.tm.api.transaction.Propagation)1 SuspendedResourcesHolder (io.seata.tm.api.transaction.SuspendedResourcesHolder)1 TransactionHook (io.seata.tm.api.transaction.TransactionHook)1 BeforeEach (org.junit.jupiter.api.BeforeEach)1 ClassPathXmlApplicationContext (org.springframework.context.support.ClassPathXmlApplicationContext)1 JdbcTemplate (org.springframework.jdbc.core.JdbcTemplate)1