Code review comment: @wyb Good suggestion, this will make the implementation more clearly.

Code under review:
public ResultWrapper handle(BaseRequest request, BaseResponse response) throws UserException {
        TransactionOperation txnOperation = txnOperationParams.getTxnOperation();
        String dbName = txnOperationParams.getDbName();
        String tableName = txnOperationParams.getTableName();
        String label = txnOperationParams.getLabel();
        LoadJobSourceType sourceType = txnOperationParams.getSourceType();
        Long timeoutMillis = txnOperationParams.getTimeoutMillis();
        Body requestBody = txnOperationParams.getBody();
        LOG.info("Handle transaction without channel info, label: {}, source: {}", label, sourceType);

        Database db = Optional.ofNullable(GlobalStateMgr.getCurrentState().getDb(dbName))
                .orElseThrow(() -> new UserException(String.format("Database[%s] does not exist.", dbName)));

        TransactionResult result = null;
        switch (txnOperation) {
            case TXN_BEGIN:
                Table table = Optional.ofNullable(db.getTable(tableName))
                        .orElseThrow(() -> new UserException(
                                String.format("Table[%s.%s] does not exist.", dbName, tableName)));
                result = handleBeginTransaction(db, table, label, sourceType, timeoutMillis);
                break;
            case TXN_PREPARE:
                result = handlePrepareTransaction(
                        db, label,
                        Optional.ofNullable(requestBody.getCommittedTablets()).orElse(new ArrayList<>(0)),
                        Optional.ofNullable(requestBody.getFailedTablets()).orElse(new ArrayList<>(0))
                );
                break;
            case TXN_COMMIT:
                result = handleCommitTransaction(db, label, timeoutMillis);
                break;
            case TXN_ROLLBACK:
                result = handleRollbackTransaction(
                        db, label,
                        Optional.ofNullable(requestBody.getFailedTablets()).orElse(new ArrayList<>(0))
                );
                break;
            case TXN_LOAD:
                break;
            default:
                throw new UserException("Unsupported operation: " + txnOperation);
        }

        return new ResultWrapper(result);
    }

Line commented on: case TXN_ROLLBACK:

Revised code:
public ResultWrapper handle(BaseRequest request, BaseResponse response) throws UserException {
        TransactionOperation txnOperation = txnOperationParams.getTxnOperation();
        String dbName = txnOperationParams.getDbName();
        String label = txnOperationParams.getLabel();
        Long timeoutMillis = txnOperationParams.getTimeoutMillis();
        LOG.info("Handle transaction without channel info, label: {}", label);

        Database db = Optional.ofNullable(GlobalStateMgr.getCurrentState().getDb(dbName))
                .orElseThrow(() -> new UserException(String.format("Database[%s] does not exist.", dbName)));

        TransactionResult result = null;
        switch (txnOperation) {
            case TXN_BEGIN:
            case TXN_PREPARE:
            case TXN_LOAD:
                break;
            case TXN_COMMIT:
                result = handleCommitTransaction(db, label, timeoutMillis);
                break;
            case TXN_ROLLBACK:
                result = handleRollbackTransaction(db, label);
                break;
            default:
                throw new UserException("Unsupported operation: " + txnOperation);
        }

        return new ResultWrapper(result);
    }