diff --git a/all/pom.xml b/all/pom.xml index 56f1e0a827b..eb5965bd35d 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -327,6 +327,11 @@ + + io.seata + manual-api + ${project.version} + diff --git a/build/pom.xml b/build/pom.xml index f3b7f14efed..f0ea057e305 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -63,7 +63,7 @@ - 1.6.0-SNAPSHOT + 1.6.66-SNAPSHOT 1.8 diff --git a/common-api/pom.xml b/common-api/pom.xml new file mode 100644 index 00000000000..ef47668dd5a --- /dev/null +++ b/common-api/pom.xml @@ -0,0 +1,76 @@ + + + + + io.seata + seata-parent + ${revision} + + 4.0.0 + common-api + common-api ${project.version} + jar + + + + + ${project.groupId} + seata-tm + ${project.version} + + + ${project.groupId} + seata-rm-datasource + ${project.version} + + + ${project.groupId} + seata-rm + ${project.version} + + + ${project.groupId} + seata-serializer-all + ${project.version} + + + ${project.groupId} + seata-common + ${project.version} + + + + + + org.springframework + spring-context + + + org.springframework + spring-jdbc + + + + com.alibaba + fastjson + + + + + diff --git a/common-api/src/main/java/io/seata/commonapi/autoproxy/DefaultTransactionAutoProxy.java b/common-api/src/main/java/io/seata/commonapi/autoproxy/DefaultTransactionAutoProxy.java new file mode 100644 index 00000000000..e170923b976 --- /dev/null +++ b/common-api/src/main/java/io/seata/commonapi/autoproxy/DefaultTransactionAutoProxy.java @@ -0,0 +1,101 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.commonapi.autoproxy; + +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.util.CollectionUtils; +import io.seata.commonapi.remoting.RemotingDesc; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * the default transaction auto proxy + * + * @author ruishansun + */ +public class DefaultTransactionAutoProxy { + + /** + * all the transaction auto proxy + */ + protected static final List ALL_TRANSACTION_AUTO_PROXIES = new ArrayList<>(); + /** + * method interceptor map, beanName -> IsTransactionProxyResult + */ + private static final Map METHOD_INTERCEPTOR_MAP = new ConcurrentHashMap<>(); + + private static class SingletonHolder { + private static final DefaultTransactionAutoProxy INSTANCE = new DefaultTransactionAutoProxy(); + } + + /** + * Get the default transaction auto proxy + * + * @return the default transaction auto proxy + */ + public static DefaultTransactionAutoProxy get() { + return SingletonHolder.INSTANCE; + } + + /** + * Instantiates a new default transaction auto proxy + */ + protected DefaultTransactionAutoProxy() { + initTransactionAutoProxy(); + } + + /** + * init transaction auto proxy + */ + private void initTransactionAutoProxy() { + List proxies = EnhancedServiceLoader.loadAll(TransactionAutoProxy.class); + if (CollectionUtils.isNotEmpty(proxies)) { + ALL_TRANSACTION_AUTO_PROXIES.addAll(proxies); + } + } + + /** + * whether is transaction auto proxy + * + * @param beanName the beanName + * @param remotingDesc the remotingDesc + * @return true or false + */ + public boolean isTransactionAutoProxy(String beanName, RemotingDesc remotingDesc) { + for (TransactionAutoProxy proxy : ALL_TRANSACTION_AUTO_PROXIES) { + IsTransactionProxyResult result = proxy.isTransactionProxyTargetBean(remotingDesc); + if (result.isProxyTargetBean()) { + METHOD_INTERCEPTOR_MAP.put(beanName, result); + return true; + } + } + return false; + } + + /** + * get the IsTransactionProxyResult + * + * @param beanName the beanName + * @return the IsTransactionProxyResult + */ + public IsTransactionProxyResult getIsProxyTargetBeanResult(String beanName) { + IsTransactionProxyResult result = METHOD_INTERCEPTOR_MAP.get(beanName); + return result != null ? result : new IsTransactionProxyResult(); + } +} \ No newline at end of file diff --git a/common-api/src/main/java/io/seata/commonapi/autoproxy/IsTransactionProxyResult.java b/common-api/src/main/java/io/seata/commonapi/autoproxy/IsTransactionProxyResult.java new file mode 100644 index 00000000000..c3e6097f7eb --- /dev/null +++ b/common-api/src/main/java/io/seata/commonapi/autoproxy/IsTransactionProxyResult.java @@ -0,0 +1,75 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.commonapi.autoproxy; + +import org.aopalliance.intercept.MethodInterceptor; + +/** + * whether is the transaction proxy result + * + * @author ruishansun + */ +public class IsTransactionProxyResult { + + /** + * whether proxied by transaction bean + */ + private boolean isProxyTargetBean; + + /** + * whether used common fence + */ + private boolean useCommonFence; + + /** + * transaction proxy method + */ + private MethodInterceptor methodInterceptor; + + private ManualApiExecute manualApiExecute; + + public boolean isProxyTargetBean() { + return isProxyTargetBean; + } + + public void setProxyTargetBean(boolean proxyTargetBean) { + isProxyTargetBean = proxyTargetBean; + } + + public boolean isUseCommonFence() { + return useCommonFence; + } + + public void setUseCommonFence(boolean useCommonFence) { + this.useCommonFence = useCommonFence; + } + + public MethodInterceptor getMethodInterceptor() { + return methodInterceptor; + } + + public void setMethodInterceptor(MethodInterceptor methodInterceptor) { + this.methodInterceptor = methodInterceptor; + } + + public ManualApiExecute getManualApiExecute() { + return manualApiExecute; + } + + public void setManualApiExecute(ManualApiExecute manualApiExecute) { + this.manualApiExecute = manualApiExecute; + } +} \ No newline at end of file diff --git a/common-api/src/main/java/io/seata/commonapi/autoproxy/ManualApiExecute.java b/common-api/src/main/java/io/seata/commonapi/autoproxy/ManualApiExecute.java new file mode 100644 index 00000000000..29046cee633 --- /dev/null +++ b/common-api/src/main/java/io/seata/commonapi/autoproxy/ManualApiExecute.java @@ -0,0 +1,23 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.commonapi.autoproxy; + +import java.lang.reflect.Method; + +public interface ManualApiExecute { + + void manualApiBefore(Method method, Object[] arguments) throws Throwable; +} diff --git a/common-api/src/main/java/io/seata/commonapi/autoproxy/TransactionAutoProxy.java b/common-api/src/main/java/io/seata/commonapi/autoproxy/TransactionAutoProxy.java new file mode 100644 index 00000000000..a569f90a639 --- /dev/null +++ b/common-api/src/main/java/io/seata/commonapi/autoproxy/TransactionAutoProxy.java @@ -0,0 +1,34 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.commonapi.autoproxy; + +import io.seata.commonapi.remoting.RemotingDesc; + +/** + * The interface Transaction Auto Proxy. Proxied by tcc/saga with SPI. + * + * @author ruishansun + */ +public interface TransactionAutoProxy { + + /** + * Whether it is transaction auto proxy? (tcc or saga) + * + * @param remotingDesc the remotingDesc + * @return the IsTransactionProxyResult + */ + IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remotingDesc); +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/TCCFenceHandler.java b/common-api/src/main/java/io/seata/commonapi/fence/CommonFenceHandler.java similarity index 72% rename from tcc/src/main/java/io/seata/rm/tcc/TCCFenceHandler.java rename to common-api/src/main/java/io/seata/commonapi/fence/CommonFenceHandler.java index 86222acd60f..492d4ccf72f 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TCCFenceHandler.java +++ b/common-api/src/main/java/io/seata/commonapi/fence/CommonFenceHandler.java @@ -13,48 +13,49 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc; - -import java.lang.reflect.Method; -import java.sql.Connection; -import java.util.ArrayList; -import java.util.Date; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import javax.sql.DataSource; +package io.seata.commonapi.fence; import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.exception.SkipCallbackWrapperException; import io.seata.common.executor.Callback; import io.seata.common.thread.NamedThreadFactory; -import io.seata.rm.tcc.constant.TCCFenceConstant; -import io.seata.rm.tcc.exception.TCCFenceException; -import io.seata.rm.tcc.store.TCCFenceDO; -import io.seata.rm.tcc.store.TCCFenceStore; -import io.seata.rm.tcc.store.db.TCCFenceStoreDataBaseDAO; +import io.seata.commonapi.fence.constant.CommonFenceConstant; +import io.seata.commonapi.fence.exception.CommonFenceException; +import io.seata.commonapi.fence.store.CommonFenceDO; +import io.seata.commonapi.fence.store.CommonFenceStore; +import io.seata.commonapi.fence.store.db.CommonFenceStoreDataBaseDAO; +import io.seata.commonapi.remoting.TwoPhaseResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionTemplate; +import javax.sql.DataSource; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.util.ArrayList; +import java.util.Date; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + /** - * TCC Fence Handler(idempotent, non_rollback, suspend) + * Common Fence Handler(idempotent, non_rollback, suspend) * * @author kaka2code */ -public class TCCFenceHandler { +public class CommonFenceHandler { - private TCCFenceHandler() { + private CommonFenceHandler() { throw new IllegalStateException("Utility class"); } - private static final Logger LOGGER = LoggerFactory.getLogger(TCCFenceHandler.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CommonFenceHandler.class); - private static final TCCFenceStore TCC_FENCE_DAO = TCCFenceStoreDataBaseDAO.getInstance(); + private static final CommonFenceStore COMMON_FENCE_DAO = CommonFenceStoreDataBaseDAO.getInstance(); private static DataSource dataSource; @@ -84,19 +85,19 @@ private TCCFenceHandler() { } public static DataSource getDataSource() { - return TCCFenceHandler.dataSource; + return CommonFenceHandler.dataSource; } public static void setDataSource(DataSource dataSource) { - TCCFenceHandler.dataSource = dataSource; + CommonFenceHandler.dataSource = dataSource; } public static void setTransactionTemplate(TransactionTemplate transactionTemplate) { - TCCFenceHandler.transactionTemplate = transactionTemplate; + CommonFenceHandler.transactionTemplate = transactionTemplate; } /** - * tcc prepare method enhanced + * common prepare method enhanced * * @param xid the global transaction id * @param branchId the branch transaction id @@ -108,15 +109,15 @@ public static Object prepareFence(String xid, Long branchId, String actionName, return transactionTemplate.execute(status -> { try { Connection conn = DataSourceUtils.getConnection(dataSource); - boolean result = insertTCCFenceLog(conn, xid, branchId, actionName, TCCFenceConstant.STATUS_TRIED); - LOGGER.info("TCC fence prepare result: {}. xid: {}, branchId: {}", result, xid, branchId); + boolean result = insertCommonFenceLog(conn, xid, branchId, actionName, CommonFenceConstant.STATUS_TRIED); + LOGGER.info("Common fence prepare result: {}. xid: {}, branchId: {}", result, xid, branchId); if (result) { return targetCallback.execute(); } else { - throw new TCCFenceException(String.format("Insert tcc fence record error, prepare fence failed. xid= %s, branchId= %s", xid, branchId), + throw new CommonFenceException(String.format("Insert common fence record error, prepare fence failed. xid= %s, branchId= %s", xid, branchId), FrameworkErrorCode.InsertRecordError); } - } catch (TCCFenceException e) { + } catch (CommonFenceException e) { if (e.getErrcode() == FrameworkErrorCode.DuplicateKeyException) { LOGGER.error("Branch transaction has already rollbacked before,prepare fence failed. xid= {},branchId = {}", xid, branchId); addToLogCleanQueue(xid, branchId); @@ -131,10 +132,10 @@ public static Object prepareFence(String xid, Long branchId, String actionName, } /** - * tcc commit method enhanced + * common commit method enhanced * * @param commitMethod commit method - * @param targetTCCBean target tcc bean + * @param targetTCCBean target common bean * @param xid the global transaction id * @param branchId the branch transaction id * @param args commit method's parameters @@ -145,22 +146,22 @@ public static boolean commitFence(Method commitMethod, Object targetTCCBean, return transactionTemplate.execute(status -> { try { Connection conn = DataSourceUtils.getConnection(dataSource); - TCCFenceDO tccFenceDO = TCC_FENCE_DAO.queryTCCFenceDO(conn, xid, branchId); - if (tccFenceDO == null) { - throw new TCCFenceException(String.format("TCC fence record not exists, commit fence method failed. xid= %s, branchId= %s", xid, branchId), + CommonFenceDO commonFenceDO = COMMON_FENCE_DAO.queryCommonFenceDO(conn, xid, branchId); + if (commonFenceDO == null) { + throw new CommonFenceException(String.format("Common fence record not exists, commit fence method failed. xid= %s, branchId= %s", xid, branchId), FrameworkErrorCode.RecordNotExists); } - if (TCCFenceConstant.STATUS_COMMITTED == tccFenceDO.getStatus()) { - LOGGER.info("Branch transaction has already committed before. idempotency rejected. xid: {}, branchId: {}, status: {}", xid, branchId, tccFenceDO.getStatus()); + if (CommonFenceConstant.STATUS_COMMITTED == commonFenceDO.getStatus()) { + LOGGER.info("Branch transaction has already committed before. idempotency rejected. xid: {}, branchId: {}, status: {}", xid, branchId, commonFenceDO.getStatus()); return true; } - if (TCCFenceConstant.STATUS_ROLLBACKED == tccFenceDO.getStatus() || TCCFenceConstant.STATUS_SUSPENDED == tccFenceDO.getStatus()) { + if (CommonFenceConstant.STATUS_ROLLBACKED == commonFenceDO.getStatus() || CommonFenceConstant.STATUS_SUSPENDED == commonFenceDO.getStatus()) { if (LOGGER.isWarnEnabled()) { - LOGGER.warn("Branch transaction status is unexpected. xid: {}, branchId: {}, status: {}", xid, branchId, tccFenceDO.getStatus()); + LOGGER.warn("Branch transaction status is unexpected. xid: {}, branchId: {}, status: {}", xid, branchId, commonFenceDO.getStatus()); } return false; } - return updateStatusAndInvokeTargetMethod(conn, commitMethod, targetTCCBean, xid, branchId, TCCFenceConstant.STATUS_COMMITTED, status, args); + return updateStatusAndInvokeTargetMethod(conn, commitMethod, targetTCCBean, xid, branchId, CommonFenceConstant.STATUS_COMMITTED, status, args); } catch (Throwable t) { status.setRollbackOnly(); throw new SkipCallbackWrapperException(t); @@ -169,7 +170,7 @@ public static boolean commitFence(Method commitMethod, Object targetTCCBean, } /** - * tcc rollback method enhanced + * Common rollback method enhanced * * @param rollbackMethod rollback method * @param targetTCCBean target tcc bean @@ -184,29 +185,29 @@ public static boolean rollbackFence(Method rollbackMethod, Object targetTCCBean, return transactionTemplate.execute(status -> { try { Connection conn = DataSourceUtils.getConnection(dataSource); - TCCFenceDO tccFenceDO = TCC_FENCE_DAO.queryTCCFenceDO(conn, xid, branchId); + CommonFenceDO commonFenceDO = COMMON_FENCE_DAO.queryCommonFenceDO(conn, xid, branchId); // non_rollback - if (tccFenceDO == null) { - boolean result = insertTCCFenceLog(conn, xid, branchId, actionName, TCCFenceConstant.STATUS_SUSPENDED); - LOGGER.info("Insert tcc fence record result: {}. xid: {}, branchId: {}", result, xid, branchId); + if (commonFenceDO == null) { + boolean result = insertCommonFenceLog(conn, xid, branchId, actionName, CommonFenceConstant.STATUS_SUSPENDED); + LOGGER.info("Insert common fence record result: {}. xid: {}, branchId: {}", result, xid, branchId); if (!result) { - throw new TCCFenceException(String.format("Insert tcc fence record error, rollback fence method failed. xid= %s, branchId= %s", xid, branchId), + throw new CommonFenceException(String.format("Insert common fence record error, rollback fence method failed. xid= %s, branchId= %s", xid, branchId), FrameworkErrorCode.InsertRecordError); } return true; } else { - if (TCCFenceConstant.STATUS_ROLLBACKED == tccFenceDO.getStatus() || TCCFenceConstant.STATUS_SUSPENDED == tccFenceDO.getStatus()) { - LOGGER.info("Branch transaction had already rollbacked before, idempotency rejected. xid: {}, branchId: {}, status: {}", xid, branchId, tccFenceDO.getStatus()); + if (CommonFenceConstant.STATUS_ROLLBACKED == commonFenceDO.getStatus() || CommonFenceConstant.STATUS_SUSPENDED == commonFenceDO.getStatus()) { + LOGGER.info("Branch transaction had already rollbacked before, idempotency rejected. xid: {}, branchId: {}, status: {}", xid, branchId, commonFenceDO.getStatus()); return true; } - if (TCCFenceConstant.STATUS_COMMITTED == tccFenceDO.getStatus()) { + if (CommonFenceConstant.STATUS_COMMITTED == commonFenceDO.getStatus()) { if (LOGGER.isWarnEnabled()) { - LOGGER.warn("Branch transaction status is unexpected. xid: {}, branchId: {}, status: {}", xid, branchId, tccFenceDO.getStatus()); + LOGGER.warn("Branch transaction status is unexpected. xid: {}, branchId: {}, status: {}", xid, branchId, commonFenceDO.getStatus()); } return false; } } - return updateStatusAndInvokeTargetMethod(conn, rollbackMethod, targetTCCBean, xid, branchId, TCCFenceConstant.STATUS_ROLLBACKED, status, args); + return updateStatusAndInvokeTargetMethod(conn, rollbackMethod, targetTCCBean, xid, branchId, CommonFenceConstant.STATUS_ROLLBACKED, status, args); } catch (Throwable t) { status.setRollbackOnly(); throw new SkipCallbackWrapperException(t); @@ -215,7 +216,7 @@ public static boolean rollbackFence(Method rollbackMethod, Object targetTCCBean, } /** - * Insert TCC fence log + * Insert Common fence log * * @param conn the db connection * @param xid the xid @@ -223,13 +224,13 @@ public static boolean rollbackFence(Method rollbackMethod, Object targetTCCBean, * @param status the status * @return the boolean */ - private static boolean insertTCCFenceLog(Connection conn, String xid, Long branchId, String actionName, Integer status) { - TCCFenceDO tccFenceDO = new TCCFenceDO(); - tccFenceDO.setXid(xid); - tccFenceDO.setBranchId(branchId); - tccFenceDO.setActionName(actionName); - tccFenceDO.setStatus(status); - return TCC_FENCE_DAO.insertTCCFenceDO(conn, tccFenceDO); + private static boolean insertCommonFenceLog(Connection conn, String xid, Long branchId, String actionName, Integer status) { + CommonFenceDO commonFenceDO = new CommonFenceDO(); + commonFenceDO.setXid(xid); + commonFenceDO.setBranchId(branchId); + commonFenceDO.setActionName(actionName); + commonFenceDO.setStatus(status); + return COMMON_FENCE_DAO.insertCommonFenceDO(conn, commonFenceDO); } /** @@ -246,7 +247,7 @@ private static boolean updateStatusAndInvokeTargetMethod(Connection conn, Method String xid, Long branchId, int status, TransactionStatus transactionStatus, Object[] args) throws Exception { - boolean result = TCC_FENCE_DAO.updateTCCFenceDO(conn, xid, branchId, status, TCCFenceConstant.STATUS_TRIED); + boolean result = COMMON_FENCE_DAO.updateCommonFenceDO(conn, xid, branchId, status, CommonFenceConstant.STATUS_TRIED); if (result) { // invoke two phase method Object ret = method.invoke(targetTCCBean, args); @@ -266,7 +267,7 @@ private static boolean updateStatusAndInvokeTargetMethod(Connection conn, Method } /** - * Delete TCC Fence + * Delete Common Fence * * @param xid the global transaction id * @param branchId the branch transaction id @@ -277,7 +278,7 @@ public static boolean deleteFence(String xid, Long branchId) { boolean ret = false; try { Connection conn = DataSourceUtils.getConnection(dataSource); - ret = TCC_FENCE_DAO.deleteTCCFenceDO(conn, xid, branchId); + ret = COMMON_FENCE_DAO.deleteCommonFenceDO(conn, xid, branchId); } catch (RuntimeException e) { status.setRollbackOnly(); LOGGER.error("delete fence log failed, xid: {}, branchId: {}", xid, branchId, e); @@ -288,18 +289,24 @@ public static boolean deleteFence(String xid, Long branchId) { + /** + * Delete Common Fence By Datetime + * + * @param datetime datetime + * @return the deleted row count + */ public static int deleteFenceByDate(Date datetime) { - DataSource dataSource = TCCFenceHandler.getDataSource(); + DataSource dataSource = CommonFenceHandler.getDataSource(); Connection connection = null; int total = 0; try { connection = DataSourceUtils.getConnection(dataSource); while (true) { - Set xidSet = TCC_FENCE_DAO.queryEndStatusXidsByDate(connection, datetime, LIMIT_DELETE); + Set xidSet = COMMON_FENCE_DAO.queryEndStatusXidsByDate(connection, datetime, LIMIT_DELETE); if (xidSet.isEmpty()) { break; } - total += TCC_FENCE_DAO.deleteTCCFenceDO(connection, new ArrayList<>(xidSet)); + total += COMMON_FENCE_DAO.deleteTCCFenceDO(connection, new ArrayList<>(xidSet)); } } catch (RuntimeException e) { LOGGER.error("delete fence log failed ", e); @@ -335,7 +342,7 @@ private static void addToLogCleanQueue(final String xid, final long branchId) { /** * clean fence log that has the final status runnable. * - * @see TCCFenceConstant + * @see CommonFenceConstant */ private static class FenceLogCleanRunnable implements Runnable { @Override @@ -344,7 +351,7 @@ public void run() { try { FenceLogIdentity logIdentity = LOG_QUEUE.take(); - boolean ret = TCCFenceHandler.deleteFence(logIdentity.getXid(), logIdentity.getBranchId()); + boolean ret = CommonFenceHandler.deleteFence(logIdentity.getXid(), logIdentity.getBranchId()); if (!ret) { LOGGER.error("delete fence log failed, xid: {}, branchId: {}", logIdentity.getXid(), logIdentity.getBranchId()); } @@ -384,4 +391,4 @@ public void setBranchId(Long branchId) { this.branchId = branchId; } } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/config/TCCFenceConfig.java b/common-api/src/main/java/io/seata/commonapi/fence/config/CommonFenceConfig.java similarity index 75% rename from tcc/src/main/java/io/seata/rm/tcc/config/TCCFenceConfig.java rename to common-api/src/main/java/io/seata/commonapi/fence/config/CommonFenceConfig.java index fffc08ab993..5263fb7dc01 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/config/TCCFenceConfig.java +++ b/common-api/src/main/java/io/seata/commonapi/fence/config/CommonFenceConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.config; +package io.seata.commonapi.fence.config; import java.time.Duration; import java.util.Date; @@ -26,10 +26,10 @@ import io.seata.common.DefaultValues; import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.thread.NamedThreadFactory; +import io.seata.commonapi.fence.CommonFenceHandler; +import io.seata.commonapi.fence.exception.CommonFenceException; import io.seata.core.rpc.Disposable; -import io.seata.rm.tcc.TCCFenceHandler; -import io.seata.rm.tcc.exception.TCCFenceException; -import io.seata.rm.tcc.store.db.TCCFenceStoreDataBaseDAO; +import io.seata.commonapi.fence.store.db.CommonFenceStoreDataBaseDAO; import org.apache.commons.lang.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,48 +38,48 @@ import org.springframework.transaction.support.TransactionTemplate; /** - * TCC Fence Config + * Common Fence Config * * @author kaka2code */ -public class TCCFenceConfig implements InitializingBean, Disposable { +public class CommonFenceConfig implements InitializingBean, Disposable { - private static final Logger LOGGER = LoggerFactory.getLogger(TCCFenceConfig.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CommonFenceConfig.class); private final AtomicBoolean initialized = new AtomicBoolean(false); /** - * TCC fence clean period max value. maximum interval is 68 years + * Common fence clean period max value. maximum interval is 68 years */ private static final Duration MAX_PERIOD = Duration.ofSeconds(Integer.MAX_VALUE); /** - * TCC fence clean period. only duration type format are supported + * Common fence clean period. only duration type format are supported */ - private Duration cleanPeriod = Duration.ofDays(DefaultValues.DEFAULT_TCC_FENCE_CLEAN_PERIOD); + private Duration cleanPeriod = Duration.ofDays(DefaultValues.DEFAULT_COMMON_FENCE_CLEAN_PERIOD); /** - * TCC fence log table name + * Common fence log table name */ - private String logTableName = DefaultValues.DEFAULT_TCC_FENCE_LOG_TABLE_NAME; + private String logTableName = DefaultValues.DEFAULT_COMMON_FENCE_LOG_TABLE_NAME; /** - * TCC fence datasource + * Common fence datasource */ private final DataSource dataSource; /** - * TCC fence transactionManager + * Common fence transactionManager */ private final PlatformTransactionManager transactionManager; /** - * TCC fence clean scheduled thread pool + * Common fence clean scheduled thread pool */ private final ScheduledThreadPoolExecutor tccFenceClean = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("tccFenceClean", 1)); - public TCCFenceConfig(final DataSource dataSource, final PlatformTransactionManager transactionManager) { + public CommonFenceConfig(final DataSource dataSource, final PlatformTransactionManager transactionManager) { this.dataSource = dataSource; this.transactionManager = transactionManager; } @@ -116,7 +116,7 @@ public void initCleanTask() { Date timeBefore = null; try { timeBefore = DateUtils.addSeconds(new Date(), -(int)periodSeconds); - int deletedRowCount = TCCFenceHandler.deleteFenceByDate(timeBefore); + int deletedRowCount = CommonFenceHandler.deleteFenceByDate(timeBefore); if (deletedRowCount > 0) { LOGGER.info("TCC fence clean task executed success, timeBefore: {}, deleted row count: {}", timeBefore, deletedRowCount); @@ -141,20 +141,19 @@ public void destroy() { public void afterPropertiesSet() { // set log table name if (logTableName != null) { - TCCFenceStoreDataBaseDAO.getInstance().setLogTableName(logTableName); + CommonFenceStoreDataBaseDAO.getInstance().setLogTableName(logTableName); } if (dataSource != null) { // set dataSource - TCCFenceHandler.setDataSource(dataSource); + CommonFenceHandler.setDataSource(dataSource); } else { - throw new TCCFenceException(FrameworkErrorCode.DateSourceNeedInjected); + throw new CommonFenceException(FrameworkErrorCode.DateSourceNeedInjected); } if (transactionManager != null) { // set transaction template - TCCFenceHandler.setTransactionTemplate(new TransactionTemplate(transactionManager)); + CommonFenceHandler.setTransactionTemplate(new TransactionTemplate(transactionManager)); } else { - throw new TCCFenceException(FrameworkErrorCode.TransactionManagerNeedInjected); + throw new CommonFenceException(FrameworkErrorCode.TransactionManagerNeedInjected); } } } - diff --git a/tcc/src/main/java/io/seata/rm/tcc/constant/TCCFenceConstant.java b/common-api/src/main/java/io/seata/commonapi/fence/constant/CommonFenceConstant.java similarity index 88% rename from tcc/src/main/java/io/seata/rm/tcc/constant/TCCFenceConstant.java rename to common-api/src/main/java/io/seata/commonapi/fence/constant/CommonFenceConstant.java index 7c9a2b416cf..4371ba6b070 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/constant/TCCFenceConstant.java +++ b/common-api/src/main/java/io/seata/commonapi/fence/constant/CommonFenceConstant.java @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.constant; +package io.seata.commonapi.fence.constant; /** - * TCC Fence Constant + * Common Fence Constant * * @author kaka2code */ -public class TCCFenceConstant { +public class CommonFenceConstant { - private TCCFenceConstant() { + private CommonFenceConstant() { throw new IllegalStateException("Utility class"); } @@ -45,4 +45,4 @@ private TCCFenceConstant() { * Suspended status. */ public static final int STATUS_SUSPENDED = 4; -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/exception/TCCFenceException.java b/common-api/src/main/java/io/seata/commonapi/fence/exception/CommonFenceException.java similarity index 64% rename from tcc/src/main/java/io/seata/rm/tcc/exception/TCCFenceException.java rename to common-api/src/main/java/io/seata/commonapi/fence/exception/CommonFenceException.java index 716da66ed1f..081c3b3962c 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/exception/TCCFenceException.java +++ b/common-api/src/main/java/io/seata/commonapi/fence/exception/CommonFenceException.java @@ -13,40 +13,40 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.exception; +package io.seata.commonapi.fence.exception; import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.exception.FrameworkException; /** - * TCC Fence Exception + * Common Fence Exception * * @author kaka2code */ -public class TCCFenceException extends FrameworkException { +public class CommonFenceException extends FrameworkException { - public TCCFenceException(FrameworkErrorCode err) { + public CommonFenceException(FrameworkErrorCode err) { super(err); } - public TCCFenceException(String msg) { + public CommonFenceException(String msg) { super(msg); } - public TCCFenceException(String msg, FrameworkErrorCode errCode) { + public CommonFenceException(String msg, FrameworkErrorCode errCode) { super(msg, errCode); } - public TCCFenceException(Throwable cause, String msg, FrameworkErrorCode errCode) { + public CommonFenceException(Throwable cause, String msg, FrameworkErrorCode errCode) { super(cause, msg, errCode); } - public TCCFenceException(Throwable th) { + public CommonFenceException(Throwable th) { super(th); } - public TCCFenceException(Throwable th, String msg) { + public CommonFenceException(Throwable th, String msg) { super(th, msg); } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceDO.java b/common-api/src/main/java/io/seata/commonapi/fence/store/CommonFenceDO.java similarity index 94% rename from tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceDO.java rename to common-api/src/main/java/io/seata/commonapi/fence/store/CommonFenceDO.java index 6878a9a0c74..a8f35b9364e 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceDO.java +++ b/common-api/src/main/java/io/seata/commonapi/fence/store/CommonFenceDO.java @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.store; +package io.seata.commonapi.fence.store; import java.util.Date; /** - * TCC Fence Domain + * Common Fence Domain * * @author kaka2code */ -public class TCCFenceDO { +public class CommonFenceDO { /** * the global transaction id @@ -40,7 +40,7 @@ public class TCCFenceDO { private String actionName; /** - * the tcc fence status + * the common fence status * tried: 1; committed: 2; rollbacked: 3; suspended: 4 */ private Integer status; @@ -103,4 +103,4 @@ public void setGmtModified(Date gmtModified) { this.gmtModified = gmtModified; } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceStore.java b/common-api/src/main/java/io/seata/commonapi/fence/store/CommonFenceStore.java similarity index 72% rename from tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceStore.java rename to common-api/src/main/java/io/seata/commonapi/fence/store/CommonFenceStore.java index 3f356526e5d..f2ac8480ad9 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceStore.java +++ b/common-api/src/main/java/io/seata/commonapi/fence/store/CommonFenceStore.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.store; +package io.seata.commonapi.fence.store; import java.sql.Connection; import java.util.Date; @@ -21,20 +21,20 @@ import java.util.Set; /** - * The TCC Fence Store + * The common Fence Store * * @author kaka2code */ -public interface TCCFenceStore { +public interface CommonFenceStore { /** - * Query tcc fence do. + * Query common fence do. * @param conn the connection * @param xid the global transaction id * @param branchId the branch transaction id - * @return the tcc fence do + * @return the common fence do */ - TCCFenceDO queryTCCFenceDO(Connection conn, String xid, Long branchId); + CommonFenceDO queryCommonFenceDO(Connection conn, String xid, Long branchId); /** * Query xid. @@ -46,15 +46,15 @@ public interface TCCFenceStore { Set queryEndStatusXidsByDate(Connection conn, Date datetime, int limit); /** - * Insert tcc fence do boolean. + * Insert common fence do boolean. * @param conn the connection - * @param tccFenceDO the tcc fence do + * @param commonFenceDO the common fence do * @return the boolean */ - boolean insertTCCFenceDO(Connection conn, TCCFenceDO tccFenceDO); + boolean insertCommonFenceDO(Connection conn, CommonFenceDO commonFenceDO); /** - * Update tcc fence do boolean. + * Update common fence do boolean. * @param conn the connection * @param xid the global transaction id * @param branchId the branch transaction id @@ -62,16 +62,16 @@ public interface TCCFenceStore { * @param oldStatus the old status * @return the boolean */ - boolean updateTCCFenceDO(Connection conn, String xid, Long branchId, int newStatus, int oldStatus); + boolean updateCommonFenceDO(Connection conn, String xid, Long branchId, int newStatus, int oldStatus); /** - * Delete tcc fence do boolean. + * Delete common fence do boolean. * @param conn the connection * @param xid the global transaction id * @param branchId the branch transaction id * @return the boolean */ - boolean deleteTCCFenceDO(Connection conn, String xid, Long branchId); + boolean deleteCommonFenceDO(Connection conn, String xid, Long branchId); /** * Delete tcc fence do boolean. @@ -82,13 +82,13 @@ public interface TCCFenceStore { int deleteTCCFenceDO(Connection conn, List xids); /** - * Delete tcc fence by datetime. + * Delete common fence by datetime. * @param conn the connection * @param datetime datetime * @param limit limit * @return the deleted row count */ - int deleteTCCFenceDOByDate(Connection conn, Date datetime, int limit); + int deleteCommonFenceDOByDate(Connection conn, Date datetime, int limit); /** * Set LogTable Name diff --git a/tcc/src/main/java/io/seata/rm/tcc/store/db/TCCFenceStoreDataBaseDAO.java b/common-api/src/main/java/io/seata/commonapi/fence/store/db/CommonFenceStoreDataBaseDAO.java similarity index 66% rename from tcc/src/main/java/io/seata/rm/tcc/store/db/TCCFenceStoreDataBaseDAO.java rename to common-api/src/main/java/io/seata/commonapi/fence/store/db/CommonFenceStoreDataBaseDAO.java index 98b96662687..49a4cd8c46e 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/store/db/TCCFenceStoreDataBaseDAO.java +++ b/common-api/src/main/java/io/seata/commonapi/fence/store/db/CommonFenceStoreDataBaseDAO.java @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.store.db; +package io.seata.commonapi.fence.store.db; import io.seata.common.DefaultValues; import io.seata.common.exception.DataAccessException; import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.exception.StoreException; import io.seata.common.util.IOUtil; -import io.seata.rm.tcc.exception.TCCFenceException; -import io.seata.rm.tcc.store.TCCFenceDO; -import io.seata.rm.tcc.store.TCCFenceStore; -import io.seata.rm.tcc.store.db.sql.TCCFenceStoreSqls; +import io.seata.commonapi.fence.exception.CommonFenceException; +import io.seata.commonapi.fence.store.CommonFenceDO; +import io.seata.commonapi.fence.store.CommonFenceStore; +import io.seata.commonapi.fence.store.db.sql.CommonFenceStoreSqls; import java.sql.Connection; import java.sql.PreparedStatement; @@ -37,26 +37,26 @@ import java.util.Set; /** - * The type TCC Fence store data base dao + * The type Common Fence store data base dao * * @author kaka2code */ -public class TCCFenceStoreDataBaseDAO implements TCCFenceStore { +public class CommonFenceStoreDataBaseDAO implements CommonFenceStore { /** - * TCC fence log table name + * Common fence log table name */ - private String logTableName = DefaultValues.DEFAULT_TCC_FENCE_LOG_TABLE_NAME; + private String logTableName = DefaultValues.DEFAULT_COMMON_FENCE_LOG_TABLE_NAME; - private static volatile TCCFenceStoreDataBaseDAO instance = null; + private static volatile CommonFenceStoreDataBaseDAO instance = null; - private TCCFenceStoreDataBaseDAO() {} + private CommonFenceStoreDataBaseDAO() {} - public static TCCFenceStore getInstance() { + public static CommonFenceStore getInstance() { if (instance == null) { - synchronized (TCCFenceStore.class) { + synchronized (CommonFenceStore.class) { if (instance == null) { - instance = new TCCFenceStoreDataBaseDAO(); + instance = new CommonFenceStoreDataBaseDAO(); } } } @@ -64,21 +64,21 @@ public static TCCFenceStore getInstance() { } @Override - public TCCFenceDO queryTCCFenceDO(Connection conn, String xid, Long branchId) { + public CommonFenceDO queryCommonFenceDO(Connection conn, String xid, Long branchId) { PreparedStatement ps = null; ResultSet rs = null; try { - String sql = TCCFenceStoreSqls.getQuerySQLByBranchIdAndXid(logTableName); + String sql = CommonFenceStoreSqls.getQuerySQLByBranchIdAndXid(logTableName); ps = conn.prepareStatement(sql); ps.setString(1, xid); ps.setLong(2, branchId); rs = ps.executeQuery(); if (rs.next()) { - TCCFenceDO tccFenceDO = new TCCFenceDO(); - tccFenceDO.setXid(rs.getString("xid")); - tccFenceDO.setBranchId(rs.getLong("branch_id")); - tccFenceDO.setStatus(rs.getInt("status")); - return tccFenceDO; + CommonFenceDO commonFenceDO = new CommonFenceDO(); + commonFenceDO.setXid(rs.getString("xid")); + commonFenceDO.setBranchId(rs.getLong("branch_id")); + commonFenceDO.setStatus(rs.getInt("status")); + return commonFenceDO; } else { return null; } @@ -94,7 +94,7 @@ public Set queryEndStatusXidsByDate(Connection conn, Date datetime, int PreparedStatement ps = null; ResultSet rs = null; try { - String sql = TCCFenceStoreSqls.getQueryEndStatusSQLByDate(logTableName); + String sql = CommonFenceStoreSqls.getQueryEndStatusSQLByDate(logTableName); ps = conn.prepareStatement(sql); ps.setTimestamp(1, new Timestamp(datetime.getTime())); ps.setInt(2, limit); @@ -112,22 +112,22 @@ public Set queryEndStatusXidsByDate(Connection conn, Date datetime, int } @Override - public boolean insertTCCFenceDO(Connection conn, TCCFenceDO tccFenceDO) { + public boolean insertCommonFenceDO(Connection conn, CommonFenceDO commonFenceDO) { PreparedStatement ps = null; try { Timestamp now = new Timestamp(System.currentTimeMillis()); - String sql = TCCFenceStoreSqls.getInsertLocalTCCLogSQL(logTableName); + String sql = CommonFenceStoreSqls.getInsertLocalTCCLogSQL(logTableName); ps = conn.prepareStatement(sql); - ps.setString(1, tccFenceDO.getXid()); - ps.setLong(2, tccFenceDO.getBranchId()); - ps.setString(3, tccFenceDO.getActionName()); - ps.setInt(4, tccFenceDO.getStatus()); + ps.setString(1, commonFenceDO.getXid()); + ps.setLong(2, commonFenceDO.getBranchId()); + ps.setString(3, commonFenceDO.getActionName()); + ps.setInt(4, commonFenceDO.getStatus()); ps.setTimestamp(5, now); ps.setTimestamp(6, now); return ps.executeUpdate() > 0; } catch (SQLIntegrityConstraintViolationException e) { - throw new TCCFenceException(String.format("Insert tcc fence record duplicate key exception. xid= %s, branchId= %s", tccFenceDO.getXid(), tccFenceDO.getBranchId()), + throw new CommonFenceException(String.format("Insert tcc fence record duplicate key exception. xid= %s, branchId= %s", commonFenceDO.getXid(), commonFenceDO.getBranchId()), FrameworkErrorCode.DuplicateKeyException); } catch (SQLException e) { throw new StoreException(e); @@ -137,10 +137,10 @@ public boolean insertTCCFenceDO(Connection conn, TCCFenceDO tccFenceDO) { } @Override - public boolean updateTCCFenceDO(Connection conn, String xid, Long branchId, int newStatus, int oldStatus) { + public boolean updateCommonFenceDO(Connection conn, String xid, Long branchId, int newStatus, int oldStatus) { PreparedStatement ps = null; try { - String sql = TCCFenceStoreSqls.getUpdateStatusSQLByBranchIdAndXid(logTableName); + String sql = CommonFenceStoreSqls.getUpdateStatusSQLByBranchIdAndXid(logTableName); ps = conn.prepareStatement(sql); ps.setInt(1, newStatus); // gmt_modified @@ -157,10 +157,10 @@ public boolean updateTCCFenceDO(Connection conn, String xid, Long branchId, int } @Override - public boolean deleteTCCFenceDO(Connection conn, String xid, Long branchId) { + public boolean deleteCommonFenceDO(Connection conn, String xid, Long branchId) { PreparedStatement ps = null; try { - String sql = TCCFenceStoreSqls.getDeleteSQLByBranchIdAndXid(logTableName); + String sql = CommonFenceStoreSqls.getDeleteSQLByBranchIdAndXid(logTableName); ps = conn.prepareStatement(sql); ps.setString(1, xid); ps.setLong(2, branchId); @@ -178,7 +178,7 @@ public int deleteTCCFenceDO(Connection conn, List xids) { PreparedStatement ps = null; try { String paramsPlaceHolder = org.apache.commons.lang.StringUtils.repeat("?", ",", xids.size()); - String sql = TCCFenceStoreSqls.getDeleteSQLByXids(logTableName, paramsPlaceHolder); + String sql = CommonFenceStoreSqls.getDeleteSQLByXids(logTableName, paramsPlaceHolder); ps = conn.prepareStatement(sql); for (int i = 0; i < xids.size(); i++) { ps.setString(i + 1, xids.get(i)); @@ -192,10 +192,10 @@ public int deleteTCCFenceDO(Connection conn, List xids) { } @Override - public int deleteTCCFenceDOByDate(Connection conn, Date datetime, int limit) { + public int deleteCommonFenceDOByDate(Connection conn, Date datetime, int limit) { PreparedStatement ps = null; try { - String sql = TCCFenceStoreSqls.getDeleteSQLByDateAndStatus(logTableName); + String sql = CommonFenceStoreSqls.getDeleteSQLByDateAndStatus(logTableName); ps = conn.prepareStatement(sql); ps.setTimestamp(1, new Timestamp(datetime.getTime())); ps.setInt(2, limit); @@ -211,4 +211,4 @@ public int deleteTCCFenceDOByDate(Connection conn, Date datetime, int limit) { public void setLogTableName(String logTableName) { this.logTableName = logTableName; } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/store/db/sql/TCCFenceStoreSqls.java b/common-api/src/main/java/io/seata/commonapi/fence/store/db/sql/CommonFenceStoreSqls.java similarity index 88% rename from tcc/src/main/java/io/seata/rm/tcc/store/db/sql/TCCFenceStoreSqls.java rename to common-api/src/main/java/io/seata/commonapi/fence/store/db/sql/CommonFenceStoreSqls.java index f1b43b2540e..eae59da4101 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/store/db/sql/TCCFenceStoreSqls.java +++ b/common-api/src/main/java/io/seata/commonapi/fence/store/db/sql/CommonFenceStoreSqls.java @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.store.db.sql; +package io.seata.commonapi.fence.store.db.sql; -import io.seata.rm.tcc.constant.TCCFenceConstant; +import io.seata.commonapi.fence.constant.CommonFenceConstant; /** * TCC Fence Store Sqls * * @author kaka2code */ -public class TCCFenceStoreSqls { +public class CommonFenceStoreSqls { - private TCCFenceStoreSqls() { + private CommonFenceStoreSqls() { throw new IllegalStateException("Utility class"); } @@ -59,7 +59,7 @@ private TCCFenceStoreSqls() { protected static final String QUERY_END_STATUS_BY_DATE = "select xid, branch_id, status, gmt_create, gmt_modified " + "from " + LOCAL_TCC_LOG_PLACEHOLD + " where gmt_modified < ? " - + " and status in (" + TCCFenceConstant.STATUS_COMMITTED + " , " + TCCFenceConstant.STATUS_ROLLBACKED + " , " + TCCFenceConstant.STATUS_SUSPENDED + ")" + + " and status in (" + CommonFenceConstant.STATUS_COMMITTED + " , " + CommonFenceConstant.STATUS_ROLLBACKED + " , " + CommonFenceConstant.STATUS_SUSPENDED + ")" + " limit ?"; /** @@ -84,7 +84,7 @@ private TCCFenceStoreSqls() { */ protected static final String DELETE_BY_DATE_AND_STATUS = "delete from " + LOCAL_TCC_LOG_PLACEHOLD + " where gmt_modified < ? " - + " and status in (" + TCCFenceConstant.STATUS_COMMITTED + " , " + TCCFenceConstant.STATUS_ROLLBACKED + " , " + TCCFenceConstant.STATUS_SUSPENDED + ")" + + " and status in (" + CommonFenceConstant.STATUS_COMMITTED + " , " + CommonFenceConstant.STATUS_ROLLBACKED + " , " + CommonFenceConstant.STATUS_SUSPENDED + ")" + " limit ?"; public static String getInsertLocalTCCLogSQL(String localTccTable) { @@ -116,4 +116,4 @@ public static String getDeleteSQLByDateAndStatus(String localTccTable) { return DELETE_BY_DATE_AND_STATUS.replace(LOCAL_TCC_LOG_PLACEHOLD, localTccTable); } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextFilter.java b/common-api/src/main/java/io/seata/commonapi/interceptor/ActionContextFilter.java similarity index 89% rename from tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextFilter.java rename to common-api/src/main/java/io/seata/commonapi/interceptor/ActionContextFilter.java index 32a6f492161..0b17371e46a 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextFilter.java +++ b/common-api/src/main/java/io/seata/commonapi/interceptor/ActionContextFilter.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.interceptor; +package io.seata.commonapi.interceptor; -import io.seata.rm.tcc.api.BusinessActionContextParameter; +import io.seata.commonapi.rm.tcc.api.BusinessActionContextParameter; /** * The interface Action context filter. diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextUtil.java b/common-api/src/main/java/io/seata/commonapi/interceptor/ActionContextUtil.java similarity index 98% rename from tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextUtil.java rename to common-api/src/main/java/io/seata/commonapi/interceptor/ActionContextUtil.java index 8b50b52bce9..167d57b6f4c 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextUtil.java +++ b/common-api/src/main/java/io/seata/commonapi/interceptor/ActionContextUtil.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.interceptor; +package io.seata.commonapi.interceptor; import java.lang.reflect.Field; import java.util.Collections; @@ -28,9 +28,9 @@ import io.seata.common.util.CollectionUtils; import io.seata.common.util.ReflectionUtil; import io.seata.common.util.StringUtils; -import io.seata.rm.tcc.api.BusinessActionContext; -import io.seata.rm.tcc.api.BusinessActionContextParameter; -import io.seata.rm.tcc.api.ParamType; +import io.seata.commonapi.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContextParameter; +import io.seata.commonapi.rm.tcc.api.ParamType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java b/common-api/src/main/java/io/seata/commonapi/interceptor/ActionInterceptorHandler.java similarity index 55% rename from tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java rename to common-api/src/main/java/io/seata/commonapi/interceptor/ActionInterceptorHandler.java index 3fdec847b63..f387c4d9862 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java +++ b/common-api/src/main/java/io/seata/commonapi/interceptor/ActionInterceptorHandler.java @@ -13,15 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.interceptor; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.lang.reflect.UndeclaredThrowableException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import javax.annotation.Nonnull; +package io.seata.commonapi.interceptor; import com.alibaba.fastjson.JSON; import io.seata.common.Constants; @@ -30,21 +22,34 @@ import io.seata.common.executor.Callback; import io.seata.common.util.CollectionUtils; import io.seata.common.util.NetUtil; +import io.seata.commonapi.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContextParameter; +import io.seata.commonapi.rm.tcc.api.BusinessActionContextUtil; +import io.seata.commonapi.rm.tcc.api.ParamType; +import io.seata.commonapi.fence.CommonFenceHandler; +import io.seata.commonapi.util.DubboUtil; +import io.seata.commonapi.util.SpringProxyUtils; import io.seata.core.context.RootContext; -import io.seata.core.model.BranchType; +import io.seata.commonapi.remoting.RemotingDesc; import io.seata.rm.DefaultResourceManager; -import io.seata.rm.tcc.TCCFenceHandler; -import io.seata.rm.tcc.api.BusinessActionContext; -import io.seata.rm.tcc.api.BusinessActionContextParameter; -import io.seata.rm.tcc.api.BusinessActionContextUtil; -import io.seata.rm.tcc.api.ParamType; -import io.seata.rm.tcc.api.TwoPhaseBusinessAction; + + +import org.aopalliance.intercept.MethodInvocation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + /** - * Handler the TCC Participant Aspect : Setting Context, Creating Branch Record + * Handler the Tx Participant Aspect : Setting Context, Creating Branch Record * * @author zhangsen */ @@ -53,31 +58,33 @@ public class ActionInterceptorHandler { private static final Logger LOGGER = LoggerFactory.getLogger(ActionInterceptorHandler.class); /** - * Handler the TCC Aspect + * Handler the Tx Aspect * * @param method the method * @param arguments the arguments * @param xid the xid - * @param businessAction the business action + * @param businessActionParam the business action params * @param targetCallback the target callback * @return the business result * @throws Throwable the throwable */ - public Object proceed(Method method, Object[] arguments, String xid, TwoPhaseBusinessAction businessAction, - Callback targetCallback) throws Throwable { + public Object proceed(Method method, Object[] arguments, String xid, TwoPhaseBusinessActionParam businessActionParam, + Callback targetCallback) throws Throwable { //Get action context from arguments, or create a new one and then reset to arguments BusinessActionContext actionContext = getOrCreateActionContextAndResetToArguments(method.getParameterTypes(), arguments); //Set the xid actionContext.setXid(xid); //Set the action name - String actionName = businessAction.name(); + String actionName = businessActionParam.getActionName(); actionContext.setActionName(actionName); //Set the delay report - actionContext.setDelayReport(businessAction.isDelayReport()); + actionContext.setDelayReport(businessActionParam.getDelayReport()); + //Set branch type + actionContext.setBranchType(businessActionParam.getBranchType()); //Creating Branch Record - String branchId = doTccActionLogStore(method, arguments, businessAction, actionContext); + String branchId = doTxActionLogStore(method, arguments, businessActionParam, actionContext); actionContext.setBranchId(branchId); //MDC put branchId MDC.put(RootContext.MDC_KEY_BRANCH_ID, branchId); @@ -88,14 +95,14 @@ public Object proceed(Method method, Object[] arguments, String xid, TwoPhaseBus //share actionContext implicitly BusinessActionContextUtil.setContext(actionContext); - if (businessAction.useTCCFence()) { + if (businessActionParam.getUseCommonFence()) { try { - // Use TCC Fence, and return the business result - return TCCFenceHandler.prepareFence(xid, Long.valueOf(branchId), actionName, targetCallback); + // Use common Fence, and return the business result + return CommonFenceHandler.prepareFence(xid, Long.valueOf(branchId), actionName, targetCallback); } catch (SkipCallbackWrapperException | UndeclaredThrowableException e) { Throwable originException = e.getCause(); if (originException instanceof FrameworkException) { - LOGGER.error("[{}] prepare TCC fence error: {}", xid, originException.getMessage()); + LOGGER.error("[{}] prepare common fence error: {}", xid, originException.getMessage()); } throw originException; } @@ -119,6 +126,46 @@ public Object proceed(Method method, Object[] arguments, String xid, TwoPhaseBus } } + public Object proceedManual(Method method, Object[] arguments, String xid, TwoPhaseBusinessActionParam businessActionParam) throws Throwable { + //Get action context from arguments, or create a new one and then reset to arguments + BusinessActionContext actionContext = getOrCreateActionContextAndResetToArguments(method.getParameterTypes(), arguments); + + //Set the xid + actionContext.setXid(xid); + //Set the action name + String actionName = businessActionParam.getActionName(); + actionContext.setActionName(actionName); + //Set the delay report + actionContext.setDelayReport(businessActionParam.getDelayReport()); + //Set branch type + actionContext.setBranchType(businessActionParam.getBranchType()); + + //Creating Branch Record + String branchId = doTxActionLogStore(method, arguments, businessActionParam, actionContext); + actionContext.setBranchId(branchId); + //MDC put branchId + MDC.put(RootContext.MDC_KEY_BRANCH_ID, branchId); + + //share actionContext implicitly + BusinessActionContextUtil.setContext(actionContext); + + if (businessActionParam.getUseCommonFence()) { + try { + // Use common Fence, and return the business result + EmptyCallBack emptyCallBack = new EmptyCallBack(); + return CommonFenceHandler.prepareFence(xid, Long.valueOf(branchId), actionName, emptyCallBack); + } catch (SkipCallbackWrapperException | UndeclaredThrowableException e) { + Throwable originException = e.getCause(); + if (originException instanceof FrameworkException) { + LOGGER.error("[{}] prepare common fence error: {}", xid, originException.getMessage()); + } + throw originException; + } + } else { + return null; + } + } + /** * Get or create action context, and reset to arguments * @@ -135,7 +182,7 @@ protected BusinessActionContext getOrCreateActionContextAndResetToArguments(Clas int argIndex = 0; for (Class parameterType : parameterTypes) { if (BusinessActionContext.class.isAssignableFrom(parameterType)) { - actionContext = (BusinessActionContext)arguments[argIndex]; + actionContext = (BusinessActionContext) arguments[argIndex]; if (actionContext == null) { // If the action context exists in arguments but is null, create a new one and reset the action context to the arguments actionContext = new BusinessActionContext(); @@ -159,14 +206,14 @@ protected BusinessActionContext getOrCreateActionContextAndResetToArguments(Clas /** * Creating Branch Record * - * @param method the method - * @param arguments the arguments - * @param businessAction the business action - * @param actionContext the action context + * @param method the method + * @param arguments the arguments + * @param businessActionParam the business action param + * @param actionContext the action context * @return the branchId */ - protected String doTccActionLogStore(Method method, Object[] arguments, TwoPhaseBusinessAction businessAction, - BusinessActionContext actionContext) { + protected String doTxActionLogStore(Method method, Object[] arguments, TwoPhaseBusinessActionParam businessActionParam, + BusinessActionContext actionContext) { String actionName = actionContext.getActionName(); String xid = actionContext.getXid(); @@ -176,7 +223,7 @@ protected String doTccActionLogStore(Method method, Object[] arguments, TwoPhase context.put(Constants.ACTION_START_TIME, System.currentTimeMillis()); //Init business context - initBusinessContext(context, method, businessAction); + initBusinessContext(context, method, businessActionParam.getBusinessActionContext()); //Init running environment context initFrameworkContext(context); @@ -193,15 +240,15 @@ protected String doTccActionLogStore(Method method, Object[] arguments, TwoPhase //endregion //Init applicationData - Map applicationContext = Collections.singletonMap(Constants.TCC_ACTION_CONTEXT, context); + Map applicationContext = Collections.singletonMap(Constants.TX_ACTION_CONTEXT, context); String applicationContextStr = JSON.toJSONString(applicationContext); try { //registry branch record - Long branchId = DefaultResourceManager.get().branchRegister(BranchType.TCC, actionName, null, xid, + Long branchId = DefaultResourceManager.get().branchRegister(businessActionParam.getBranchType(), actionName, null, xid, applicationContextStr, null); return String.valueOf(branchId); } catch (Throwable t) { - String msg = String.format("TCC branch Register error, xid: %s", xid); + String msg = String.format("%s branch Register error, xid: %s", businessActionParam.getBranchType(), xid); LOGGER.error(msg, t); throw new FrameworkException(t, msg); } @@ -223,22 +270,19 @@ protected void initFrameworkContext(Map context) { /** * Init business context * - * @param context the context - * @param method the method - * @param businessAction the business action + * @param context the context + * @param method the method + * @param businessActionContext the business action map */ protected void initBusinessContext(Map context, Method method, - TwoPhaseBusinessAction businessAction) { + Map businessActionContext) { if (method != null) { //the phase one method name context.put(Constants.PREPARE_METHOD, method.getName()); } - if (businessAction != null) { + if (businessActionContext != null && businessActionContext.size() > 0) { //the phase two method name - context.put(Constants.COMMIT_METHOD, businessAction.commitMethod()); - context.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod()); - context.put(Constants.ACTION_NAME, businessAction.name()); - context.put(Constants.USE_TCC_FENCE, businessAction.useTCCFence()); + context.putAll(businessActionContext); } } @@ -249,7 +293,7 @@ protected void initBusinessContext(Map context, Method method, * @param arguments the arguments * @return the context */ - protected Map fetchActionRequestContext(Method method, Object[] arguments) { + public Map fetchActionRequestContext(Method method, Object[] arguments) { Map context = new HashMap<>(8); Annotation[][] parameterAnnotations = method.getParameterAnnotations(); @@ -257,7 +301,7 @@ protected Map fetchActionRequestContext(Method method, Object[] for (int j = 0; j < parameterAnnotations[i].length; j++) { if (parameterAnnotations[i][j] instanceof BusinessActionContextParameter) { // get annotation - BusinessActionContextParameter annotation = (BusinessActionContextParameter)parameterAnnotations[i][j]; + BusinessActionContextParameter annotation = (BusinessActionContextParameter) parameterAnnotations[i][j]; if (arguments[i] == null) { throw new IllegalArgumentException("@BusinessActionContextParameter 's params can not null"); } @@ -275,4 +319,56 @@ protected Map fetchActionRequestContext(Method method, Object[] } return context; } -} + + /** + * get the method from interface + * + * @param invocation the invocation + * @return the action interface method + */ + public Method getActionInterfaceMethod(MethodInvocation invocation, RemotingDesc remotingDesc) { + Class serviceType = null; + try { + if (remotingDesc == null) { + serviceType = getProxyInterface(invocation.getThis()); + } else { + serviceType = remotingDesc.getServiceClass(); + } + if (serviceType == null && remotingDesc != null && remotingDesc.getServiceClassName() != null) { + serviceType = Class.forName(remotingDesc.getServiceClassName(), true, + Thread.currentThread().getContextClassLoader()); + } + if (serviceType == null) { + return invocation.getMethod(); + } + return serviceType.getMethod(invocation.getMethod().getName(), + invocation.getMethod().getParameterTypes()); + } catch (NoSuchMethodException e) { + if (serviceType != null && !"toString".equals(invocation.getMethod().getName())) { + LOGGER.warn("no such method '{}' from interface {}", invocation.getMethod().getName(), serviceType.getName()); + } + return invocation.getMethod(); + } catch (Exception e) { + LOGGER.warn("get Method from interface failed", e); + return invocation.getMethod(); + } + } + + /** + * get the interface of proxy + * + * @param proxyBean the proxy bean + * @return proxy interface + * @throws Exception the exception + */ + @Nullable + protected Class getProxyInterface(Object proxyBean) throws Exception { + if (DubboUtil.isDubboProxyName(proxyBean.getClass().getName())) { + //dubbo javaassist proxy + return DubboUtil.getAssistInterface(proxyBean); + } else { + //jdk/cglib proxy + return SpringProxyUtils.getTargetInterface(proxyBean); + } + } +} \ No newline at end of file diff --git a/common-api/src/main/java/io/seata/commonapi/interceptor/EmptyCallBack.java b/common-api/src/main/java/io/seata/commonapi/interceptor/EmptyCallBack.java new file mode 100644 index 00000000000..dc5c394aa23 --- /dev/null +++ b/common-api/src/main/java/io/seata/commonapi/interceptor/EmptyCallBack.java @@ -0,0 +1,26 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.commonapi.interceptor; + +import io.seata.common.executor.Callback; + +public class EmptyCallBack implements Callback { + + @Override + public Object execute() throws Throwable { + return null; + } +} diff --git a/common-api/src/main/java/io/seata/commonapi/interceptor/TwoPhaseBusinessActionParam.java b/common-api/src/main/java/io/seata/commonapi/interceptor/TwoPhaseBusinessActionParam.java new file mode 100644 index 00000000000..5d0f727ffc8 --- /dev/null +++ b/common-api/src/main/java/io/seata/commonapi/interceptor/TwoPhaseBusinessActionParam.java @@ -0,0 +1,78 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.commonapi.interceptor; + +import io.seata.core.model.BranchType; + +import java.util.Map; + +/** + * The two phase business action parameters. + * + * @author ruishansun + */ +public class TwoPhaseBusinessActionParam { + + private String actionName; + + private Boolean isDelayReport; + + private Boolean useCommonFence; + + private Map businessActionContext; + + private BranchType branchType; + + public String getActionName() { + return actionName; + } + + public void setActionName(String actionName) { + this.actionName = actionName; + } + + public Boolean getDelayReport() { + return isDelayReport; + } + + public void setDelayReport(Boolean delayReport) { + isDelayReport = delayReport; + } + + public Boolean getUseCommonFence() { + return useCommonFence; + } + + public void setUseCommonFence(Boolean useCommonFence) { + this.useCommonFence = useCommonFence; + } + + public Map getBusinessActionContext() { + return businessActionContext; + } + + public void setBusinessActionContext(Map businessActionContext) { + this.businessActionContext = businessActionContext; + } + + public BranchType getBranchType() { + return branchType; + } + + public void setBranchType(BranchType branchType) { + this.branchType = branchType; + } +} \ No newline at end of file diff --git a/spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java b/common-api/src/main/java/io/seata/commonapi/interceptor/TxAnnotationProcessor.java similarity index 70% rename from spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java rename to common-api/src/main/java/io/seata/commonapi/interceptor/TxAnnotationProcessor.java index 9b496fbe533..fbbefe74d72 100644 --- a/spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java +++ b/common-api/src/main/java/io/seata/commonapi/interceptor/TxAnnotationProcessor.java @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.tcc; +package io.seata.commonapi.interceptor; -import io.seata.rm.tcc.api.TwoPhaseBusinessAction; -import io.seata.rm.tcc.remoting.RemotingDesc; -import io.seata.spring.util.TCCBeanParserUtils; +import io.seata.commonapi.autoproxy.DefaultTransactionAutoProxy; +import io.seata.commonapi.autoproxy.IsTransactionProxyResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; @@ -26,7 +25,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashSet; @@ -35,12 +33,12 @@ import java.util.Set; /** - * An annotation adapter for TCC + * An annotation adapter for transaction annotation * * @author ppf */ -public class TccAnnotationProcessor implements BeanPostProcessor { - private static final Logger LOGGER = LoggerFactory.getLogger(TccAnnotationProcessor.class); +public class TxAnnotationProcessor implements BeanPostProcessor { + private static final Logger LOGGER = LoggerFactory.getLogger(TxAnnotationProcessor.class); private static final List> ANNOTATIONS = new ArrayList<>(4); private static final Set PROXIED_SET = new HashSet<>(); @@ -76,7 +74,7 @@ protected void process(Object bean, String beanName, Class return; } - addTccAdvise(bean, beanName, field, field.getType()); + addTxAdvise(bean, beanName, field, field.getType()); }, field -> !Modifier.isStatic(field.getModifiers()) && (field.isAnnotationPresent(annotation))); @@ -85,7 +83,7 @@ protected void process(Object bean, String beanName, Class } /** - * Add TCC interceptor for tcc proxy bean + * Add transaction interceptor for common transaction proxy bean * * @param bean the bean * @param beanName the bean name @@ -93,22 +91,18 @@ protected void process(Object bean, String beanName, Class * @param serviceClass the serviceClass * @throws IllegalAccessException the illegal access exception */ - public void addTccAdvise(Object bean, String beanName, Field field, Class serviceClass) throws IllegalAccessException { + public void addTxAdvise(Object bean, String beanName, Field field, Class serviceClass) throws IllegalAccessException { Object fieldValue = field.get(bean); if (fieldValue == null) { return; } - for (Method method : field.getType().getMethods()) { - if (!Modifier.isStatic(method.getModifiers()) && (method.isAnnotationPresent(TwoPhaseBusinessAction.class))) { - RemotingDesc remotingDesc = new RemotingDesc(); - remotingDesc.setServiceClass(serviceClass); - - TccActionInterceptor actionInterceptor = new TccActionInterceptor(remotingDesc); - Object proxyBean = TCCBeanParserUtils.createProxy(serviceClass, fieldValue, actionInterceptor); - field.setAccessible(true); - field.set(bean, proxyBean); - LOGGER.info("Bean[" + bean.getClass().getName() + "] with name [" + field.getName() + "] would use proxy [" + actionInterceptor.getClass().getName() + "]"); - } + + IsTransactionProxyResult isProxyTargetBeanResult = DefaultTransactionAutoProxy.get().getIsProxyTargetBeanResult(beanName); + if (isProxyTargetBeanResult.isProxyTargetBean()) { + Object proxyBean = TxBeanParserUtils.createProxy(serviceClass, fieldValue, isProxyTargetBeanResult.getMethodInterceptor()); + field.setAccessible(true); + field.set(bean, proxyBean); + LOGGER.info("Bean[" + bean.getClass().getName() + "] with name [" + field.getName() + "] would use proxy [" + isProxyTargetBeanResult.getMethodInterceptor().getClass().getName() + "]"); } } @@ -127,4 +121,3 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw } } - diff --git a/spring/src/main/java/io/seata/spring/util/TCCBeanParserUtils.java b/common-api/src/main/java/io/seata/commonapi/interceptor/TxBeanParserUtils.java similarity index 57% rename from spring/src/main/java/io/seata/spring/util/TCCBeanParserUtils.java rename to common-api/src/main/java/io/seata/commonapi/interceptor/TxBeanParserUtils.java index 5ccd339cc3b..d53537717bd 100644 --- a/spring/src/main/java/io/seata/spring/util/TCCBeanParserUtils.java +++ b/common-api/src/main/java/io/seata/commonapi/interceptor/TxBeanParserUtils.java @@ -13,48 +13,48 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.util; +package io.seata.commonapi.interceptor; +import io.seata.commonapi.autoproxy.DefaultTransactionAutoProxy; +import io.seata.commonapi.autoproxy.IsTransactionProxyResult; import io.seata.common.DefaultValues; -import io.seata.rm.tcc.api.TwoPhaseBusinessAction; -import io.seata.rm.tcc.config.TCCFenceConfig; -import io.seata.rm.tcc.remoting.Protocols; -import io.seata.rm.tcc.remoting.RemotingDesc; -import io.seata.rm.tcc.remoting.RemotingParser; -import io.seata.rm.tcc.remoting.parser.DefaultRemotingParser; -import io.seata.spring.tcc.TccActionInterceptor; +import io.seata.commonapi.fence.config.CommonFenceConfig; +import io.seata.commonapi.remoting.parser.DefaultRemotingParser; +import io.seata.commonapi.util.SpringProxyUtils; +import io.seata.commonapi.remoting.Protocols; +import io.seata.commonapi.remoting.RemotingDesc; +import io.seata.commonapi.remoting.RemotingParser; +import org.aopalliance.intercept.MethodInterceptor; import org.springframework.aop.framework.ProxyFactory; import org.springframework.context.ApplicationContext; -import java.lang.reflect.Method; - /** - * parser TCC bean + * parser transaction bean * * @author zhangsen */ -public class TCCBeanParserUtils { +public class TxBeanParserUtils { - private TCCBeanParserUtils() { + private TxBeanParserUtils() { } /** - * is auto proxy TCC bean + * is auto proxy transaction bean * * @param bean the bean * @param beanName the bean name * @param applicationContext the application context * @return boolean boolean */ - public static boolean isTccAutoProxy(Object bean, String beanName, ApplicationContext applicationContext) { + public static boolean isTxAutoProxy(Object bean, String beanName, ApplicationContext applicationContext) { boolean isRemotingBean = parserRemotingServiceInfo(bean, beanName); //get RemotingBean description RemotingDesc remotingDesc = DefaultRemotingParser.get().getRemotingBeanDesc(beanName); //is remoting bean if (isRemotingBean) { if (remotingDesc != null && remotingDesc.getProtocol() == Protocols.IN_JVM) { - //LocalTCC - return isTccProxyTargetBean(remotingDesc); + //LocalService + return DefaultTransactionAutoProxy.get().isTransactionAutoProxy(beanName, remotingDesc); } else { // sofa:reference / dubbo:reference, factory bean return false; @@ -64,16 +64,28 @@ public static boolean isTccAutoProxy(Object bean, String beanName, ApplicationCo //check FactoryBean if (isRemotingFactoryBean(bean, beanName, applicationContext)) { remotingDesc = DefaultRemotingParser.get().getRemotingBeanDesc(beanName); - return isTccProxyTargetBean(remotingDesc); + return DefaultTransactionAutoProxy.get().isTransactionAutoProxy(beanName, remotingDesc); } else { return false; } } else { - return isTccProxyTargetBean(remotingDesc); + return DefaultTransactionAutoProxy.get().isTransactionAutoProxy(beanName, remotingDesc); } } } + public static IsTransactionProxyResult getManualProxyResult(Object bean, String beanName) { + parserRemotingServiceInfo(bean, beanName); + RemotingDesc remotingDesc = DefaultRemotingParser.get().getRemotingBeanDesc(beanName); + if (remotingDesc == null) { + return new IsTransactionProxyResult(); + } + if (!DefaultTransactionAutoProxy.get().isTransactionAutoProxy(beanName, remotingDesc)) { + return new IsTransactionProxyResult(); + } + return DefaultTransactionAutoProxy.get().getIsProxyTargetBeanResult(beanName); + } + /** * if it is proxy bean, check if the FactoryBean is Remoting bean * @@ -102,66 +114,24 @@ protected static boolean isRemotingFactoryBean(Object bean, String beanName, } /** - * is TCC proxy-bean/target-bean: LocalTCC , the proxy bean of sofa:reference/dubbo:reference + * init common fence clean task if enable useCommonFence * - * @param remotingDesc the remoting desc - * @return boolean boolean - */ - public static boolean isTccProxyTargetBean(RemotingDesc remotingDesc) { - if (remotingDesc == null) { - return false; - } - //check if it is TCC bean - boolean isTccClazz = false; - Class tccServiceClazz = remotingDesc.getServiceClass(); - Method[] methods = tccServiceClazz.getMethods(); - TwoPhaseBusinessAction twoPhaseBusinessAction; - for (Method method : methods) { - twoPhaseBusinessAction = method.getAnnotation(TwoPhaseBusinessAction.class); - if (twoPhaseBusinessAction != null) { - isTccClazz = true; - break; - } - } - if (!isTccClazz) { - return false; - } - short protocols = remotingDesc.getProtocol(); - //LocalTCC - if (Protocols.IN_JVM == protocols) { - //in jvm TCC bean , AOP - return true; - } - // sofa:reference / dubbo:reference, AOP - return remotingDesc.isReference(); - } - - /** - * init tcc fence clean task if enable useTccFence - * - * @param remotingDesc the remoting desc + * @param remotingDesc the remoting desc * @param applicationContext applicationContext */ - public static void initTccFenceCleanTask(RemotingDesc remotingDesc, ApplicationContext applicationContext) { + public static void initCommonFenceCleanTask(RemotingDesc remotingDesc, ApplicationContext applicationContext, boolean useCommonFence) { if (remotingDesc == null) { return; } - if (applicationContext != null && applicationContext.containsBean(DefaultValues.TCC_FENCE_BEAN_NAME)) { - TCCFenceConfig tccFenceConfig = (TCCFenceConfig) applicationContext.getBean(DefaultValues.TCC_FENCE_BEAN_NAME); - if (tccFenceConfig == null || tccFenceConfig.getInitialized().get()) { + if (applicationContext != null && applicationContext.containsBean(DefaultValues.COMMON_FENCE_BEAN_NAME)) { + CommonFenceConfig commonFenceConfig = (CommonFenceConfig) applicationContext.getBean(DefaultValues.COMMON_FENCE_BEAN_NAME); + if (commonFenceConfig == null || commonFenceConfig.getInitialized().get()) { return; } - Class tccServiceClazz = remotingDesc.getServiceClass(); - Method[] methods = tccServiceClazz.getMethods(); - for (Method method : methods) { - TwoPhaseBusinessAction twoPhaseBusinessAction = method.getAnnotation(TwoPhaseBusinessAction.class); - if (twoPhaseBusinessAction != null && twoPhaseBusinessAction.useTCCFence()) { - if (tccFenceConfig.getInitialized().compareAndSet(false, true)) { - // init tcc fence clean task if enable useTccFence - tccFenceConfig.initCleanTask(); - break; - } - } + + if (useCommonFence && commonFenceConfig.getInitialized().compareAndSet(false, true)) { + // init common fence clean task if enable useCommonFence + commonFenceConfig.initCleanTask(); } } } @@ -182,7 +152,7 @@ protected static boolean parserRemotingServiceInfo(Object bean, String beanName) } /** - * get the remoting description of TCC bean + * get the remoting description of Tx bean * * @param beanName the bean name * @return remoting desc @@ -192,14 +162,14 @@ public static RemotingDesc getRemotingDesc(String beanName) { } /** - * Create a proxy bean for tcc service + * Create a proxy bean for transaction service * - * @param interfaceClass the interface class - * @param fieldValue the field value + * @param interfaceClass the interface class + * @param fieldValue the field value * @param actionInterceptor the action interceptor * @return the service proxy bean */ - public static T createProxy(Class interfaceClass, Object fieldValue, TccActionInterceptor actionInterceptor) { + public static T createProxy(Class interfaceClass, Object fieldValue, MethodInterceptor actionInterceptor) { ProxyFactory factory = new ProxyFactory(); factory.setTarget(fieldValue); factory.setInterfaces(interfaceClass); @@ -207,4 +177,4 @@ public static T createProxy(Class interfaceClass, Object fieldValue, TccA return (T) factory.getProxy(); } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/Protocols.java b/common-api/src/main/java/io/seata/commonapi/remoting/Protocols.java similarity index 96% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/Protocols.java rename to common-api/src/main/java/io/seata/commonapi/remoting/Protocols.java index 3d38f71e82a..669e2527926 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/Protocols.java +++ b/common-api/src/main/java/io/seata/commonapi/remoting/Protocols.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.remoting; +package io.seata.commonapi.remoting; /** * remoting protocols enum diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingDesc.java b/common-api/src/main/java/io/seata/commonapi/remoting/RemotingDesc.java similarity index 89% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingDesc.java rename to common-api/src/main/java/io/seata/commonapi/remoting/RemotingDesc.java index 73b97c97ca9..d3ca4268a01 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingDesc.java +++ b/common-api/src/main/java/io/seata/commonapi/remoting/RemotingDesc.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.remoting; +package io.seata.commonapi.remoting; /** * remoting bean info @@ -27,6 +27,11 @@ public class RemotingDesc { */ private boolean isReference = false; + /** + * is service bean ? + */ + private boolean isService = false; + /** * rpc target bean, the service bean has this property */ @@ -183,4 +188,20 @@ public void setReference(boolean reference) { isReference = reference; } -} + /** + * Is service boolean. + * + * @return the boolean + */ + public boolean isService() { + return isService; + } + + /** + * Sets service. + * @param service the service + */ + public void setService(boolean service) { + isService = service; + } +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java b/common-api/src/main/java/io/seata/commonapi/remoting/RemotingParser.java similarity index 98% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java rename to common-api/src/main/java/io/seata/commonapi/remoting/RemotingParser.java index 2ff32ca4980..1166d134d8c 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java +++ b/common-api/src/main/java/io/seata/commonapi/remoting/RemotingParser.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.remoting; +package io.seata.commonapi.remoting; import io.seata.common.exception.FrameworkException; diff --git a/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java b/common-api/src/main/java/io/seata/commonapi/remoting/TwoPhaseResult.java similarity index 98% rename from tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java rename to common-api/src/main/java/io/seata/commonapi/remoting/TwoPhaseResult.java index 54b4c3139ee..27bf9851401 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java +++ b/common-api/src/main/java/io/seata/commonapi/remoting/TwoPhaseResult.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc; +package io.seata.commonapi.remoting; import io.seata.common.util.StringUtils; @@ -92,4 +92,4 @@ public String toString() { sb.append("]"); return sb.toString(); } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/AbstractedRemotingParser.java b/common-api/src/main/java/io/seata/commonapi/remoting/parser/AbstractedRemotingParser.java similarity index 91% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/AbstractedRemotingParser.java rename to common-api/src/main/java/io/seata/commonapi/remoting/parser/AbstractedRemotingParser.java index 153326688ea..e6e937a77bb 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/AbstractedRemotingParser.java +++ b/common-api/src/main/java/io/seata/commonapi/remoting/parser/AbstractedRemotingParser.java @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.remoting.parser; +package io.seata.commonapi.remoting.parser; import io.seata.common.exception.FrameworkException; -import io.seata.rm.tcc.remoting.RemotingParser; +import io.seata.commonapi.remoting.RemotingParser; /** * The type Abstracted remoting parser. @@ -31,4 +31,4 @@ public boolean isRemoting(Object bean, String beanName) throws FrameworkExceptio return isReference(bean, beanName) || isService(bean, beanName); } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DefaultRemotingParser.java b/common-api/src/main/java/io/seata/commonapi/remoting/parser/DefaultRemotingParser.java similarity index 69% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DefaultRemotingParser.java rename to common-api/src/main/java/io/seata/commonapi/remoting/parser/DefaultRemotingParser.java index 16c1455a4b3..c903394930c 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DefaultRemotingParser.java +++ b/common-api/src/main/java/io/seata/commonapi/remoting/parser/DefaultRemotingParser.java @@ -13,7 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.remoting.parser; +package io.seata.commonapi.remoting.parser; + +import io.seata.common.exception.FrameworkException; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.util.CollectionUtils; +import io.seata.commonapi.interceptor.ActionContextUtil; +import io.seata.commonapi.remoting.RemotingDesc; +import io.seata.commonapi.remoting.RemotingParser; +import io.seata.commonapi.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContextParameter; import java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -22,18 +31,6 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import io.seata.common.exception.FrameworkException; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.util.CollectionUtils; -import io.seata.rm.DefaultResourceManager; -import io.seata.rm.tcc.TCCResource; -import io.seata.rm.tcc.api.BusinessActionContext; -import io.seata.rm.tcc.api.BusinessActionContextParameter; -import io.seata.rm.tcc.api.TwoPhaseBusinessAction; -import io.seata.rm.tcc.interceptor.ActionContextUtil; -import io.seata.rm.tcc.remoting.RemotingDesc; -import io.seata.rm.tcc.remoting.RemotingParser; - /** * parsing remoting bean * @@ -170,41 +167,6 @@ public RemotingDesc parserRemotingServiceInfo(Object bean, String beanName, Remo } remotingServiceMap.put(beanName, remotingBeanDesc); - Class serviceClass = remotingBeanDesc.getServiceClass(); - Method[] methods = serviceClass.getMethods(); - if (remotingParser.isService(bean, beanName)) { - try { - //service bean, registry resource - Object targetBean = remotingBeanDesc.getTargetBean(); - for (Method m : methods) { - TwoPhaseBusinessAction twoPhaseBusinessAction = m.getAnnotation(TwoPhaseBusinessAction.class); - if (twoPhaseBusinessAction != null) { - TCCResource tccResource = new TCCResource(); - tccResource.setActionName(twoPhaseBusinessAction.name()); - tccResource.setTargetBean(targetBean); - tccResource.setPrepareMethod(m); - tccResource.setCommitMethodName(twoPhaseBusinessAction.commitMethod()); - tccResource.setCommitMethod(serviceClass.getMethod(twoPhaseBusinessAction.commitMethod(), - twoPhaseBusinessAction.commitArgsClasses())); - tccResource.setRollbackMethodName(twoPhaseBusinessAction.rollbackMethod()); - tccResource.setRollbackMethod(serviceClass.getMethod(twoPhaseBusinessAction.rollbackMethod(), - twoPhaseBusinessAction.rollbackArgsClasses())); - // set argsClasses - tccResource.setCommitArgsClasses(twoPhaseBusinessAction.commitArgsClasses()); - tccResource.setRollbackArgsClasses(twoPhaseBusinessAction.rollbackArgsClasses()); - // set phase two method's keys - tccResource.setPhaseTwoCommitKeys(this.getTwoPhaseArgs(tccResource.getCommitMethod(), - twoPhaseBusinessAction.commitArgsClasses())); - tccResource.setPhaseTwoRollbackKeys(this.getTwoPhaseArgs(tccResource.getRollbackMethod(), - twoPhaseBusinessAction.rollbackArgsClasses())); - //registry tcc resource - DefaultResourceManager.get().registerResource(tccResource); - } - } - } catch (Throwable t) { - throw new FrameworkException(t, "parser remoting service error"); - } - } if (remotingParser.isReference(bean, beanName)) { //reference bean, TCC proxy remotingBeanDesc.setReference(true); @@ -212,7 +174,7 @@ public RemotingDesc parserRemotingServiceInfo(Object bean, String beanName, Remo return remotingBeanDesc; } - protected String[] getTwoPhaseArgs(Method method, Class[] argsClasses) { + public String[] getTwoPhaseArgs(Method method, Class[] argsClasses) { Annotation[][] parameterAnnotations = method.getParameterAnnotations(); String[] keys = new String[parameterAnnotations.length]; /* @@ -248,4 +210,4 @@ public RemotingDesc getRemotingBeanDesc(String beanName) { return remotingServiceMap.get(beanName); } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboRemotingParser.java b/common-api/src/main/java/io/seata/commonapi/remoting/parser/DubboRemotingParser.java similarity index 85% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboRemotingParser.java rename to common-api/src/main/java/io/seata/commonapi/remoting/parser/DubboRemotingParser.java index 8ded4d41ae5..8e273a4b458 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboRemotingParser.java +++ b/common-api/src/main/java/io/seata/commonapi/remoting/parser/DubboRemotingParser.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.remoting.parser; +package io.seata.commonapi.remoting.parser; import io.seata.common.exception.FrameworkException; import io.seata.common.util.ReflectionUtil; -import io.seata.rm.tcc.remoting.Protocols; -import io.seata.rm.tcc.remoting.RemotingDesc; +import io.seata.commonapi.remoting.Protocols; +import io.seata.commonapi.remoting.RemotingDesc; /** * dubbo remoting bean parsing @@ -31,14 +31,14 @@ public class DubboRemotingParser extends AbstractedRemotingParser { public boolean isReference(Object bean, String beanName) throws FrameworkException { Class c = bean.getClass(); return "com.alibaba.dubbo.config.spring.ReferenceBean".equals(c.getName()) - || "org.apache.dubbo.config.spring.ReferenceBean".equals(c.getName()); + || "org.apache.dubbo.config.spring.ReferenceBean".equals(c.getName()); } @Override public boolean isService(Object bean, String beanName) throws FrameworkException { Class c = bean.getClass(); return "com.alibaba.dubbo.config.spring.ServiceBean".equals(c.getName()) - || "org.apache.dubbo.config.spring.ServiceBean".equals(c.getName()); + || "org.apache.dubbo.config.spring.ServiceBean".equals(c.getName()); } @Override @@ -61,6 +61,8 @@ public RemotingDesc getServiceDesc(Object bean, String beanName) throws Framewor Object targetBean = ReflectionUtil.getFieldValue(bean, "ref"); serviceBeanDesc.setTargetBean(targetBean); } + serviceBeanDesc.setReference(this.isReference(bean, beanName)); + serviceBeanDesc.setService(this.isService(bean, beanName)); return serviceBeanDesc; } catch (Throwable t) { throw new FrameworkException(t); @@ -71,4 +73,4 @@ public RemotingDesc getServiceDesc(Object bean, String beanName) throws Framewor public short getProtocol() { return Protocols.DUBBO; } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/HSFRemotingParser.java b/common-api/src/main/java/io/seata/commonapi/remoting/parser/HSFRemotingParser.java similarity index 91% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/HSFRemotingParser.java rename to common-api/src/main/java/io/seata/commonapi/remoting/parser/HSFRemotingParser.java index ae3e7db0f61..dd4f20e96d8 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/HSFRemotingParser.java +++ b/common-api/src/main/java/io/seata/commonapi/remoting/parser/HSFRemotingParser.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.remoting.parser; +package io.seata.commonapi.remoting.parser; import io.seata.common.exception.FrameworkException; import io.seata.common.util.ReflectionUtil; -import io.seata.rm.tcc.remoting.Protocols; -import io.seata.rm.tcc.remoting.RemotingDesc; +import io.seata.commonapi.remoting.Protocols; +import io.seata.commonapi.remoting.RemotingDesc; /** * HSF Remote Bean Parser @@ -85,6 +85,8 @@ public RemotingDesc getServiceDesc(Object bean, String beanName) throws Framewor serviceBeanDesc.setUniqueId(uniqueId); serviceBeanDesc.setGroup(group); serviceBeanDesc.setProtocol(Protocols.HSF); + serviceBeanDesc.setReference(this.isReference(bean, beanName)); + serviceBeanDesc.setService(this.isService(bean, beanName)); return serviceBeanDesc; } else if (isService(bean, beanName)) { Object consumerBean = ReflectionUtil.getFieldValue(bean, "providerBean"); @@ -103,6 +105,8 @@ public RemotingDesc getServiceDesc(Object bean, String beanName) throws Framewor Object targetBean = ReflectionUtil.getFieldValue(metadata, "target"); serviceBeanDesc.setTargetBean(targetBean); serviceBeanDesc.setProtocol(Protocols.HSF); + serviceBeanDesc.setReference(this.isReference(bean, beanName)); + serviceBeanDesc.setService(this.isService(bean, beanName)); return serviceBeanDesc; } } catch (Throwable t) { @@ -116,4 +120,4 @@ public RemotingDesc getServiceDesc(Object bean, String beanName) throws Framewor public short getProtocol() { return Protocols.HSF; } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java b/common-api/src/main/java/io/seata/commonapi/remoting/parser/SofaRpcRemotingParser.java similarity index 88% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java rename to common-api/src/main/java/io/seata/commonapi/remoting/parser/SofaRpcRemotingParser.java index 5debae1c3d5..16d3cfc5e1c 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java +++ b/common-api/src/main/java/io/seata/commonapi/remoting/parser/SofaRpcRemotingParser.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.remoting.parser; +package io.seata.commonapi.remoting.parser; import io.seata.common.exception.FrameworkException; import io.seata.common.util.ReflectionUtil; -import io.seata.rm.tcc.remoting.Protocols; -import io.seata.rm.tcc.remoting.RemotingDesc; +import io.seata.commonapi.remoting.Protocols; +import io.seata.commonapi.remoting.RemotingDesc; /** * sofa-rpc remoting bean parsing @@ -30,7 +30,7 @@ public class SofaRpcRemotingParser extends AbstractedRemotingParser { @Override public boolean isReference(Object bean, String beanName) - throws FrameworkException { + throws FrameworkException { String beanClassName = bean.getClass().getName(); return "com.alipay.sofa.runtime.spring.factory.ReferenceFactoryBean".equals(beanClassName); } @@ -60,6 +60,8 @@ public RemotingDesc getServiceDesc(Object bean, String beanName) throws Framewor Object targetBean = ReflectionUtil.getFieldValue(bean, "ref"); serviceBeanDesc.setTargetBean(targetBean); } + serviceBeanDesc.setReference(this.isReference(bean, beanName)); + serviceBeanDesc.setService(this.isService(bean, beanName)); return serviceBeanDesc; } catch (Throwable t) { throw new FrameworkException(t); @@ -70,4 +72,4 @@ public RemotingDesc getServiceDesc(Object bean, String beanName) throws Framewor public short getProtocol() { return Protocols.SOFA_RPC; } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java b/common-api/src/main/java/io/seata/commonapi/rm/tcc/api/BusinessActionContext.java similarity index 91% rename from tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java rename to common-api/src/main/java/io/seata/commonapi/rm/tcc/api/BusinessActionContext.java index f11b3249940..8fb2c59adea 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java +++ b/common-api/src/main/java/io/seata/commonapi/rm/tcc/api/BusinessActionContext.java @@ -13,14 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.api; +package io.seata.commonapi.rm.tcc.api; import java.io.Serializable; import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import io.seata.rm.tcc.interceptor.ActionContextUtil; +import io.seata.core.model.BranchType; +import io.seata.commonapi.interceptor.ActionContextUtil; + /** * The type Business action context. @@ -38,7 +40,7 @@ public class BusinessActionContext implements Serializable { /** * delay branch report while sharing params to tcc phase 2 to enhance performance * - * @see io.seata.rm.tcc.api.BusinessActionContextUtil + * @see BusinessActionContextUtil * @see io.seata.rm.tcc.api.TwoPhaseBusinessAction */ private Boolean isDelayReport; @@ -46,10 +48,15 @@ public class BusinessActionContext implements Serializable { /** * mark that actionContext has been updated by business * - * @see io.seata.rm.tcc.api.BusinessActionContextUtil + * @see BusinessActionContextUtil */ private Boolean isUpdated; + /** + * branch Type + */ + private BranchType branchType; + /** * action context */ @@ -219,6 +226,14 @@ public void setUpdated(Boolean updated) { isUpdated = updated; } + public BranchType getBranchType() { + return branchType; + } + + public void setBranchType(BranchType branchType) { + this.branchType = branchType; + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -227,8 +242,9 @@ public String toString() { .append(",action_name:").append(actionName) .append(",is_delay_report:").append(isDelayReport) .append(",is_updated:").append(isDelayReport) + .append(",branch_type:").append(branchType) .append(",action_context:") .append(actionContext).append("]"); return sb.toString(); } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java b/common-api/src/main/java/io/seata/commonapi/rm/tcc/api/BusinessActionContextParameter.java similarity index 84% rename from tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java rename to common-api/src/main/java/io/seata/commonapi/rm/tcc/api/BusinessActionContextParameter.java index 518a7c5dec4..0af8f7582ce 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java +++ b/common-api/src/main/java/io/seata/commonapi/rm/tcc/api/BusinessActionContextParameter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.api; +package io.seata.commonapi.rm.tcc.api; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -26,7 +26,7 @@ * add this annotation on the parameters of the try method, and the parameters will be passed to the action context * * @author zhangsen - * @see io.seata.rm.tcc.interceptor.ActionContextUtil + * @see io.seata.spring.interceptor.ActionContextUtil */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.FIELD}) @@ -36,7 +36,7 @@ * parameter's name. Synonym for {@link #paramName()}. * * @return the name of the param or field - * @see io.seata.rm.tcc.interceptor.ActionContextUtil#getParamNameFromAnnotation + * @see io.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation */ String value() default ""; @@ -44,7 +44,7 @@ * parameter's name. Synonym for {@link #value()}. * * @return the name of the param or field - * @see io.seata.rm.tcc.interceptor.ActionContextUtil#getParamNameFromAnnotation + * @see io.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation */ String paramName() default ""; @@ -61,7 +61,7 @@ * Specify the index of the parameter in the List * * @return the index of the List - * @see io.seata.rm.tcc.interceptor.ActionContextUtil#getByIndex + * @see io.seata.spring.interceptor.ActionContextUtil#getByIndex */ int index() default -1; @@ -70,8 +70,8 @@ * if {@code index >= 0}, the object get from the List and then do get the parameter from the property of the object * * @return the boolean - * @see io.seata.rm.tcc.interceptor.ActionContextUtil#loadParamByAnnotationAndPutToContext - * @see io.seata.rm.tcc.interceptor.ActionContextUtil#fetchContextFromObject + * @see io.seata.spring.interceptor.ActionContextUtil#loadParamByAnnotationAndPutToContext + * @see io.seata.spring.interceptor.ActionContextUtil#fetchContextFromObject */ boolean isParamInProperty() default false; -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java b/common-api/src/main/java/io/seata/commonapi/rm/tcc/api/BusinessActionContextUtil.java similarity index 68% rename from tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java rename to common-api/src/main/java/io/seata/commonapi/rm/tcc/api/BusinessActionContextUtil.java index 3bb0158df9d..0b5111dbdc2 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java +++ b/common-api/src/main/java/io/seata/commonapi/rm/tcc/api/BusinessActionContextUtil.java @@ -13,23 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.api; - -import java.util.Collections; -import java.util.Map; +package io.seata.commonapi.rm.tcc.api; import com.alibaba.fastjson.JSON; import io.seata.common.Constants; import io.seata.common.exception.FrameworkException; import io.seata.common.util.CollectionUtils; +import io.seata.common.util.StringUtils; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; +import io.seata.commonapi.interceptor.ActionContextUtil; import io.seata.rm.DefaultResourceManager; -import io.seata.rm.tcc.interceptor.ActionContextUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + /** * the api of sharing business action context to tcc phase 2 * @@ -105,11 +106,11 @@ public static boolean reportContext(BusinessActionContext actionContext) { try { // branch report DefaultResourceManager.get().branchReport( - BranchType.TCC, + actionContext.getBranchType(), actionContext.getXid(), actionContext.getBranchId(), BranchStatus.Registered, - JSON.toJSONString(Collections.singletonMap(Constants.TCC_ACTION_CONTEXT, actionContext.getActionContext())) + JSON.toJSONString(Collections.singletonMap(Constants.TX_ACTION_CONTEXT, actionContext.getActionContext())) ); // reset to un_updated @@ -133,4 +134,43 @@ public static void setContext(BusinessActionContext context) { public static void clear() { CONTEXT_HOLDER.remove(); } -} + + /** + * transfer tcc applicationData to BusinessActionContext + * + * @param xid the xid + * @param branchId the branch id + * @param resourceId the resource id + * @param applicationData the application data + * @return business action context + */ + public static BusinessActionContext getBusinessActionContext(String xid, long branchId, String resourceId, + String applicationData) { + Map actionContextMap = null; + if (StringUtils.isNotBlank(applicationData)) { + Map tccContext = JSON.parseObject(applicationData, Map.class); + actionContextMap = (Map) tccContext.get(Constants.TX_ACTION_CONTEXT); + } + if (actionContextMap == null) { + actionContextMap = new HashMap<>(2); + } + + //instance the action context + BusinessActionContext businessActionContext = new BusinessActionContext( + xid, String.valueOf(branchId), actionContextMap); + businessActionContext.setActionName(resourceId); + return businessActionContext; + } + + public static Object[] getTwoPhaseMethodParams(String[] keys, Class[] argsClasses, BusinessActionContext businessActionContext) { + Object[] args = new Object[argsClasses.length]; + for (int i = 0; i < argsClasses.length; i++) { + if (argsClasses[i].equals(BusinessActionContext.class)) { + args[i] = businessActionContext; + } else { + args[i] = businessActionContext.getActionContext(keys[i], argsClasses[i]); + } + } + return args; + } +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/ParamType.java b/common-api/src/main/java/io/seata/commonapi/rm/tcc/api/ParamType.java similarity index 96% rename from tcc/src/main/java/io/seata/rm/tcc/api/ParamType.java rename to common-api/src/main/java/io/seata/commonapi/rm/tcc/api/ParamType.java index 87b65c07da1..7ff34abc083 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/api/ParamType.java +++ b/common-api/src/main/java/io/seata/commonapi/rm/tcc/api/ParamType.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.api; +package io.seata.commonapi.rm.tcc.api; /** * The enum ParamType diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboUtil.java b/common-api/src/main/java/io/seata/commonapi/util/DubboUtil.java similarity index 98% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboUtil.java rename to common-api/src/main/java/io/seata/commonapi/util/DubboUtil.java index c33651ca09b..d6bfbb0ee8e 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboUtil.java +++ b/common-api/src/main/java/io/seata/commonapi/util/DubboUtil.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.remoting.parser; +package io.seata.commonapi.util; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; diff --git a/spring/src/main/java/io/seata/spring/util/SpringProxyUtils.java b/common-api/src/main/java/io/seata/commonapi/util/SpringProxyUtils.java similarity index 98% rename from spring/src/main/java/io/seata/spring/util/SpringProxyUtils.java rename to common-api/src/main/java/io/seata/commonapi/util/SpringProxyUtils.java index 567903b75ac..96767b42315 100644 --- a/spring/src/main/java/io/seata/spring/util/SpringProxyUtils.java +++ b/common-api/src/main/java/io/seata/commonapi/util/SpringProxyUtils.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.util; +package io.seata.commonapi.util; import java.lang.reflect.Field; import java.lang.reflect.Proxy; @@ -22,7 +22,6 @@ import java.util.Set; import io.seata.common.util.CollectionUtils; -import io.seata.rm.tcc.remoting.parser.DubboUtil; import org.springframework.aop.TargetSource; import org.springframework.aop.framework.Advised; import org.springframework.aop.framework.AdvisedSupport; diff --git a/common-api/src/main/resources/META-INF/services/io.seata.commonapi.autoproxy.TransactionAutoProxy b/common-api/src/main/resources/META-INF/services/io.seata.commonapi.autoproxy.TransactionAutoProxy new file mode 100644 index 00000000000..a27056a0435 --- /dev/null +++ b/common-api/src/main/resources/META-INF/services/io.seata.commonapi.autoproxy.TransactionAutoProxy @@ -0,0 +1 @@ +io.seata.rm.tcc.autoproxy.TccTransactionAutoProxy \ No newline at end of file diff --git a/common-api/src/main/resources/META-INF/services/io.seata.commonapi.remoting.RemotingParser b/common-api/src/main/resources/META-INF/services/io.seata.commonapi.remoting.RemotingParser new file mode 100644 index 00000000000..9d79ac4dd73 --- /dev/null +++ b/common-api/src/main/resources/META-INF/services/io.seata.commonapi.remoting.RemotingParser @@ -0,0 +1,4 @@ +io.seata.commonapi.remoting.parser.DubboRemotingParser +io.seata.rm.tcc.remoting.parser.LocalTCCRemotingParser +io.seata.commonapi.remoting.parser.SofaRpcRemotingParser +io.seata.commonapi.remoting.parser.HSFRemotingParser \ No newline at end of file diff --git a/common/src/main/java/io/seata/common/Constants.java b/common/src/main/java/io/seata/common/Constants.java index 08bb175eadd..f5a4507dcc7 100644 --- a/common/src/main/java/io/seata/common/Constants.java +++ b/common/src/main/java/io/seata/common/Constants.java @@ -69,7 +69,7 @@ public interface Constants { /** * Use TCC fence */ - String USE_TCC_FENCE = "useTCCFence"; + String USE_COMMON_FENCE = "useTCCFence"; /** * phase one method name @@ -94,7 +94,7 @@ public interface Constants { /** * branch context */ - String TCC_ACTION_CONTEXT = "actionContext"; + String TX_ACTION_CONTEXT = "actionContext"; /** * default charset name @@ -165,5 +165,10 @@ public interface Constants { * The constant REGISTRY_TYPE_SPLIT_CHAR. */ String REGISTRY_TYPE_SPLIT_CHAR = ","; + + /** + * phase two compensation method name + */ + String COMPENSATION_METHOD = "sys::compensation"; -} +} \ No newline at end of file diff --git a/common/src/main/java/io/seata/common/DefaultValues.java b/common/src/main/java/io/seata/common/DefaultValues.java index 180d75dcfe3..173b2b5c1ec 100644 --- a/common/src/main/java/io/seata/common/DefaultValues.java +++ b/common/src/main/java/io/seata/common/DefaultValues.java @@ -141,29 +141,34 @@ public interface DefaultValues { * the constant TM_INTERCEPTOR_ORDER */ int TM_INTERCEPTOR_ORDER = Integer.MIN_VALUE + 1000; - + /** * the constant TCC_ACTION_INTERCEPTOR_ORDER */ int TCC_ACTION_INTERCEPTOR_ORDER = Integer.MIN_VALUE + 1000; + /** + * the constant SAGA_ACTION_INTERCEPTOR_ORDER + */ + int SAGA_ACTION_INTERCEPTOR_ORDER = Integer.MIN_VALUE + 1000; + /** * the constant DEFAULT_DISTRIBUTED_LOCK_EXPIRE */ int DEFAULT_DISTRIBUTED_LOCK_EXPIRE = 10000; /** - * the constant DEFAULT_TCC_FENCE_CLEAN_PERIOD + * the constant DEFAULT_COMMON_FENCE_CLEAN_PERIOD */ - int DEFAULT_TCC_FENCE_CLEAN_PERIOD = 1; + int DEFAULT_COMMON_FENCE_CLEAN_PERIOD = 1; /** - * the constant DEFAULT_TCC_FENCE_LOG_TABLE_NAME + * the constant DEFAULT_COMMON_FENCE_LOG_TABLE_NAME */ - String DEFAULT_TCC_FENCE_LOG_TABLE_NAME = "tcc_fence_log"; + String DEFAULT_COMMON_FENCE_LOG_TABLE_NAME = "tcc_fence_log"; /** - * the constant TCC_FENCE_BEAN_NAME + * the constant COMMON_FENCE_BEAN_NAME */ - String TCC_FENCE_BEAN_NAME = "tccFenceConfig"; + String COMMON_FENCE_BEAN_NAME = "tccFenceConfig"; /** * the constant DEFAULT_RPC_RM_REQUEST_TIMEOUT @@ -269,4 +274,4 @@ public interface DefaultValues { * DEFAULT_ENABLE_BRANCH_ASYNC_REMOVE */ boolean DEFAULT_ENABLE_BRANCH_ASYNC_REMOVE = false; -} +} \ No newline at end of file diff --git a/manual-api/pom.xml b/manual-api/pom.xml new file mode 100644 index 00000000000..bf587acc1e3 --- /dev/null +++ b/manual-api/pom.xml @@ -0,0 +1,42 @@ + + + + + io.seata + seata-parent + ${revision} + + 4.0.0 + manual-api + manual-api ${project.version} + jar + + + + ${project.groupId} + common-api + ${project.version} + + + net.bytebuddy + byte-buddy + 1.12.17 + + + diff --git a/manual-api/src/main/java/io/seata/manualapi/advisor/DefaultSeataAdvisor.java b/manual-api/src/main/java/io/seata/manualapi/advisor/DefaultSeataAdvisor.java new file mode 100644 index 00000000000..b513ced6e68 --- /dev/null +++ b/manual-api/src/main/java/io/seata/manualapi/advisor/DefaultSeataAdvisor.java @@ -0,0 +1,39 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.manualapi.advisor; + +import io.seata.commonapi.autoproxy.IsTransactionProxyResult; +import io.seata.commonapi.interceptor.TxBeanParserUtils; +import net.bytebuddy.asm.Advice; + +import java.lang.reflect.Method; + +/** + * The default seata advisor + */ +public class DefaultSeataAdvisor { + + @Advice.OnMethodEnter + public static void onMethodEnter(@Advice.Origin Method method, @Advice.AllArguments Object[] arguments, @Advice.This Object bean) throws Throwable { + + IsTransactionProxyResult isTransactionProxyResult = TxBeanParserUtils.getManualProxyResult(bean, bean.getClass().getName()); + if (isTransactionProxyResult.isProxyTargetBean()) { + // init tcc fence clean task if enable useTccFence +// TxBeanParserUtils.initCommonFenceCleanTask(TxBeanParserUtils.getRemotingDesc(beanName), applicationContext, isTransactionProxyResult.isUseCommonFence()); + isTransactionProxyResult.getManualApiExecute().manualApiBefore(method, arguments); + } + } +} diff --git a/manual-api/src/main/java/io/seata/manualapi/api/SeataClient.java b/manual-api/src/main/java/io/seata/manualapi/api/SeataClient.java new file mode 100644 index 00000000000..840ae6faa91 --- /dev/null +++ b/manual-api/src/main/java/io/seata/manualapi/api/SeataClient.java @@ -0,0 +1,43 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.manualapi.api; + +import io.seata.manualapi.advisor.DefaultSeataAdvisor; +import io.seata.rm.RMClient; +import io.seata.tm.TMClient; +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.matcher.ElementMatchers; + +public class SeataClient { + + public static void init(String applicationId, String txServiceGroup) { + TMClient.init(applicationId, txServiceGroup); + RMClient.init(applicationId, txServiceGroup); + } + + public static T createProxy(Class tccAction) throws InstantiationException, IllegalAccessException { + + return new ByteBuddy() + .subclass(tccAction) + .method(ElementMatchers.any()) + .intercept(Advice.to(DefaultSeataAdvisor.class)) + .make() + .load(tccAction.getClassLoader()) + .getLoaded() + .newInstance(); + } +} diff --git a/pom.xml b/pom.xml index b63a62c9961..5b0046fc267 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,8 @@ sqlparser server ext/apm-seata-skywalking-plugin + common-api + manual-api diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataClientEnvironmentPostProcessor.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataClientEnvironmentPostProcessor.java index 5939248427a..8e34ff87962 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataClientEnvironmentPostProcessor.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataClientEnvironmentPostProcessor.java @@ -16,35 +16,18 @@ package io.seata.spring.boot.autoconfigure; import io.seata.common.holder.ObjectHolder; -import io.seata.rm.tcc.config.TCCFenceConfig; +import io.seata.commonapi.fence.config.CommonFenceConfig; import io.seata.saga.engine.StateMachineConfig; import io.seata.spring.boot.autoconfigure.properties.SagaAsyncThreadPoolProperties; import io.seata.spring.boot.autoconfigure.properties.SeataProperties; -import io.seata.spring.boot.autoconfigure.properties.client.LoadBalanceProperties; -import io.seata.spring.boot.autoconfigure.properties.client.LockProperties; -import io.seata.spring.boot.autoconfigure.properties.client.RmProperties; -import io.seata.spring.boot.autoconfigure.properties.client.ServiceProperties; -import io.seata.spring.boot.autoconfigure.properties.client.TmProperties; -import io.seata.spring.boot.autoconfigure.properties.client.UndoCompressProperties; -import io.seata.spring.boot.autoconfigure.properties.client.UndoProperties; +import io.seata.spring.boot.autoconfigure.properties.client.*; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.Ordered; import org.springframework.core.env.ConfigurableEnvironment; import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; -import static io.seata.spring.boot.autoconfigure.StarterConstants.CLIENT_RM_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.CLIENT_TM_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.COMPRESS_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.LOAD_BALANCE_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.LOCK_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.PROPERTY_BEAN_MAP; -import static io.seata.spring.boot.autoconfigure.StarterConstants.SAGA_ASYNC_THREAD_POOL_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.SAGA_STATE_MACHINE_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.SEATA_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.SERVICE_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.TCC_FENCE_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.UNDO_PREFIX; +import static io.seata.spring.boot.autoconfigure.StarterConstants.*; /** * @author xingfudeshi@gmail.com @@ -64,7 +47,7 @@ public void postProcessEnvironment(ConfigurableEnvironment environment, SpringAp PROPERTY_BEAN_MAP.put(UNDO_PREFIX, UndoProperties.class); PROPERTY_BEAN_MAP.put(COMPRESS_PREFIX, UndoCompressProperties.class); PROPERTY_BEAN_MAP.put(LOAD_BALANCE_PREFIX, LoadBalanceProperties.class); - PROPERTY_BEAN_MAP.put(TCC_FENCE_PREFIX, TCCFenceConfig.class); + PROPERTY_BEAN_MAP.put(TCC_FENCE_PREFIX, CommonFenceConfig.class); PROPERTY_BEAN_MAP.put(SAGA_STATE_MACHINE_PREFIX, StateMachineConfig.class); PROPERTY_BEAN_MAP.put(SAGA_ASYNC_THREAD_POOL_PREFIX, SagaAsyncThreadPoolProperties.class); } @@ -73,4 +56,4 @@ public void postProcessEnvironment(ConfigurableEnvironment environment, SpringAp public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } -} +} \ No newline at end of file diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataTCCFenceAutoConfiguration.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataTCCFenceAutoConfiguration.java index 3f4cd97a87f..a6542ba636a 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataTCCFenceAutoConfiguration.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataTCCFenceAutoConfiguration.java @@ -15,7 +15,7 @@ */ package io.seata.spring.boot.autoconfigure; -import io.seata.rm.tcc.config.TCCFenceConfig; +import io.seata.commonapi.fence.config.CommonFenceConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -37,7 +37,7 @@ */ @ConditionalOnExpression("${seata.enabled:true}") @ConditionalOnBean(type = {"javax.sql.DataSource", "org.springframework.transaction.PlatformTransactionManager"}) -@ConditionalOnMissingBean(TCCFenceConfig.class) +@ConditionalOnMissingBean(CommonFenceConfig.class) @AutoConfigureAfter({SeataCoreAutoConfiguration.class, DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class}) public class SeataTCCFenceAutoConfiguration { @@ -46,13 +46,13 @@ public class SeataTCCFenceAutoConfiguration { @Bean @ConfigurationProperties(StarterConstants.TCC_FENCE_PREFIX) - public TCCFenceConfig tccFenceConfig( + public CommonFenceConfig tccFenceConfig( DataSource dataSource, PlatformTransactionManager transactionManager, @Qualifier(TCC_FENCE_DATA_SOURCE_BEAN_NAME) @Autowired(required = false) DataSource tccFenceDataSource, @Qualifier(TCC_FENCE_TRANSACTION_MANAGER_BEAN_NAME) @Autowired(required = false) PlatformTransactionManager tccFenceTransactionManager) { - return new TCCFenceConfig(tccFenceDataSource != null ? tccFenceDataSource : dataSource, + return new CommonFenceConfig(tccFenceDataSource != null ? tccFenceDataSource : dataSource, tccFenceTransactionManager != null ? tccFenceTransactionManager : transactionManager); } -} +} \ No newline at end of file diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 5ca2a8de55c..1c0376f2db5 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -248,14 +248,14 @@ "name": "seata.tcc.fence.log-table-name", "type": "java.lang.String", "description": "TCC fence log table name.", - "sourceType": "io.seata.rm.tcc.config.TCCFenceConfig", + "sourceType": "io.seata.commonapi.fence.config.CommonFenceConfig", "defaultValue": "tcc_fence_log" }, { "name": "seata.tcc.fence.clean-period", "type": "java.time.Duration", "description": "TCC fence log clean period. only duration type format are supported.", - "sourceType": "io.seata.rm.tcc.config.TCCFenceConfig", + "sourceType": "io.seata.commonapi.fence.config.CommonFenceConfig", "defaultValue": "1d" }, { diff --git a/spring/pom.xml b/spring/pom.xml index c67e64c763a..3979e8a906d 100644 --- a/spring/pom.xml +++ b/spring/pom.xml @@ -41,12 +41,12 @@ ${project.groupId} - seata-tcc + seata-rm ${project.version} ${project.groupId} - seata-rm + common-api ${project.version} @@ -64,6 +64,10 @@ org.springframework spring-context + + org.springframework + spring-jdbc + org.jetbrains.kotlin kotlin-stdlib-jdk8 @@ -78,8 +82,10 @@ org.jetbrains.kotlinx kotlinx-coroutines-core - - + + com.alibaba + fastjson + @@ -102,4 +108,4 @@ - + \ No newline at end of file diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java index 852d959e55e..15e0f049f5f 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java @@ -25,6 +25,8 @@ import javax.annotation.Nullable; +import io.seata.commonapi.autoproxy.DefaultTransactionAutoProxy; +import io.seata.commonapi.autoproxy.IsTransactionProxyResult; import io.seata.common.util.CollectionUtils; import io.seata.common.util.StringUtils; import io.seata.config.ConfigurationCache; @@ -35,12 +37,11 @@ import io.seata.core.rpc.ShutdownHook; import io.seata.core.rpc.netty.RmNettyRemotingClient; import io.seata.core.rpc.netty.TmNettyRemotingClient; +import io.seata.commonapi.interceptor.TxBeanParserUtils; import io.seata.rm.RMClient; import io.seata.spring.annotation.scannercheckers.PackageScannerChecker; -import io.seata.spring.tcc.TccActionInterceptor; import io.seata.spring.util.OrderUtil; -import io.seata.spring.util.SpringProxyUtils; -import io.seata.spring.util.TCCBeanParserUtils; +import io.seata.commonapi.util.SpringProxyUtils; import io.seata.tm.TMClient; import io.seata.tm.api.FailureHandler; import org.aopalliance.aop.Advice; @@ -209,8 +210,8 @@ private void initClient() { } if (DEFAULT_TX_GROUP_OLD.equals(txServiceGroup)) { LOGGER.warn("the default value of seata.tx-service-group: {} has already changed to {} since Seata 1.5, " + - "please change your default configuration as soon as possible " + - "and we don't recommend you to use default tx-service-group's value provided by seata", + "please change your default configuration as soon as possible " + + "and we don't recommend you to use default tx-service-group's value provided by seata", DEFAULT_TX_GROUP_OLD, DEFAULT_TX_GROUP); } if (StringUtils.isNullOrEmpty(applicationId) || StringUtils.isNullOrEmpty(txServiceGroup)) { @@ -245,23 +246,24 @@ private void registerSpringShutdownHook() { /** * The following will be scanned, and added corresponding interceptor: - * + *

* TM: + * * @see io.seata.spring.annotation.GlobalTransactional // TM annotation * Corresponding interceptor: * @see io.seata.spring.annotation.GlobalTransactionalInterceptor#handleGlobalTransaction(MethodInvocation, AspectTransactional) // TM handler - * + *

* GlobalLock: * @see io.seata.spring.annotation.GlobalLock // GlobalLock annotation * Corresponding interceptor: * @see io.seata.spring.annotation.GlobalTransactionalInterceptor#handleGlobalLock(MethodInvocation, GlobalLock) // GlobalLock handler - * + *

* TCC mode: * @see io.seata.rm.tcc.api.LocalTCC // TCC annotation on interface * @see io.seata.rm.tcc.api.TwoPhaseBusinessAction // TCC annotation on try method - * @see io.seata.rm.tcc.remoting.RemotingParser // Remote TCC service parser + * @see io.seata.spring.remoting.RemotingParser // Remote TCC service parser * Corresponding interceptor: - * @see io.seata.spring.tcc.TccActionInterceptor // the interceptor of TCC mode + * @see io.seata.rm.tcc.interceptor.TccActionInterceptor // the interceptor of TCC mode */ @Override protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { @@ -276,20 +278,21 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) return bean; } interceptor = null; - //check TCC proxy - if (TCCBeanParserUtils.isTccAutoProxy(bean, beanName, applicationContext)) { + //check Transaction proxy + if (TxBeanParserUtils.isTxAutoProxy(bean, beanName, applicationContext)) { + IsTransactionProxyResult isTransactionProxyResult = DefaultTransactionAutoProxy.get().getIsProxyTargetBeanResult(beanName); // init tcc fence clean task if enable useTccFence - TCCBeanParserUtils.initTccFenceCleanTask(TCCBeanParserUtils.getRemotingDesc(beanName), applicationContext); - //TCC interceptor, proxy bean of sofa:reference/dubbo:reference, and LocalTCC - interceptor = new TccActionInterceptor(TCCBeanParserUtils.getRemotingDesc(beanName)); + TxBeanParserUtils.initCommonFenceCleanTask(TxBeanParserUtils.getRemotingDesc(beanName), applicationContext, isTransactionProxyResult.isUseCommonFence()); + //transaction interceptor(TCC/SAGA), proxy bean of sofa:reference/dubbo:reference, LocalTCC and LocalService + interceptor = isTransactionProxyResult.getMethodInterceptor(); ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, - (ConfigurationChangeListener)interceptor); + (ConfigurationChangeListener) interceptor); } else { Class serviceInterface = SpringProxyUtils.findTargetClass(bean); Class[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean); if (!existsAnnotation(new Class[]{serviceInterface}) - && !existsAnnotation(interfacesIfJdk)) { + && !existsAnnotation(interfacesIfJdk)) { return bean; } @@ -297,7 +300,7 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) globalTransactionalInterceptor = new GlobalTransactionalInterceptor(failureHandlerHook); ConfigurationCache.addConfigListener( ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, - (ConfigurationChangeListener)globalTransactionalInterceptor); + (ConfigurationChangeListener) globalTransactionalInterceptor); } interceptor = globalTransactionalInterceptor; } @@ -325,7 +328,7 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) private boolean doCheckers(Object bean, String beanName) { if (PROXYED_SET.contains(beanName) || EXCLUDE_BEAN_NAME_SET.contains(beanName) - || FactoryBean.class.isAssignableFrom(bean.getClass())) { + || FactoryBean.class.isAssignableFrom(bean.getClass())) { return false; } @@ -406,7 +409,7 @@ private Integer computePositionIfHasTransactionInterceptor(AdvisedSupport advise Advice seataAdvice = seataAdvisor.getAdvice(); if (SeataInterceptorPosition.AfterTransaction == seataInterceptorPosition && OrderUtil.higherThan(seataOrder, transactionInterceptorOrder)) { int newSeataOrder = OrderUtil.lower(transactionInterceptorOrder, 1); - ((SeataInterceptor)seataAdvice).setOrder(newSeataOrder); + ((SeataInterceptor) seataAdvice).setOrder(newSeataOrder); if (LOGGER.isWarnEnabled()) { LOGGER.warn("The {}'s order '{}' is higher or equals than {}'s order '{}' , reset {}'s order to lower order '{}'.", seataAdvice.getClass().getSimpleName(), seataOrder, @@ -417,7 +420,7 @@ private Integer computePositionIfHasTransactionInterceptor(AdvisedSupport advise return transactionInterceptorPosition + 1; } else if (SeataInterceptorPosition.BeforeTransaction == seataInterceptorPosition && OrderUtil.lowerThan(seataOrder, transactionInterceptorOrder)) { int newSeataOrder = OrderUtil.higher(transactionInterceptorOrder, 1); - ((SeataInterceptor)seataAdvice).setOrder(newSeataOrder); + ((SeataInterceptor) seataAdvice).setOrder(newSeataOrder); if (LOGGER.isWarnEnabled()) { LOGGER.warn("The {}'s order '{}' is lower or equals than {}'s order '{}' , reset {}'s order to higher order '{}'.", seataAdvice.getClass().getSimpleName(), seataOrder, @@ -448,7 +451,7 @@ private int findPositionInAdvisors(Advisor[] advisors, Advisor seataAdvisor) { private SeataInterceptorPosition getSeataInterceptorPosition(Advisor seataAdvisor) { Advice seataAdvice = seataAdvisor.getAdvice(); if (seataAdvice instanceof SeataInterceptor) { - return ((SeataInterceptor)seataAdvice).getPosition(); + return ((SeataInterceptor) seataAdvice).getPosition(); } else { return SeataInterceptorPosition.Any; } @@ -505,7 +508,7 @@ public void afterPropertiesSet() { LOGGER.info("Global transaction is disabled."); } ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, - (ConfigurationChangeListener)this); + (ConfigurationChangeListener) this); return; } if (initialized.compareAndSet(false, true)) { @@ -558,4 +561,4 @@ public static void addScannerExcludeBeanNames(String... beanNames) { EXCLUDE_BEAN_NAME_SET.addAll(Arrays.asList(beanNames)); } } -} +} \ No newline at end of file diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactional.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactional.java index 2fb478073e9..40ff30dad0c 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactional.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactional.java @@ -40,7 +40,7 @@ * @see io.seata.spring.annotation.datasource.SeataAutoDataSourceProxyAdvice#invoke(MethodInvocation) io.seata.spring * .annotation.datasource.SeataAutoDataSourceProxyAdvice#invoke(MethodInvocation)// RM: the interceptor of * GlobalLockLogic and AT/XA mode - * @see io.seata.spring.tcc.TccActionInterceptor#invoke(MethodInvocation) io.seata.spring.tcc + * @see io.seata.rm.tcc.interceptor.TccActionInterceptor#invoke(MethodInvocation) io.seata.spring.tcc * .TccActionInterceptor#invoke(MethodInvocation)// RM: the interceptor of TCC mode */ @Retention(RetentionPolicy.RUNTIME) diff --git a/tcc/pom.xml b/tcc/pom.xml index 70d8a152bdf..67a7b6707f4 100644 --- a/tcc/pom.xml +++ b/tcc/pom.xml @@ -52,5 +52,15 @@ com.alibaba fastjson + + io.seata + seata-spring + ${project.version} + + + ${project.groupId} + common-api + ${project.version} + - + \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java b/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java index f431861e7ce..481dd1b702d 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java +++ b/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java @@ -15,23 +15,23 @@ */ package io.seata.rm.tcc; -import java.lang.reflect.Method; -import java.lang.reflect.UndeclaredThrowableException; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import com.alibaba.fastjson.JSON; import io.seata.common.Constants; import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.exception.SkipCallbackWrapperException; -import io.seata.common.util.StringUtils; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; import io.seata.core.model.Resource; +import io.seata.commonapi.fence.CommonFenceHandler; +import io.seata.commonapi.remoting.TwoPhaseResult; import io.seata.rm.AbstractResourceManager; -import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContextUtil; + +import java.lang.reflect.Method; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * TCC resource manager @@ -95,15 +95,16 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI } try { //BusinessActionContext - BusinessActionContext businessActionContext = getBusinessActionContext(xid, branchId, resourceId, - applicationData); + BusinessActionContext businessActionContext = BusinessActionContextUtil.getBusinessActionContext(xid, branchId, resourceId, + applicationData); + Object[] args = this.getTwoPhaseCommitArgs(tccResource, businessActionContext); Object ret; boolean result; // add idempotent and anti hanging - if (Boolean.TRUE.equals(businessActionContext.getActionContext(Constants.USE_TCC_FENCE))) { + if (Boolean.TRUE.equals(businessActionContext.getActionContext(Constants.USE_COMMON_FENCE))) { try { - result = TCCFenceHandler.commitFence(commitMethod, targetTCCBean, xid, branchId, args); + result = CommonFenceHandler.commitFence(commitMethod, targetTCCBean, xid, branchId, args); } catch (SkipCallbackWrapperException | UndeclaredThrowableException e) { throw e.getCause(); } @@ -153,15 +154,15 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc } try { //BusinessActionContext - BusinessActionContext businessActionContext = getBusinessActionContext(xid, branchId, resourceId, - applicationData); + BusinessActionContext businessActionContext = BusinessActionContextUtil.getBusinessActionContext(xid, branchId, resourceId, + applicationData); Object[] args = this.getTwoPhaseRollbackArgs(tccResource, businessActionContext); Object ret; boolean result; // add idempotent and anti hanging - if (Boolean.TRUE.equals(businessActionContext.getActionContext(Constants.USE_TCC_FENCE))) { + if (Boolean.TRUE.equals(businessActionContext.getActionContext(Constants.USE_COMMON_FENCE))) { try { - result = TCCFenceHandler.rollbackFence(rollbackMethod, targetTCCBean, xid, branchId, + result = CommonFenceHandler.rollbackFence(rollbackMethod, targetTCCBean, xid, branchId, args, tccResource.getActionName()); } catch (SkipCallbackWrapperException | UndeclaredThrowableException e) { throw e.getCause(); @@ -187,33 +188,6 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc } } - /** - * transfer tcc applicationData to BusinessActionContext - * - * @param xid the xid - * @param branchId the branch id - * @param resourceId the resource id - * @param applicationData the application data - * @return business action context - */ - protected BusinessActionContext getBusinessActionContext(String xid, long branchId, String resourceId, - String applicationData) { - Map actionContextMap = null; - if (StringUtils.isNotBlank(applicationData)) { - Map tccContext = JSON.parseObject(applicationData, Map.class); - actionContextMap = (Map)tccContext.get(Constants.TCC_ACTION_CONTEXT); - } - if (actionContextMap == null) { - actionContextMap = new HashMap<>(2); - } - - //instance the action context - BusinessActionContext businessActionContext = new BusinessActionContext( - xid, String.valueOf(branchId), actionContextMap); - businessActionContext.setActionName(resourceId); - return businessActionContext; - } - /** * get phase two commit method's args * @param tccResource tccResource @@ -223,7 +197,7 @@ protected BusinessActionContext getBusinessActionContext(String xid, long branch private Object[] getTwoPhaseCommitArgs(TCCResource tccResource, BusinessActionContext businessActionContext) { String[] keys = tccResource.getPhaseTwoCommitKeys(); Class[] argsCommitClasses = tccResource.getCommitArgsClasses(); - return this.getTwoPhaseMethodParams(keys, argsCommitClasses, businessActionContext); + return BusinessActionContextUtil.getTwoPhaseMethodParams(keys, argsCommitClasses, businessActionContext); } /** @@ -235,23 +209,11 @@ private Object[] getTwoPhaseCommitArgs(TCCResource tccResource, BusinessActionCo private Object[] getTwoPhaseRollbackArgs(TCCResource tccResource, BusinessActionContext businessActionContext) { String[] keys = tccResource.getPhaseTwoRollbackKeys(); Class[] argsRollbackClasses = tccResource.getRollbackArgsClasses(); - return this.getTwoPhaseMethodParams(keys, argsRollbackClasses, businessActionContext); - } - - private Object[] getTwoPhaseMethodParams(String[] keys, Class[] argsClasses, BusinessActionContext businessActionContext) { - Object[] args = new Object[argsClasses.length]; - for (int i = 0; i < argsClasses.length; i++) { - if (argsClasses[i].equals(BusinessActionContext.class)) { - args[i] = businessActionContext; - } else { - args[i] = businessActionContext.getActionContext(keys[i], argsClasses[i]); - } - } - return args; + return BusinessActionContextUtil.getTwoPhaseMethodParams(keys, argsRollbackClasses, businessActionContext); } @Override public BranchType getBranchType() { return BranchType.TCC; } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/LocalTCC.java b/tcc/src/main/java/io/seata/rm/tcc/api/LocalTCC.java index 4b3be4ea139..2a8ee88c40a 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/api/LocalTCC.java +++ b/tcc/src/main/java/io/seata/rm/tcc/api/LocalTCC.java @@ -15,6 +15,8 @@ */ package io.seata.rm.tcc.api; +import io.seata.rm.tcc.remoting.parser.LocalTCCRemotingParser; + import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; @@ -26,7 +28,7 @@ * * @author zhangsen * @see io.seata.spring.annotation.GlobalTransactionScanner#wrapIfNecessary(Object, String, Object) // the scanner for TM, GlobalLock, and TCC mode - * @see io.seata.rm.tcc.remoting.parser.LocalTCCRemotingParser // the RemotingParser impl for LocalTCC + * @see LocalTCCRemotingParser // the RemotingParser impl for LocalTCC */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/TwoPhaseBusinessAction.java b/tcc/src/main/java/io/seata/rm/tcc/api/TwoPhaseBusinessAction.java index 0bc714b7b6e..0f30d5aaf63 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/api/TwoPhaseBusinessAction.java +++ b/tcc/src/main/java/io/seata/rm/tcc/api/TwoPhaseBusinessAction.java @@ -15,6 +15,11 @@ */ package io.seata.rm.tcc.api; +import io.seata.commonapi.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContextParameter; +import io.seata.commonapi.rm.tcc.api.BusinessActionContextUtil; +import io.seata.rm.tcc.interceptor.TccActionInterceptor; + import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; @@ -29,7 +34,7 @@ * @author zhangsen * @see io.seata.rm.tcc.api.LocalTCC // TCC annotation, which added on the TCC interface. It can't be left out. * @see io.seata.spring.annotation.GlobalTransactionScanner#wrapIfNecessary(Object, String, Object) // the scanner for TM, GlobalLock, and TCC mode - * @see io.seata.spring.tcc.TccActionInterceptor // the interceptor of TCC mode + * @see TccActionInterceptor // the interceptor of TCC mode * @see BusinessActionContext * @see BusinessActionContextUtil * @see BusinessActionContextParameter diff --git a/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java b/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java new file mode 100644 index 00000000000..8f452f1c927 --- /dev/null +++ b/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java @@ -0,0 +1,123 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.rm.tcc.autoproxy; + +import io.seata.commonapi.autoproxy.IsTransactionProxyResult; +import io.seata.commonapi.autoproxy.TransactionAutoProxy; +import io.seata.common.exception.FrameworkException; +import io.seata.commonapi.remoting.Protocols; +import io.seata.commonapi.remoting.RemotingDesc; +import io.seata.commonapi.remoting.parser.DefaultRemotingParser; +import io.seata.rm.DefaultResourceManager; +import io.seata.rm.tcc.TCCResource; +import io.seata.rm.tcc.api.TwoPhaseBusinessAction; +import io.seata.rm.tcc.interceptor.TccActionInterceptor; +import io.seata.rm.tcc.interceptor.TccManualApiExecute; + +import java.lang.reflect.Method; + +/** + * the tcc implements of TransactionAutoProxy + * + * @author ruishansun + */ +public class TccTransactionAutoProxy implements TransactionAutoProxy { + + /** + * is TCC proxy-bean/target-bean: LocalTCC , the proxy bean of sofa:reference/dubbo:reference + * + * @param remotingDesc the remoting desc + * @return boolean + */ + @Override + public IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remotingDesc) { + if (remotingDesc == null) { + return new IsTransactionProxyResult(); + } + //check if it is TCC bean + boolean isTccClazz = false; + boolean userFence = false; + Class tccServiceClazz = remotingDesc.getServiceClass(); + Method[] methods = tccServiceClazz.getMethods(); + TwoPhaseBusinessAction twoPhaseBusinessAction; + for (Method method : methods) { + twoPhaseBusinessAction = method.getAnnotation(TwoPhaseBusinessAction.class); + if (twoPhaseBusinessAction != null) { + isTccClazz = true; + if (twoPhaseBusinessAction.useTCCFence()) { + userFence = true; + } + break; + } + } + if (!isTccClazz) { + return new IsTransactionProxyResult(); + } + + if (// LocalTCC in jvm TCC bean , AOP + Protocols.IN_JVM == remotingDesc.getProtocol() + // sofa:reference / dubbo:reference, AOP + || remotingDesc.isReference()) { + this.registryResource(remotingDesc); + IsTransactionProxyResult result = new IsTransactionProxyResult(); + result.setProxyTargetBean(true); + result.setUseCommonFence(userFence); + result.setMethodInterceptor(new TccActionInterceptor(remotingDesc)); + result.setManualApiExecute(new TccManualApiExecute()); + return result; + } + return new IsTransactionProxyResult(); + + } + + private void registryResource(RemotingDesc remotingDesc) { + if (remotingDesc.isService()) { + try { + Class tccServiceClazz = remotingDesc.getServiceClass(); + Method[] methods = tccServiceClazz.getMethods(); + //service bean, registry resource + Object targetBean = remotingDesc.getTargetBean(); + for (Method m : methods) { + TwoPhaseBusinessAction twoPhaseBusinessAction = m.getAnnotation(TwoPhaseBusinessAction.class); + if (twoPhaseBusinessAction != null) { + TCCResource tccResource = new TCCResource(); + tccResource.setActionName(twoPhaseBusinessAction.name()); + tccResource.setTargetBean(targetBean); + tccResource.setPrepareMethod(m); + tccResource.setCommitMethodName(twoPhaseBusinessAction.commitMethod()); + tccResource.setCommitMethod(tccServiceClazz.getMethod(twoPhaseBusinessAction.commitMethod(), + twoPhaseBusinessAction.commitArgsClasses())); + tccResource.setRollbackMethodName(twoPhaseBusinessAction.rollbackMethod()); + tccResource.setRollbackMethod(tccServiceClazz.getMethod(twoPhaseBusinessAction.rollbackMethod(), + twoPhaseBusinessAction.rollbackArgsClasses())); + // set argsClasses + tccResource.setCommitArgsClasses(twoPhaseBusinessAction.commitArgsClasses()); + tccResource.setRollbackArgsClasses(twoPhaseBusinessAction.rollbackArgsClasses()); + // set phase two method's keys + tccResource.setPhaseTwoCommitKeys(DefaultRemotingParser.get().getTwoPhaseArgs(tccResource.getCommitMethod(), + twoPhaseBusinessAction.commitArgsClasses())); + tccResource.setPhaseTwoRollbackKeys(DefaultRemotingParser.get().getTwoPhaseArgs(tccResource.getRollbackMethod(), + twoPhaseBusinessAction.rollbackArgsClasses())); + //registry tcc resource + DefaultResourceManager.get().registerResource(tccResource); + } + } + } catch (Throwable t) { + throw new FrameworkException(t, "parser remoting service error"); + } + } + } +} \ No newline at end of file diff --git a/spring/src/main/java/io/seata/spring/tcc/TccActionInterceptor.java b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptor.java similarity index 62% rename from spring/src/main/java/io/seata/spring/tcc/TccActionInterceptor.java rename to tcc/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptor.java index b09f282ec72..36b95a9560f 100644 --- a/spring/src/main/java/io/seata/spring/tcc/TccActionInterceptor.java +++ b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptor.java @@ -13,11 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.tcc; - -import java.lang.reflect.Method; -import javax.annotation.Nullable; +package io.seata.rm.tcc.interceptor; +import io.seata.common.Constants; import io.seata.common.DefaultValues; import io.seata.config.ConfigurationChangeEvent; import io.seata.config.ConfigurationChangeListener; @@ -25,11 +23,10 @@ import io.seata.core.constants.ConfigurationKeys; import io.seata.core.context.RootContext; import io.seata.core.model.BranchType; +import io.seata.commonapi.interceptor.ActionInterceptorHandler; +import io.seata.commonapi.interceptor.TwoPhaseBusinessActionParam; +import io.seata.commonapi.remoting.RemotingDesc; import io.seata.rm.tcc.api.TwoPhaseBusinessAction; -import io.seata.rm.tcc.interceptor.ActionInterceptorHandler; -import io.seata.rm.tcc.remoting.RemotingDesc; -import io.seata.rm.tcc.remoting.parser.DubboUtil; -import io.seata.spring.util.SpringProxyUtils; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.slf4j.Logger; @@ -37,6 +34,10 @@ import org.slf4j.MDC; import org.springframework.core.Ordered; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + import static io.seata.common.DefaultValues.DEFAULT_DISABLE_GLOBAL_TRANSACTION; import static io.seata.core.constants.ConfigurationKeys.TCC_ACTION_INTERCEPTOR_ORDER; @@ -55,7 +56,7 @@ public class TccActionInterceptor implements MethodInterceptor, ConfigurationCha private ActionInterceptorHandler actionInterceptorHandler = new ActionInterceptorHandler(); private volatile boolean disable = ConfigurationFactory.getInstance().getBoolean( - ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, DEFAULT_DISABLE_GLOBAL_TRANSACTION); + ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, DEFAULT_DISABLE_GLOBAL_TRANSACTION); /** * remoting bean info @@ -83,7 +84,7 @@ public Object invoke(final MethodInvocation invocation) throws Throwable { //not in transaction, or this interceptor is disabled return invocation.proceed(); } - Method method = getActionInterfaceMethod(invocation); + Method method = actionInterceptorHandler.getActionInterfaceMethod(invocation, this.remotingDesc); TwoPhaseBusinessAction businessAction = method.getAnnotation(TwoPhaseBusinessAction.class); //try method if (businessAction != null) { @@ -96,8 +97,20 @@ public Object invoke(final MethodInvocation invocation) throws Throwable { RootContext.bindBranchType(BranchType.TCC); } try { + TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam(); + businessActionParam.setActionName(businessAction.name()); + businessActionParam.setDelayReport(businessAction.isDelayReport()); + businessActionParam.setUseCommonFence(businessAction.useTCCFence()); + businessActionParam.setBranchType(BranchType.TCC); + Map businessActionContextMap = new HashMap<>(4); + //the phase two method name + businessActionContextMap.put(Constants.COMMIT_METHOD, businessAction.commitMethod()); + businessActionContextMap.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod()); + businessActionContextMap.put(Constants.ACTION_NAME, businessAction.name()); + businessActionContextMap.put(Constants.USE_COMMON_FENCE, businessAction.useTCCFence()); + businessActionParam.setBusinessActionContext(businessActionContextMap); //Handler the TCC Aspect, and return the business result - return actionInterceptorHandler.proceed(method, invocation.getArguments(), xid, businessAction, + return actionInterceptorHandler.proceed(method, invocation.getArguments(), xid, businessActionParam, invocation::proceed); } finally { //if not TCC, unbind branchType @@ -113,63 +126,11 @@ public Object invoke(final MethodInvocation invocation) throws Throwable { return invocation.proceed(); } - /** - * get the method from interface - * - * @param invocation the invocation - * @return the action interface method - */ - protected Method getActionInterfaceMethod(MethodInvocation invocation) { - Class serviceType = null; - try { - if (remotingDesc == null) { - serviceType = getProxyInterface(invocation.getThis()); - } else { - serviceType = remotingDesc.getServiceClass(); - } - if (serviceType == null && remotingDesc != null && remotingDesc.getServiceClassName() != null) { - serviceType = Class.forName(remotingDesc.getServiceClassName(), true, - Thread.currentThread().getContextClassLoader()); - } - if (serviceType == null) { - return invocation.getMethod(); - } - return serviceType.getMethod(invocation.getMethod().getName(), - invocation.getMethod().getParameterTypes()); - } catch (NoSuchMethodException e) { - if (serviceType != null && !"toString".equals(invocation.getMethod().getName())) { - LOGGER.warn("no such method '{}' from interface {}", invocation.getMethod().getName(), serviceType.getName()); - } - return invocation.getMethod(); - } catch (Exception e) { - LOGGER.warn("get Method from interface failed", e); - return invocation.getMethod(); - } - } - - /** - * get the interface of proxy - * - * @param proxyBean the proxy bean - * @return proxy interface - * @throws Exception the exception - */ - @Nullable - protected Class getProxyInterface(Object proxyBean) throws Exception { - if (DubboUtil.isDubboProxyName(proxyBean.getClass().getName())) { - //dubbo javaassist proxy - return DubboUtil.getAssistInterface(proxyBean); - } else { - //jdk/cglib proxy - return SpringProxyUtils.getTargetInterface(proxyBean); - } - } - @Override public void onChangeEvent(ConfigurationChangeEvent event) { if (ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION.equals(event.getDataId())) { LOGGER.info("{} config changed, old value:{}, new value:{}", ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, - disable, event.getNewValue()); + disable, event.getNewValue()); disable = Boolean.parseBoolean(event.getNewValue().trim()); } } @@ -178,4 +139,4 @@ public void onChangeEvent(ConfigurationChangeEvent event) { public int getOrder() { return ORDER_NUM; } -} +} \ No newline at end of file diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccManualApiExecute.java b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccManualApiExecute.java new file mode 100644 index 00000000000..1b447317474 --- /dev/null +++ b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccManualApiExecute.java @@ -0,0 +1,67 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.rm.tcc.interceptor; + +import io.seata.commonapi.autoproxy.ManualApiExecute; +import io.seata.common.Constants; +import io.seata.core.context.RootContext; +import io.seata.core.model.BranchType; +import io.seata.commonapi.interceptor.ActionInterceptorHandler; +import io.seata.commonapi.interceptor.TwoPhaseBusinessActionParam; +import io.seata.rm.tcc.api.TwoPhaseBusinessAction; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +public class TccManualApiExecute implements ManualApiExecute { + + private ActionInterceptorHandler actionInterceptorHandler; + + @Override + public void manualApiBefore(Method method, Object[] arguments) throws Throwable { + + TwoPhaseBusinessAction businessAction = method.getAnnotation(TwoPhaseBusinessAction.class); + if (businessAction != null) { + //save the xid + String xid = RootContext.getXID(); + //save the previous branchType + BranchType previousBranchType = RootContext.getBranchType(); + //if not TCC, bind TCC branchType + if (BranchType.TCC != previousBranchType) { + RootContext.bindBranchType(BranchType.TCC); + } + + TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam(); + businessActionParam.setActionName(businessAction.name()); + businessActionParam.setDelayReport(businessAction.isDelayReport()); + businessActionParam.setUseCommonFence(businessAction.useTCCFence()); + businessActionParam.setBranchType(BranchType.TCC); + Map businessActionContextMap = new HashMap<>(4); + //the phase two method name + businessActionContextMap.put(Constants.COMMIT_METHOD, businessAction.commitMethod()); + businessActionContextMap.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod()); + businessActionContextMap.put(Constants.ACTION_NAME, businessAction.name()); + businessActionContextMap.put(Constants.USE_COMMON_FENCE, businessAction.useTCCFence()); + businessActionParam.setBusinessActionContext(businessActionContextMap); + //Handler the TCC Aspect, and return the business result + if (actionInterceptorHandler == null) { + actionInterceptorHandler = new ActionInterceptorHandler(); + } + actionInterceptorHandler.proceedManual(method, arguments, xid, businessActionParam); + } + } +} diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java b/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java index 7a966df29b5..f950201e2fa 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java +++ b/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java @@ -15,15 +15,16 @@ */ package io.seata.rm.tcc.remoting.parser; -import java.util.Set; - import io.seata.common.exception.FrameworkException; import io.seata.common.util.ReflectionUtil; +import io.seata.commonapi.remoting.Protocols; +import io.seata.commonapi.remoting.RemotingDesc; +import io.seata.commonapi.remoting.parser.AbstractedRemotingParser; import io.seata.rm.tcc.api.LocalTCC; -import io.seata.rm.tcc.remoting.Protocols; -import io.seata.rm.tcc.remoting.RemotingDesc; import org.springframework.aop.framework.AopProxyUtils; +import java.util.Set; + /** * local tcc bean parsing * @@ -47,7 +48,8 @@ public RemotingDesc getServiceDesc(Object bean, String beanName) throws Framewor return null; } RemotingDesc remotingDesc = new RemotingDesc(); - remotingDesc.setReference(true); + remotingDesc.setReference(this.isReference(bean, beanName)); + remotingDesc.setService(this.isService(bean, beanName)); remotingDesc.setProtocol(Protocols.IN_JVM); Class classType = bean.getClass(); // check if LocalTCC annotation is marked on the implementation class @@ -90,4 +92,4 @@ private boolean isLocalTCC(Object bean) { } return classType.isAnnotationPresent(LocalTCC.class); } -} +} \ No newline at end of file diff --git a/tcc/src/main/resources/META-INF/services/io.seata.rm.tcc.remoting.RemotingParser b/tcc/src/main/resources/META-INF/services/io.seata.rm.tcc.remoting.RemotingParser deleted file mode 100644 index 30ef923192e..00000000000 --- a/tcc/src/main/resources/META-INF/services/io.seata.rm.tcc.remoting.RemotingParser +++ /dev/null @@ -1,4 +0,0 @@ -io.seata.rm.tcc.remoting.parser.DubboRemotingParser -io.seata.rm.tcc.remoting.parser.LocalTCCRemotingParser -io.seata.rm.tcc.remoting.parser.SofaRpcRemotingParser -io.seata.rm.tcc.remoting.parser.HSFRemotingParser \ No newline at end of file diff --git a/tcc/src/test/java/io/seata/rm/tcc/TccAction.java b/tcc/src/test/java/io/seata/rm/tcc/TccAction.java index 94f22365fa2..1f6dfe5c3c6 100644 --- a/tcc/src/test/java/io/seata/rm/tcc/TccAction.java +++ b/tcc/src/test/java/io/seata/rm/tcc/TccAction.java @@ -15,8 +15,8 @@ */ package io.seata.rm.tcc; -import io.seata.rm.tcc.api.BusinessActionContext; -import io.seata.rm.tcc.api.BusinessActionContextParameter; +import io.seata.commonapi.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContextParameter; import io.seata.rm.tcc.api.LocalTCC; import io.seata.rm.tcc.api.TwoPhaseBusinessAction; diff --git a/tcc/src/test/java/io/seata/rm/tcc/TccActionImpl.java b/tcc/src/test/java/io/seata/rm/tcc/TccActionImpl.java index 81646bda9fb..e6ab96218f5 100644 --- a/tcc/src/test/java/io/seata/rm/tcc/TccActionImpl.java +++ b/tcc/src/test/java/io/seata/rm/tcc/TccActionImpl.java @@ -15,8 +15,8 @@ */ package io.seata.rm.tcc; -import io.seata.rm.tcc.api.BusinessActionContext; -import io.seata.rm.tcc.api.BusinessActionContextParameter; +import io.seata.commonapi.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContextParameter; import java.util.List; diff --git a/tcc/src/test/java/io/seata/rm/tcc/TccParam.java b/tcc/src/test/java/io/seata/rm/tcc/TccParam.java index c5013a4958a..98168a4fc44 100644 --- a/tcc/src/test/java/io/seata/rm/tcc/TccParam.java +++ b/tcc/src/test/java/io/seata/rm/tcc/TccParam.java @@ -15,7 +15,7 @@ */ package io.seata.rm.tcc; -import io.seata.rm.tcc.api.BusinessActionContextParameter; +import io.seata.commonapi.rm.tcc.api.BusinessActionContextParameter; /** * The type Tcc param. diff --git a/tcc/src/test/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandlerTest.java b/tcc/src/test/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandlerTest.java index 1fb8f1b5fb8..5da62c20f67 100644 --- a/tcc/src/test/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandlerTest.java +++ b/tcc/src/test/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandlerTest.java @@ -15,9 +15,10 @@ */ package io.seata.rm.tcc.interceptor; +import io.seata.commonapi.interceptor.ActionInterceptorHandler; import io.seata.rm.tcc.TccAction; import io.seata.rm.tcc.TccParam; -import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContext; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -36,7 +37,7 @@ public class ActionInterceptorHandlerTest { /** * The Action interceptor handler. */ - protected ActionInterceptorHandler actionInterceptorHandler = new ActionInterceptorHandler(); + protected ActionInterceptorHandler actionInterceptorHandler = new ActionInterceptorHandler(); /** * Test business action context. diff --git a/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/DefaultRemotingParserTest.java b/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/DefaultRemotingParserTest.java index 33e493af265..04b62fd0e7a 100644 --- a/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/DefaultRemotingParserTest.java +++ b/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/DefaultRemotingParserTest.java @@ -15,8 +15,9 @@ */ package io.seata.rm.tcc.remoting.parser; +import io.seata.commonapi.remoting.parser.DefaultRemotingParser; import io.seata.rm.tcc.TccParam; -import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContext; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -24,7 +25,7 @@ public class DefaultRemotingParserTest { - DefaultRemotingParser defaultRemotingParser = new DefaultRemotingParser(); + DefaultRemotingParser defaultRemotingParser = DefaultRemotingParser.get(); @Test public void testGetTwoPhaseArgs() throws Exception { @@ -41,4 +42,4 @@ public void testGetTwoPhaseArgs() throws Exception { Assertions.assertEquals("tccParam", keys[1]); } -} +} \ No newline at end of file diff --git a/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParserTest.java b/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParserTest.java index 6618c3395c0..0d26f65c04c 100644 --- a/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParserTest.java +++ b/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParserTest.java @@ -15,9 +15,9 @@ */ package io.seata.rm.tcc.remoting.parser; +import io.seata.commonapi.remoting.RemotingDesc; import io.seata.rm.tcc.TccAction; import io.seata.rm.tcc.TccActionImpl; -import io.seata.rm.tcc.remoting.RemotingDesc; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/spring/src/test/java/io/seata/spring/annotation/Business.java b/tcc/src/test/java/io/seata/rm/tcc/spring/Business.java similarity index 95% rename from spring/src/test/java/io/seata/spring/annotation/Business.java rename to tcc/src/test/java/io/seata/rm/tcc/spring/Business.java index aaa351d03a3..2ad498f4d9e 100644 --- a/spring/src/test/java/io/seata/spring/annotation/Business.java +++ b/tcc/src/test/java/io/seata/rm/tcc/spring/Business.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.annotation; +package io.seata.rm.tcc.spring; /** * The interface Business. diff --git a/spring/src/test/java/io/seata/spring/annotation/BusinessImpl.java b/tcc/src/test/java/io/seata/rm/tcc/spring/BusinessImpl.java similarity index 92% rename from spring/src/test/java/io/seata/spring/annotation/BusinessImpl.java rename to tcc/src/test/java/io/seata/rm/tcc/spring/BusinessImpl.java index 2ac53976727..15c8e5b27c1 100644 --- a/spring/src/test/java/io/seata/spring/annotation/BusinessImpl.java +++ b/tcc/src/test/java/io/seata/rm/tcc/spring/BusinessImpl.java @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.annotation; +package io.seata.rm.tcc.spring; +import io.seata.spring.annotation.GlobalTransactional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/spring/src/test/java/io/seata/spring/annotation/BusinessProxy.java b/tcc/src/test/java/io/seata/rm/tcc/spring/BusinessProxy.java similarity index 97% rename from spring/src/test/java/io/seata/spring/annotation/BusinessProxy.java rename to tcc/src/test/java/io/seata/rm/tcc/spring/BusinessProxy.java index 14e0043e06a..6eb4cc798e8 100644 --- a/spring/src/test/java/io/seata/spring/annotation/BusinessProxy.java +++ b/tcc/src/test/java/io/seata/rm/tcc/spring/BusinessProxy.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.annotation; +package io.seata.rm.tcc.spring; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; diff --git a/tcc/src/test/java/io/seata/rm/tcc/spring/GlobalTransactionScannerSub.java b/tcc/src/test/java/io/seata/rm/tcc/spring/GlobalTransactionScannerSub.java new file mode 100644 index 00000000000..c3667a6d823 --- /dev/null +++ b/tcc/src/test/java/io/seata/rm/tcc/spring/GlobalTransactionScannerSub.java @@ -0,0 +1,33 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.rm.tcc.spring; + +import io.seata.spring.annotation.GlobalTransactionScanner; + +/** + * the subclass of GlobalTransactionScanner for test public method wrapIfNecessary + */ +public class GlobalTransactionScannerSub extends GlobalTransactionScanner { + + + public GlobalTransactionScannerSub(String txServiceGroup) { + super(txServiceGroup); + } + + public Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { + return super.wrapIfNecessary(bean, beanName, cacheKey); + } +} diff --git a/spring/src/test/java/io/seata/spring/annotation/GlobalTransactionScannerTest.java b/tcc/src/test/java/io/seata/rm/tcc/spring/GlobalTransactionScannerTest.java similarity index 91% rename from spring/src/test/java/io/seata/spring/annotation/GlobalTransactionScannerTest.java rename to tcc/src/test/java/io/seata/rm/tcc/spring/GlobalTransactionScannerTest.java index 1ab5b9927be..523247ab6c5 100644 --- a/spring/src/test/java/io/seata/spring/annotation/GlobalTransactionScannerTest.java +++ b/tcc/src/test/java/io/seata/rm/tcc/spring/GlobalTransactionScannerTest.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.annotation; +package io.seata.rm.tcc.spring; -import io.seata.spring.tcc.LocalTccAction; -import io.seata.spring.tcc.LocalTccActionImpl; -import io.seata.spring.tcc.TccAction; -import io.seata.spring.tcc.TccActionImpl; +import io.seata.rm.tcc.spring.tcc.LocalTccAction; +import io.seata.rm.tcc.spring.tcc.LocalTccActionImpl; +import io.seata.rm.tcc.spring.tcc.TccAction; +import io.seata.rm.tcc.spring.tcc.TccActionImpl; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -34,7 +34,7 @@ public class GlobalTransactionScannerTest { /** * The Global transaction scanner. */ - protected GlobalTransactionScanner globalTransactionScanner = new GlobalTransactionScanner("global-trans-scanner-test"); + protected GlobalTransactionScannerSub globalTransactionScanner = new GlobalTransactionScannerSub("global-trans-scanner-test"); /** * Test wrap normal bean. diff --git a/spring/src/test/java/io/seata/spring/tcc/LocalTccAction.java b/tcc/src/test/java/io/seata/rm/tcc/spring/tcc/LocalTccAction.java similarity index 95% rename from spring/src/test/java/io/seata/spring/tcc/LocalTccAction.java rename to tcc/src/test/java/io/seata/rm/tcc/spring/tcc/LocalTccAction.java index 4fdeb378a18..a3a2fb33473 100644 --- a/spring/src/test/java/io/seata/spring/tcc/LocalTccAction.java +++ b/tcc/src/test/java/io/seata/rm/tcc/spring/tcc/LocalTccAction.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.tcc; +package io.seata.rm.tcc.spring.tcc; import io.seata.rm.tcc.api.LocalTCC; diff --git a/spring/src/test/java/io/seata/spring/tcc/LocalTccActionImpl.java b/tcc/src/test/java/io/seata/rm/tcc/spring/tcc/LocalTccActionImpl.java similarity index 95% rename from spring/src/test/java/io/seata/spring/tcc/LocalTccActionImpl.java rename to tcc/src/test/java/io/seata/rm/tcc/spring/tcc/LocalTccActionImpl.java index e693c1e92cc..2b9c4091b70 100644 --- a/spring/src/test/java/io/seata/spring/tcc/LocalTccActionImpl.java +++ b/tcc/src/test/java/io/seata/rm/tcc/spring/tcc/LocalTccActionImpl.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.tcc; +package io.seata.rm.tcc.spring.tcc; /** * The type Local tcc action. diff --git a/spring/src/test/java/io/seata/spring/tcc/TccAction.java b/tcc/src/test/java/io/seata/rm/tcc/spring/tcc/TccAction.java similarity index 93% rename from spring/src/test/java/io/seata/spring/tcc/TccAction.java rename to tcc/src/test/java/io/seata/rm/tcc/spring/tcc/TccAction.java index db39fb708f5..2c01cf82dac 100644 --- a/spring/src/test/java/io/seata/spring/tcc/TccAction.java +++ b/tcc/src/test/java/io/seata/rm/tcc/spring/tcc/TccAction.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.tcc; +package io.seata.rm.tcc.spring.tcc; -import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContext; import io.seata.rm.tcc.api.TwoPhaseBusinessAction; /** diff --git a/spring/src/test/java/io/seata/spring/tcc/TccActionImpl.java b/tcc/src/test/java/io/seata/rm/tcc/spring/tcc/TccActionImpl.java similarity index 91% rename from spring/src/test/java/io/seata/spring/tcc/TccActionImpl.java rename to tcc/src/test/java/io/seata/rm/tcc/spring/tcc/TccActionImpl.java index c28a844c4ae..2cd528ccaeb 100644 --- a/spring/src/test/java/io/seata/spring/tcc/TccActionImpl.java +++ b/tcc/src/test/java/io/seata/rm/tcc/spring/tcc/TccActionImpl.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.spring.tcc; +package io.seata.rm.tcc.spring.tcc; -import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.commonapi.rm.tcc.api.BusinessActionContext; /** * The type Tcc action.