From aa9f275a0c377e2e6694cd9afbe8377d9c831ee4 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Sat, 30 Apr 2022 17:40:12 +0800 Subject: [PATCH 01/24] feature : SAGA annotation mode --- .../main/java/io/seata/common/Constants.java | 5 +++++ .../io/seata/rm/tcc/TCCResourceManager.java | 9 +++++++++ .../java/io/seata/rm/tcc/api/ModeType.java | 18 ++++++++++++++++++ .../rm/tcc/api/TwoPhaseBusinessAction.java | 7 +++++++ .../interceptor/ActionInterceptorHandler.java | 1 + 5 files changed, 40 insertions(+) create mode 100644 tcc/src/main/java/io/seata/rm/tcc/api/ModeType.java diff --git a/common/src/main/java/io/seata/common/Constants.java b/common/src/main/java/io/seata/common/Constants.java index aa4a0241740..4a9a64d3751 100644 --- a/common/src/main/java/io/seata/common/Constants.java +++ b/common/src/main/java/io/seata/common/Constants.java @@ -160,5 +160,10 @@ public interface Constants { * The constant SKIP_CHECK_LOCK */ String SKIP_CHECK_LOCK = "skipCheckLock"; + + /** + * The constant MODE_TYPE + */ + String MODE_TYPE = "modeType"; } 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..862651f3aac 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java +++ b/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java @@ -32,6 +32,7 @@ import io.seata.core.model.Resource; import io.seata.rm.AbstractResourceManager; import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.rm.tcc.api.ModeType; /** * TCC resource manager @@ -97,6 +98,14 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI //BusinessActionContext BusinessActionContext businessActionContext = getBusinessActionContext(xid, branchId, resourceId, applicationData); + + // if the TwoPhaseBusinessAction annotation's mode is SAGA, cancel the commit + ModeType modeType = (ModeType) businessActionContext.getActionContext(Constants.MODE_TYPE); + if(modeType != null && modeType.equals( ModeType.SAGA)) { + LOGGER.info("TwoPhaseBusinessAction's ModeType is SAGA, cancel the commit, xid: {}, branchId: {}, resourceId: {}", xid, branchId, resourceId); + return BranchStatus.PhaseTwo_Committed; + } + Object[] args = this.getTwoPhaseCommitArgs(tccResource, businessActionContext); Object ret; boolean result; diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/ModeType.java b/tcc/src/main/java/io/seata/rm/tcc/api/ModeType.java new file mode 100644 index 00000000000..557606c935c --- /dev/null +++ b/tcc/src/main/java/io/seata/rm/tcc/api/ModeType.java @@ -0,0 +1,18 @@ +package io.seata.rm.tcc.api; + +/** + * The enum ModeType + * + * @author ruishan + */ +public enum ModeType { + + /** + * TCC Mode + */ + TCC, + /** + * SAGA Mode + */ + SAGA; +} 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..af3b43b54fd 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 @@ -87,4 +87,11 @@ * @return the Class[] */ Class[] rollbackArgsClasses() default {BusinessActionContext.class}; + + /** + * Define TCC or SAGA mode + * + * @return the mode + */ + ModeType modeType() default ModeType.TCC; } diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java b/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java index ea80e3e4d62..d02fc6c55fe 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java +++ b/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java @@ -237,6 +237,7 @@ protected void initBusinessContext(Map context, Method method, context.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod()); context.put(Constants.ACTION_NAME, businessAction.name()); context.put(Constants.USE_TCC_FENCE, businessAction.useTCCFence()); + context.put(Constants.MODE_TYPE, businessAction.modeType()); } } From ff77aea77acb214a5c8aa0559064bebc180750fd Mon Sep 17 00:00:00 2001 From: ruishansun Date: Thu, 5 May 2022 10:40:39 +0800 Subject: [PATCH 02/24] format codes --- tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 862651f3aac..2aa14a234b3 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java +++ b/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java @@ -101,7 +101,7 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI // if the TwoPhaseBusinessAction annotation's mode is SAGA, cancel the commit ModeType modeType = (ModeType) businessActionContext.getActionContext(Constants.MODE_TYPE); - if(modeType != null && modeType.equals( ModeType.SAGA)) { + if (modeType != null && modeType.equals(ModeType.SAGA)) { LOGGER.info("TwoPhaseBusinessAction's ModeType is SAGA, cancel the commit, xid: {}, branchId: {}, resourceId: {}", xid, branchId, resourceId); return BranchStatus.PhaseTwo_Committed; } From f6f1b9e3365eef73c33e8ac58f902c303a76aa7f Mon Sep 17 00:00:00 2001 From: ruishansun Date: Thu, 26 May 2022 20:18:59 +0800 Subject: [PATCH 03/24] solve spring and tcc dependency issue --- spring/pom.xml | 5 -- .../annotation/GlobalTransactionScanner.java | 16 ++--- .../annotation/GlobalTransactional.java | 2 +- .../DefaultTransactionAutoProxy.java | 70 +++++++++++++++++++ .../autoproxy/TransactionAutoProxy.java | 23 ++++++ .../java/io/seata/spring/util}/DubboUtil.java | 2 +- .../seata/spring/util/SpringProxyUtils.java | 1 - ...eata.spring.autoproxy.TransactionAutoProxy | 1 + tcc/pom.xml | 5 ++ .../rm/tcc/api/TwoPhaseBusinessAction.java | 4 +- .../autoproxy/TccTransactionAutoProxy.java | 26 +++++++ .../tcc/interceptor}/TCCBeanParserUtils.java | 4 +- .../interceptor}/TccActionInterceptor.java | 5 +- .../interceptor}/TccAnnotationProcessor.java | 3 +- .../io/seata/rm/tcc/spring}/Business.java | 2 +- .../io/seata/rm/tcc/spring}/BusinessImpl.java | 3 +- .../seata/rm/tcc/spring}/BusinessProxy.java | 2 +- .../spring/GlobalTransactionScannerSub.java | 18 +++++ .../spring}/GlobalTransactionScannerTest.java | 12 ++-- .../rm/tcc}/spring/tcc/LocalTccAction.java | 2 +- .../tcc}/spring/tcc/LocalTccActionImpl.java | 2 +- .../seata/rm/tcc}/spring/tcc/TccAction.java | 2 +- .../rm/tcc}/spring/tcc/TccActionImpl.java | 2 +- 23 files changed, 173 insertions(+), 39 deletions(-) create mode 100644 spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java create mode 100644 spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java rename {tcc/src/main/java/io/seata/rm/tcc/remoting/parser => spring/src/main/java/io/seata/spring/util}/DubboUtil.java (98%) create mode 100644 spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy create mode 100644 tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java rename {spring/src/main/java/io/seata/spring/util => tcc/src/main/java/io/seata/rm/tcc/interceptor}/TCCBeanParserUtils.java (98%) rename {spring/src/main/java/io/seata/spring/tcc => tcc/src/main/java/io/seata/rm/tcc/interceptor}/TccActionInterceptor.java (97%) rename {spring/src/main/java/io/seata/spring/tcc => tcc/src/main/java/io/seata/rm/tcc/interceptor}/TccAnnotationProcessor.java (98%) rename {spring/src/test/java/io/seata/spring/annotation => tcc/src/test/java/io/seata/rm/tcc/spring}/Business.java (95%) rename {spring/src/test/java/io/seata/spring/annotation => tcc/src/test/java/io/seata/rm/tcc/spring}/BusinessImpl.java (92%) rename {spring/src/test/java/io/seata/spring/annotation => tcc/src/test/java/io/seata/rm/tcc/spring}/BusinessProxy.java (97%) create mode 100644 tcc/src/test/java/io/seata/rm/tcc/spring/GlobalTransactionScannerSub.java rename {spring/src/test/java/io/seata/spring/annotation => tcc/src/test/java/io/seata/rm/tcc/spring}/GlobalTransactionScannerTest.java (91%) rename {spring/src/test/java/io/seata => tcc/src/test/java/io/seata/rm/tcc}/spring/tcc/LocalTccAction.java (95%) rename {spring/src/test/java/io/seata => tcc/src/test/java/io/seata/rm/tcc}/spring/tcc/LocalTccActionImpl.java (95%) rename {spring/src/test/java/io/seata => tcc/src/test/java/io/seata/rm/tcc}/spring/tcc/TccAction.java (97%) rename {spring/src/test/java/io/seata => tcc/src/test/java/io/seata/rm/tcc}/spring/tcc/TccActionImpl.java (96%) diff --git a/spring/pom.xml b/spring/pom.xml index 532808e9a49..a07407e0a03 100644 --- a/spring/pom.xml +++ b/spring/pom.xml @@ -38,11 +38,6 @@ seata-rm-datasource ${project.version} - - ${project.groupId} - seata-tcc - ${project.version} - ${project.groupId} seata-rm 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..bc309fc6fb3 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java @@ -37,10 +37,9 @@ import io.seata.core.rpc.netty.TmNettyRemotingClient; import io.seata.rm.RMClient; import io.seata.spring.annotation.scannercheckers.PackageScannerChecker; -import io.seata.spring.tcc.TccActionInterceptor; +import io.seata.spring.autoproxy.DefaultTransactionAutoProxy; import io.seata.spring.util.OrderUtil; import io.seata.spring.util.SpringProxyUtils; -import io.seata.spring.util.TCCBeanParserUtils; import io.seata.tm.TMClient; import io.seata.tm.api.FailureHandler; import org.aopalliance.aop.Advice; @@ -261,7 +260,7 @@ private void registerSpringShutdownHook() { * @see io.seata.rm.tcc.api.TwoPhaseBusinessAction // TCC annotation on try method * @see io.seata.rm.tcc.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,14 +275,11 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) return bean; } interceptor = null; - //check TCC proxy - if (TCCBeanParserUtils.isTccAutoProxy(bean, beanName, applicationContext)) { - // 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)); + //check Transaction proxy + interceptor = DefaultTransactionAutoProxy.get().isTransactionAutoProxy(bean, beanName, applicationContext); + if (interceptor != null) { ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, - (ConfigurationChangeListener)interceptor); + (ConfigurationChangeListener) interceptor); } else { Class serviceInterface = SpringProxyUtils.findTargetClass(bean); Class[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean); 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/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java b/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java new file mode 100644 index 00000000000..d61e78968a2 --- /dev/null +++ b/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java @@ -0,0 +1,70 @@ +package io.seata.spring.autoproxy; + +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.util.CollectionUtils; +import org.aopalliance.intercept.MethodInterceptor; +import org.springframework.context.ApplicationContext; + +import java.util.ArrayList; +import java.util.List; + +/** + * the default transaction auto proxy + * + * @author ruishansun + */ +public class DefaultTransactionAutoProxy { + + /** + * all the transaction auto proxy + */ + protected static List allTransactionAutoProxies = new ArrayList<>(); + + 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)) { + allTransactionAutoProxies.addAll(proxies); + } + } + + /** + * is transaction auto proxy ? + * + * @param bean the bean + * @param beanName the beanName + * @param applicationContext the applicationContext + * @return the MethodInterceptor or null + */ + public MethodInterceptor isTransactionAutoProxy(Object bean, String beanName, ApplicationContext applicationContext) { + for (TransactionAutoProxy proxy : allTransactionAutoProxies) { + MethodInterceptor methodInterceptor = proxy.isTransactionAutoProxy(bean, beanName, applicationContext); + if (methodInterceptor != null) { + return methodInterceptor; + } + } + return null; + } +} diff --git a/spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java b/spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java new file mode 100644 index 00000000000..dd3e4a70610 --- /dev/null +++ b/spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java @@ -0,0 +1,23 @@ +package io.seata.spring.autoproxy; + +import org.aopalliance.intercept.MethodInterceptor; +import org.springframework.context.ApplicationContext; + +/** + * The interface Transaction Auto Proxy. + * if result is not null, then proxied by tcc/saga with SPI. + * + * @author ruishansun + */ +public interface TransactionAutoProxy { + + /** + * if it is transaction auto proxy? (tcc or saga) + * + * @param bean the bean + * @param beanName the beanName + * @param applicationContext the applicationContext + * @return the MethodInterceptor + */ + MethodInterceptor isTransactionAutoProxy(Object bean, String beanName, ApplicationContext applicationContext); +} diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboUtil.java b/spring/src/main/java/io/seata/spring/util/DubboUtil.java similarity index 98% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboUtil.java rename to spring/src/main/java/io/seata/spring/util/DubboUtil.java index c33651ca09b..e2482b8406e 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboUtil.java +++ b/spring/src/main/java/io/seata/spring/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.spring.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/spring/src/main/java/io/seata/spring/util/SpringProxyUtils.java index 567903b75ac..cbc94662a26 100644 --- a/spring/src/main/java/io/seata/spring/util/SpringProxyUtils.java +++ b/spring/src/main/java/io/seata/spring/util/SpringProxyUtils.java @@ -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/spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy b/spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy new file mode 100644 index 00000000000..a27056a0435 --- /dev/null +++ b/spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy @@ -0,0 +1 @@ +io.seata.rm.tcc.autoproxy.TccTransactionAutoProxy \ No newline at end of file diff --git a/tcc/pom.xml b/tcc/pom.xml index f92d5220929..8086afaa5e0 100644 --- a/tcc/pom.xml +++ b/tcc/pom.xml @@ -39,6 +39,11 @@ seata-rm ${project.version} + + ${project.groupId} + seata-spring + ${project.version} + org.springframework spring-jdbc 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..28319d1baff 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,8 @@ */ package io.seata.rm.tcc.api; +import io.seata.rm.tcc.interceptor.TccActionInterceptor; + import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; @@ -29,7 +31,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..917bb41317a --- /dev/null +++ b/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java @@ -0,0 +1,26 @@ +package io.seata.rm.tcc.autoproxy; + +import io.seata.rm.tcc.interceptor.TCCBeanParserUtils; +import io.seata.rm.tcc.interceptor.TccActionInterceptor; +import io.seata.spring.autoproxy.TransactionAutoProxy; +import org.aopalliance.intercept.MethodInterceptor; +import org.springframework.context.ApplicationContext; + +/** + * the tcc implements of TransactionAutoProxy + * + * @author ruishansun + */ +public class TccTransactionAutoProxy implements TransactionAutoProxy { + + @Override + public MethodInterceptor isTransactionAutoProxy(Object bean, String beanName, ApplicationContext applicationContext) { + if (TCCBeanParserUtils.isTccAutoProxy(bean, beanName, applicationContext)) { + // 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 + return new TccActionInterceptor(TCCBeanParserUtils.getRemotingDesc(beanName)); + } + return null; + } +} diff --git a/spring/src/main/java/io/seata/spring/util/TCCBeanParserUtils.java b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TCCBeanParserUtils.java similarity index 98% rename from spring/src/main/java/io/seata/spring/util/TCCBeanParserUtils.java rename to tcc/src/main/java/io/seata/rm/tcc/interceptor/TCCBeanParserUtils.java index 5c7c606ffab..c90242fa3c1 100644 --- a/spring/src/main/java/io/seata/spring/util/TCCBeanParserUtils.java +++ b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TCCBeanParserUtils.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.rm.tcc.interceptor; import io.seata.common.DefaultValues; import io.seata.rm.tcc.api.TwoPhaseBusinessAction; @@ -22,7 +22,7 @@ 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.spring.util.SpringProxyUtils; import org.springframework.aop.framework.ProxyFactory; import org.springframework.context.ApplicationContext; 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 97% 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 91fd540c7db..e2183945dcd 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,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.interceptor; import java.lang.reflect.Method; import javax.annotation.Nullable; @@ -26,9 +26,8 @@ import io.seata.core.context.RootContext; import io.seata.core.model.BranchType; 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.DubboUtil; import io.seata.spring.util.SpringProxyUtils; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; diff --git a/spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccAnnotationProcessor.java similarity index 98% rename from spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java rename to tcc/src/main/java/io/seata/rm/tcc/interceptor/TccAnnotationProcessor.java index c2674cc5dfc..6ea40955cff 100644 --- a/spring/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java +++ b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccAnnotationProcessor.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.rm.tcc.interceptor; import io.seata.rm.tcc.api.TwoPhaseBusinessAction; import io.seata.rm.tcc.remoting.RemotingDesc; -import io.seata.spring.util.TCCBeanParserUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; 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..1db26b3b48d --- /dev/null +++ b/tcc/src/test/java/io/seata/rm/tcc/spring/GlobalTransactionScannerSub.java @@ -0,0 +1,18 @@ +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 97% 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..b89e6fcfaba 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,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.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 96% 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..31b7f594b76 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,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.BusinessActionContext; From 444e478c6c730e9f73175b4d5cfd8c3c13f14075 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Sat, 28 May 2022 19:08:18 +0800 Subject: [PATCH 04/24] add Copyright --- .../autoproxy/DefaultTransactionAutoProxy.java | 15 +++++++++++++++ .../spring/autoproxy/TransactionAutoProxy.java | 15 +++++++++++++++ .../rm/tcc/autoproxy/TccTransactionAutoProxy.java | 15 +++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java b/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java index d61e78968a2..33d71799a37 100644 --- a/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java +++ b/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java @@ -1,3 +1,18 @@ +/* + * 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.spring.autoproxy; import io.seata.common.loader.EnhancedServiceLoader; diff --git a/spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java b/spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java index dd3e4a70610..a770f8802f1 100644 --- a/spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java +++ b/spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java @@ -1,3 +1,18 @@ +/* + * 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.spring.autoproxy; import org.aopalliance.intercept.MethodInterceptor; 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 index 917bb41317a..72d95213e01 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java +++ b/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java @@ -1,3 +1,18 @@ +/* + * 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.rm.tcc.interceptor.TCCBeanParserUtils; From bcf3aaa95789e88a415d474a731ce56f2a1cfbc8 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Wed, 15 Jun 2022 11:27:06 +0800 Subject: [PATCH 05/24] saga annotation mode actual plan --- .../io/seata/common/ConfigurationKeys.java | 5 + .../main/java/io/seata/common/Constants.java | 4 +- .../java/io/seata/common/DefaultValues.java | 5 + pom.xml | 1 + saga/anotation-mode/pom.xml | 32 ++++ .../io/seata/saga/api/SagaTransactional.java | 63 ++++++++ .../autoproxy/SagaTransactionAutoProxy.java | 97 ++++++++++++ .../interceptor/SagaActionInterceptor.java | 146 ++++++++++++++++++ saga/pom.xml | 1 + saga/seata-saga-rm/pom.xml | 5 + .../seata/saga/rm/SagaAnnotationResource.java | 81 ++++++++++ .../java/io/seata/saga/rm/SagaResource.java | 13 ++ .../io/seata/saga/rm/SagaResourceManager.java | 95 +++++++++++- .../SeataClientEnvironmentPostProcessor.java | 2 +- .../SeataTCCFenceAutoConfiguration.java | 2 +- .../properties/client/RmProperties.java | 21 ++- ...itional-spring-configuration-metadata.json | 4 +- spring/pom.xml | 10 +- .../rm/tcc/api/BusinessActionContext.java | 2 +- .../api/BusinessActionContextParameter.java | 12 +- .../rm/tcc/api/BusinessActionContextUtil.java | 43 +++++- .../java/io/seata/rm/tcc/api/ParamType.java | 0 .../annotation/GlobalTransactionScanner.java | 21 ++- .../seata/spring/annotation/LocalService.java | 33 ++++ .../DefaultTransactionAutoProxy.java | 40 +++-- .../autoproxy/IsTransactionProxyResult.java | 65 ++++++++ .../autoproxy/TransactionAutoProxy.java | 16 +- .../seata/spring/fence}/TCCFenceHandler.java | 13 +- .../spring/fence}/config/TCCFenceConfig.java | 8 +- .../fence}/constant/TCCFenceConstant.java | 2 +- .../fence}/exception/TCCFenceException.java | 2 +- .../seata/spring/fence}/store/TCCFenceDO.java | 2 +- .../spring/fence}/store/TCCFenceStore.java | 2 +- .../store/db/TCCFenceStoreDataBaseDAO.java | 10 +- .../store/db/sql/TCCFenceStoreSqls.java | 4 +- .../interceptor/ActionContextFilter.java | 2 +- .../interceptor/ActionContextUtil.java | 2 +- .../interceptor/ActionInterceptorHandler.java | 135 +++++++++++----- .../interceptor/TCCBeanParserUtils.java | 77 ++------- .../interceptor/TccAnnotationProcessor.java | 31 ++-- .../TwoPhaseBusinessActionParam.java | 78 ++++++++++ .../io/seata/spring}/remoting/Protocols.java | 2 +- .../seata/spring}/remoting/RemotingDesc.java | 2 +- .../spring}/remoting/RemotingParser.java | 2 +- .../spring/remoting}/TwoPhaseResult.java | 2 +- .../parser/AbstractedRemotingParser.java | 4 +- .../parser/DefaultRemotingParser.java | 62 ++------ .../remoting/parser/DubboRemotingParser.java | 6 +- .../remoting/parser/HSFRemotingParser.java | 6 +- .../parser/LocalServiceRemotingParser.java | 85 ++++++++++ .../parser/SofaRpcRemotingParser.java | 6 +- .../io.seata.spring.remoting.RemotingParser | 5 + tcc/pom.xml | 8 - .../io/seata/rm/tcc/TCCResourceManager.java | 58 +------ .../java/io/seata/rm/tcc/api/ModeType.java | 18 --- .../rm/tcc/api/TwoPhaseBusinessAction.java | 7 - .../autoproxy/TccTransactionAutoProxy.java | 108 +++++++++++-- .../tcc/interceptor/TccActionInterceptor.java | 87 ++++------- .../parser/LocalTCCRemotingParser.java | 5 +- .../io.seata.rm.tcc.remoting.RemotingParser | 4 - .../ActionInterceptorHandlerTest.java | 1 + .../parser/DefaultRemotingParserTest.java | 3 +- .../parser/LocalTCCRemotingParserTest.java | 2 +- 63 files changed, 1241 insertions(+), 429 deletions(-) create mode 100644 saga/anotation-mode/pom.xml create mode 100644 saga/anotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java create mode 100644 saga/anotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java create mode 100644 saga/anotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java create mode 100644 saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaAnnotationResource.java rename {tcc => spring}/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java (99%) rename {tcc => spring}/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java (85%) rename {tcc => spring}/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java (70%) rename {tcc => spring}/src/main/java/io/seata/rm/tcc/api/ParamType.java (100%) create mode 100644 spring/src/main/java/io/seata/spring/annotation/LocalService.java create mode 100644 spring/src/main/java/io/seata/spring/autoproxy/IsTransactionProxyResult.java rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring/fence}/TCCFenceHandler.java (97%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring/fence}/config/TCCFenceConfig.java (96%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring/fence}/constant/TCCFenceConstant.java (96%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring/fence}/exception/TCCFenceException.java (97%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring/fence}/store/TCCFenceDO.java (98%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring/fence}/store/TCCFenceStore.java (98%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring/fence}/store/db/TCCFenceStoreDataBaseDAO.java (95%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring/fence}/store/db/sql/TCCFenceStoreSqls.java (97%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/interceptor/ActionContextFilter.java (96%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/interceptor/ActionContextUtil.java (99%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/interceptor/ActionInterceptorHandler.java (69%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/interceptor/TCCBeanParserUtils.java (67%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/interceptor/TccAnnotationProcessor.java (76%) create mode 100644 spring/src/main/java/io/seata/spring/interceptor/TwoPhaseBusinessActionParam.java rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/remoting/Protocols.java (96%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/remoting/RemotingDesc.java (99%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/remoting/RemotingParser.java (98%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring/remoting}/TwoPhaseResult.java (98%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/remoting/parser/AbstractedRemotingParser.java (91%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/remoting/parser/DefaultRemotingParser.java (70%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/remoting/parser/DubboRemotingParser.java (95%) rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/remoting/parser/HSFRemotingParser.java (97%) create mode 100644 spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java rename {tcc/src/main/java/io/seata/rm/tcc => spring/src/main/java/io/seata/spring}/remoting/parser/SofaRpcRemotingParser.java (95%) create mode 100644 spring/src/main/resources/META-INF/services/io.seata.spring.remoting.RemotingParser delete mode 100644 tcc/src/main/java/io/seata/rm/tcc/api/ModeType.java delete mode 100644 tcc/src/main/resources/META-INF/services/io.seata.rm.tcc.remoting.RemotingParser diff --git a/common/src/main/java/io/seata/common/ConfigurationKeys.java b/common/src/main/java/io/seata/common/ConfigurationKeys.java index 3a07b50baea..5647ad248b8 100644 --- a/common/src/main/java/io/seata/common/ConfigurationKeys.java +++ b/common/src/main/java/io/seata/common/ConfigurationKeys.java @@ -231,6 +231,11 @@ public interface ConfigurationKeys { */ String TCC_ACTION_INTERCEPTOR_ORDER = CLIENT_RM_PREFIX + "tccActionInterceptorOrder"; + /** + * The constant SAGA_ACTION_INTERCEPTOR_ORDER. + */ + String SAGA_ACTION_INTERCEPTOR_ORDER = CLIENT_RM_PREFIX + "sagaActionInterceptorOrder"; + /** * The constant CLIENT_TM_PREFIX. */ diff --git a/common/src/main/java/io/seata/common/Constants.java b/common/src/main/java/io/seata/common/Constants.java index 4a9a64d3751..e688044cc79 100644 --- a/common/src/main/java/io/seata/common/Constants.java +++ b/common/src/main/java/io/seata/common/Constants.java @@ -162,8 +162,8 @@ public interface Constants { String SKIP_CHECK_LOCK = "skipCheckLock"; /** - * The constant MODE_TYPE + * phase two compensation method name */ - String MODE_TYPE = "modeType"; + String COMPENSATION_METHOD = "sys::compensation"; } diff --git a/common/src/main/java/io/seata/common/DefaultValues.java b/common/src/main/java/io/seata/common/DefaultValues.java index c982230262c..c97c53fe04e 100644 --- a/common/src/main/java/io/seata/common/DefaultValues.java +++ b/common/src/main/java/io/seata/common/DefaultValues.java @@ -147,6 +147,11 @@ public interface DefaultValues { */ 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 */ diff --git a/pom.xml b/pom.xml index c7bf5287b5b..b454f19a2f8 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,7 @@ sqlparser server ext/apm-seata-skywalking-plugin + anotation-mode diff --git a/saga/anotation-mode/pom.xml b/saga/anotation-mode/pom.xml new file mode 100644 index 00000000000..4f96e62ceb5 --- /dev/null +++ b/saga/anotation-mode/pom.xml @@ -0,0 +1,32 @@ + + + + seata-saga + io.seata + ${revision} + + 4.0.0 + + anotation-mode + + + 8 + 8 + + + + + ${project.groupId} + seata-spring + ${project.version} + + + io.seata + seata-saga-rm + ${project.version} + + + + \ No newline at end of file diff --git a/saga/anotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java b/saga/anotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java new file mode 100644 index 00000000000..1bfbd09b791 --- /dev/null +++ b/saga/anotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java @@ -0,0 +1,63 @@ +/* + * 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.saga.api; + +import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.rm.tcc.api.BusinessActionContextParameter; +import io.seata.rm.tcc.api.BusinessActionContextUtil; +import io.seata.saga.interceptor.SagaActionInterceptor; + +import java.lang.annotation.*; + +/** + * SAGA annotation. + * Define a SAGA interface, which added on the saga commit method. + * Must be used with `@LocalService`. + * + * @author ruishansun + * @see io.seata.spring.annotation.LocalService // local transaction annotation, which added on the transaction interface. It can't be left out. + * @see io.seata.spring.annotation.GlobalTransactionScanner#wrapIfNecessary(Object, String, Object) // the scanner for TM, GlobalLock, TCC mode, SAGA mode + * @see SagaActionInterceptor // the interceptor of SAGA mode + * @see BusinessActionContext + * @see BusinessActionContextUtil + * @see BusinessActionContextParameter + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +@Inherited +public @interface SagaTransactional { + + /** + * Saga bean name, must be unique + * + * @return the string + */ + String name(); + + /** + * compensation method name + * + * @return the string + */ + String compensationMethod() default "compensation"; + + /** + * compensation method's args + * + * @return the Class[] + */ + Class[] compensationArgsClasses() default {BusinessActionContext.class}; +} diff --git a/saga/anotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java b/saga/anotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java new file mode 100644 index 00000000000..033cf1ecd3a --- /dev/null +++ b/saga/anotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java @@ -0,0 +1,97 @@ +/* + * 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.saga.autoproxy; + +import io.seata.common.exception.FrameworkException; +import io.seata.rm.DefaultResourceManager; +import io.seata.saga.api.SagaTransactional; +import io.seata.saga.interceptor.SagaActionInterceptor; +import io.seata.saga.rm.SagaAnnotationResource; +import io.seata.spring.autoproxy.IsTransactionProxyResult; +import io.seata.spring.autoproxy.TransactionAutoProxy; +import io.seata.spring.remoting.Protocols; +import io.seata.spring.remoting.RemotingDesc; +import io.seata.spring.remoting.parser.DefaultRemotingParser; + +import java.lang.reflect.Method; + +/** + * the saga implements of TransactionAutoProxy + * + * @author ruishansun + */ +public class SagaTransactionAutoProxy implements TransactionAutoProxy { + + @Override + public IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remotingDesc) { + + if (remotingDesc == null) { + return new IsTransactionProxyResult(); + } + //check if it is saga bean + Class sagaInterfaceClazz = remotingDesc.getInterfaceClass(); + Method[] methods = sagaInterfaceClazz.getMethods(); + for (Method method : methods) { + SagaTransactional sagaTransactional = method.getAnnotation(SagaTransactional.class); + if(sagaTransactional != null && (Protocols.IN_JVM == remotingDesc.getProtocol() || remotingDesc.isReference())) { + this.registryResource(remotingDesc); + IsTransactionProxyResult result = new IsTransactionProxyResult(); + result.setProxyTargetBean(true); + result.setUseFence(true); + result.setMethodInterceptor(new SagaActionInterceptor(remotingDesc)); + return result; + } + } + return new IsTransactionProxyResult(); + } + + /** + * register saga resource + * @param remotingDesc the remotingDesc + */ + private void registryResource(RemotingDesc remotingDesc) { + if (!remotingDesc.isReference()) { + try { + Class interfaceClass = remotingDesc.getInterfaceClass(); + Method[] methods = interfaceClass.getMethods(); + //service bean, registry resource + Object targetBean = remotingDesc.getTargetBean(); + for (Method m : methods) { + SagaTransactional sagaTransactional = m.getAnnotation(SagaTransactional.class); + if (sagaTransactional != null) { + SagaAnnotationResource sagaAnnotationResource = new SagaAnnotationResource(); + sagaAnnotationResource.setUseSagaAnnotationMode(true); + sagaAnnotationResource.setActionName(sagaTransactional.name()); + sagaAnnotationResource.setTargetBean(targetBean); + sagaAnnotationResource.setCommitMethod(m); + sagaAnnotationResource.setCompensationMethodName(sagaTransactional.compensationMethod()); + sagaAnnotationResource.setCompensationMethod(interfaceClass.getMethod(sagaTransactional.compensationMethod(), + sagaTransactional.compensationArgsClasses())); + // set argsClasses + sagaAnnotationResource.setCompensationArgsClasses(sagaTransactional.compensationArgsClasses()); + // set phase two method's keys + sagaAnnotationResource.setPhaseTwoCompensationKeys(DefaultRemotingParser.get().getTwoPhaseArgs(sagaAnnotationResource.getCompensationMethod(), + sagaTransactional.compensationArgsClasses())); + //registry tcc resource + DefaultResourceManager.get().registerResource(sagaAnnotationResource); + } + } + } catch (Throwable t) { + throw new FrameworkException(t, "parser remoting service error"); + } + } + } +} diff --git a/saga/anotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java b/saga/anotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java new file mode 100644 index 00000000000..d3951263341 --- /dev/null +++ b/saga/anotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java @@ -0,0 +1,146 @@ +/* + * 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.saga.interceptor; + +import io.seata.common.Constants; +import io.seata.common.DefaultValues; +import io.seata.config.ConfigurationChangeEvent; +import io.seata.config.ConfigurationChangeListener; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.context.RootContext; +import io.seata.core.model.BranchType; +import io.seata.saga.api.SagaTransactional; +import io.seata.spring.interceptor.ActionInterceptorHandler; +import io.seata.spring.interceptor.TwoPhaseBusinessActionParam; +import io.seata.spring.remoting.RemotingDesc; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.ConfigurationKeys.SAGA_ACTION_INTERCEPTOR_ORDER; +import static io.seata.common.DefaultValues.DEFAULT_DISABLE_GLOBAL_TRANSACTION; + +/** + * SAGA Interceptor + * + * @author ruishansun + */ +public class SagaActionInterceptor implements MethodInterceptor, ConfigurationChangeListener, Ordered { + + private static final Logger LOGGER = LoggerFactory.getLogger(SagaActionInterceptor.class); + + private static final int ORDER_NUM = ConfigurationFactory.getInstance().getInt(SAGA_ACTION_INTERCEPTOR_ORDER, + DefaultValues.SAGA_ACTION_INTERCEPTOR_ORDER); + + /** + * TODO Singleton? + */ + private ActionInterceptorHandler actionInterceptorHandler = new ActionInterceptorHandler(); + + private volatile boolean disable = ConfigurationFactory.getInstance().getBoolean( + ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, DEFAULT_DISABLE_GLOBAL_TRANSACTION); + + /** + * remoting bean info + */ + protected RemotingDesc remotingDesc; + + /** + * Instantiates a new Saga action interceptor. + */ + public SagaActionInterceptor() { + } + + /** + * Instantiates a new Saga action interceptor. + * + * @param remotingDesc the remoting desc + */ + public SagaActionInterceptor(RemotingDesc remotingDesc) { + this.remotingDesc = remotingDesc; + } + + @Nullable + @Override + public Object invoke(@NotNull MethodInvocation invocation) throws Throwable { + if (!RootContext.inGlobalTransaction() || disable || RootContext.inTccBranch()) { + //not in transaction, or this interceptor is disabled + return invocation.proceed(); + } + Method method = actionInterceptorHandler.getActionInterfaceMethod(invocation, this.remotingDesc); + SagaTransactional sagaTransactional = method.getAnnotation(SagaTransactional.class); + //commit method + if (sagaTransactional != null) { + //save the xid + String xid = RootContext.getXID(); + //save the previous branchType + BranchType previousBranchType = RootContext.getBranchType(); + //if not SAGA, bind SAGA branchType + if (BranchType.SAGA != previousBranchType) { + RootContext.bindBranchType(BranchType.SAGA); + } + try { + TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam(); + businessActionParam.setActionName(sagaTransactional.name()); + businessActionParam.setDelayReport(false); + businessActionParam.setUseFence(true); + Map businessActionContextMap = new HashMap<>(4); + //the phase two method name + businessActionContextMap.put(Constants.COMPENSATION_METHOD, sagaTransactional.compensationMethod()); + businessActionContextMap.put(Constants.ACTION_NAME, sagaTransactional.name()); + businessActionContextMap.put(Constants.USE_TCC_FENCE, true); + businessActionParam.setBusinessActionContext(businessActionContextMap); + //Handler the Saga Aspect, and return the business result + return actionInterceptorHandler.proceed(method, invocation.getArguments(), xid, businessActionParam, + invocation::proceed); + } finally { + //if not SAGA, unbind branchType + if (BranchType.SAGA != previousBranchType) { + RootContext.unbindBranchType(); + } + //MDC remove branchId + MDC.remove(RootContext.MDC_KEY_BRANCH_ID); + } + } + + //not SAGA commit method + return invocation.proceed(); + } + + @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 = Boolean.parseBoolean(event.getNewValue().trim()); + } + } + + @Override + public int getOrder() { + return ORDER_NUM; + } +} diff --git a/saga/pom.xml b/saga/pom.xml index 78b2a1f9066..3b0ee1108e3 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -35,6 +35,7 @@ seata-saga-rm seata-saga-tm seata-saga-engine-store + anotation-mode diff --git a/saga/seata-saga-rm/pom.xml b/saga/seata-saga-rm/pom.xml index 4a7bd62aa2d..af0896cadc2 100644 --- a/saga/seata-saga-rm/pom.xml +++ b/saga/seata-saga-rm/pom.xml @@ -43,6 +43,11 @@ seata-saga-engine ${project.version} + + io.seata + seata-spring + ${project.version} + diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaAnnotationResource.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaAnnotationResource.java new file mode 100644 index 00000000000..a4e7c2e487b --- /dev/null +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaAnnotationResource.java @@ -0,0 +1,81 @@ +package io.seata.saga.rm; + +import java.lang.reflect.Method; + +/** + * Saga annotation mode resource (Only register application as a saga annotation mode resource) + * + * @author ruishansun + */ +public class SagaAnnotationResource extends SagaResource { + + private Object targetBean; + + private String actionName; + + private Method commitMethod; + + private Method compensationMethod; + + private String compensationMethodName; + + private Class[] compensationArgsClasses; + + private String[] phaseTwoCompensationKeys; + + public Object getTargetBean() { + return targetBean; + } + + public void setTargetBean(Object targetBean) { + this.targetBean = targetBean; + } + + public String getActionName() { + return actionName; + } + + public void setActionName(String actionName) { + this.actionName = actionName; + } + + public Method getCommitMethod() { + return commitMethod; + } + + public void setCommitMethod(Method commitMethod) { + this.commitMethod = commitMethod; + } + + public Method getCompensationMethod() { + return compensationMethod; + } + + public void setCompensationMethod(Method compensationMethod) { + this.compensationMethod = compensationMethod; + } + + public String getCompensationMethodName() { + return compensationMethodName; + } + + public void setCompensationMethodName(String compensationMethodName) { + this.compensationMethodName = compensationMethodName; + } + + public Class[] getCompensationArgsClasses() { + return compensationArgsClasses; + } + + public void setCompensationArgsClasses(Class[] compensationArgsClasses) { + this.compensationArgsClasses = compensationArgsClasses; + } + + public String[] getPhaseTwoCompensationKeys() { + return phaseTwoCompensationKeys; + } + + public void setPhaseTwoCompensationKeys(String[] phaseTwoCompensationKeys) { + this.phaseTwoCompensationKeys = phaseTwoCompensationKeys; + } +} diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResource.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResource.java index 8a087c3b8c4..a64ca5f076e 100644 --- a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResource.java +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResource.java @@ -29,6 +29,11 @@ public class SagaResource implements Resource { private String applicationId; + /** + * whether used saga annotation mode + */ + private boolean useSagaAnnotationMode; + /** * Gets get resource group id. * @@ -85,4 +90,12 @@ public String getApplicationId() { public void setApplicationId(String applicationId) { this.applicationId = applicationId; } + + public boolean isUseSagaAnnotationMode() { + return useSagaAnnotationMode; + } + + public void setUseSagaAnnotationMode(boolean useSagaAnnotationMode) { + this.useSagaAnnotationMode = useSagaAnnotationMode; + } } \ No newline at end of file diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java index b58120b8d6c..88947e90e26 100644 --- a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java @@ -15,24 +15,33 @@ */ package io.seata.saga.rm; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - +import io.seata.common.Constants; import io.seata.common.exception.FrameworkErrorCode; +import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.exception.SkipCallbackWrapperException; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; import io.seata.core.model.GlobalStatus; import io.seata.core.model.Resource; import io.seata.rm.AbstractResourceManager; +import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.rm.tcc.api.BusinessActionContextUtil; import io.seata.saga.engine.exception.EngineExecutionException; import io.seata.saga.engine.exception.ForwardInvalidException; import io.seata.saga.statelang.domain.ExecutionStatus; import io.seata.saga.statelang.domain.RecoverStrategy; import io.seata.saga.statelang.domain.StateMachineInstance; +import io.seata.spring.fence.TCCFenceHandler; +import io.seata.spring.remoting.TwoPhaseResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.lang.reflect.Method; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** * Saga resource manager * @@ -84,6 +93,17 @@ public Map getManagedResources() { @Override public BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) throws TransactionException { + + // Saga annotation mode + SagaResource sagaResource = (SagaResource)sagaResourceCache.get(resourceId); + if (sagaResource == null) { + throw new ShouldNeverHappenException(String.format("Saga resource is not exist, resourceId: %s", resourceId)); + } + if(sagaResource.isUseSagaAnnotationMode()) { + return BranchStatus.PhaseTwo_Committed; + } + + // Saga state machine mode try { StateMachineInstance machineInstance = StateMachineEngineHolder.getStateMachineEngine().forward(xid, null); @@ -127,6 +147,17 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI @Override public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) throws TransactionException { + + // Saga annotation mode + SagaResource sagaResource = (SagaResource)sagaResourceCache.get(resourceId); + if (sagaResource == null) { + throw new ShouldNeverHappenException(String.format("Saga resource is not exist, resourceId: %s", resourceId)); + } + if(sagaResource.isUseSagaAnnotationMode()) { + return this.sagaCompensateBranch(xid, branchId, resourceId, applicationData, (SagaAnnotationResource) sagaResource); + } + + // Saga state machine mode try { StateMachineInstance stateMachineInstance = StateMachineEngineHolder.getStateMachineEngine().reloadStateMachineInstance(xid); if (stateMachineInstance == null) { @@ -156,6 +187,64 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc } return BranchStatus.PhaseTwo_RollbackFailed_Retryable; } + + private BranchStatus sagaCompensateBranch(String xid, long branchId, String resourceId, String applicationData, SagaAnnotationResource sagaAnnotationResource) { + if (sagaAnnotationResource == null) { + throw new ShouldNeverHappenException(String.format("Saga annotation resource is not exist, resourceId: %s", resourceId)); + } + Object targetSagaBean = sagaAnnotationResource.getTargetBean(); + Method compensationMethod = sagaAnnotationResource.getCompensationMethod(); + if (targetSagaBean == null || compensationMethod == null) { + throw new ShouldNeverHappenException(String.format("Saga target Bean or compensationMethod is not available, resourceId: %s", resourceId)); + } + try { + //BusinessActionContext + BusinessActionContext businessActionContext = BusinessActionContextUtil.getBusinessActionContext(xid, branchId, resourceId, + applicationData); + Object[] args = this.getTwoPhaseCompensationArgs(sagaAnnotationResource, businessActionContext); + + Object ret; + boolean result; + // add idempotent and anti hanging + if (Boolean.TRUE.equals(businessActionContext.getActionContext(Constants.USE_TCC_FENCE))) { + try { + result = TCCFenceHandler.rollbackFence(compensationMethod, targetSagaBean, xid, branchId, + args, sagaAnnotationResource.getActionName()); + } catch (SkipCallbackWrapperException | UndeclaredThrowableException e) { + throw e.getCause(); + } + } else { + ret = compensationMethod.invoke(targetSagaBean, args); + if (ret != null) { + if (ret instanceof TwoPhaseResult) { + result = ((TwoPhaseResult)ret).isSuccess(); + } else { + result = (boolean)ret; + } + } else { + result = true; + } + } + LOGGER.info("Saga resource compensation result : {}, xid: {}, branchId: {}, resourceId: {}", result, xid, branchId, resourceId); + return result ? BranchStatus.PhaseTwo_Rollbacked : BranchStatus.PhaseTwo_RollbackFailed_Retryable; + } catch (Throwable t) { + String msg = String.format("compensation Saga resource error, resourceId: %s, xid: %s.", resourceId, xid); + LOGGER.error(msg, t); + return BranchStatus.PhaseTwo_RollbackFailed_Retryable; + } + } + + /** + * get phase two compensate method's args + * @param sagaAnnotationResource sagaAnnotationResource + * @param businessActionContext businessActionContext + * @return args + */ + private Object[] getTwoPhaseCompensationArgs(SagaAnnotationResource sagaAnnotationResource, BusinessActionContext businessActionContext) { + String[] keys = sagaAnnotationResource.getPhaseTwoCompensationKeys(); + Class[] argsCommitClasses = sagaAnnotationResource.getCompensationArgsClasses(); + return BusinessActionContextUtil.getTwoPhaseMethodParams(keys, argsCommitClasses, businessActionContext); + } @Override public BranchType getBranchType() { 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..abd8f568d2d 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,7 +16,7 @@ package io.seata.spring.boot.autoconfigure; import io.seata.common.holder.ObjectHolder; -import io.seata.rm.tcc.config.TCCFenceConfig; +import io.seata.spring.fence.config.TCCFenceConfig; import io.seata.saga.engine.StateMachineConfig; import io.seata.spring.boot.autoconfigure.properties.SagaAsyncThreadPoolProperties; import io.seata.spring.boot.autoconfigure.properties.SeataProperties; 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..2905734c4d2 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.spring.fence.config.TCCFenceConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/RmProperties.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/RmProperties.java index 705e05ff1bd..f680d5842b7 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/RmProperties.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/RmProperties.java @@ -19,18 +19,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; -import static io.seata.common.DefaultValues.DEFAULT_CLIENT_ASYNC_COMMIT_BUFFER_LIMIT; -import static io.seata.common.DefaultValues.DEFAULT_CLIENT_REPORT_RETRY_COUNT; -import static io.seata.common.DefaultValues.DEFAULT_CLIENT_REPORT_SUCCESS_ENABLE; -import static io.seata.common.DefaultValues.DEFAULT_CLIENT_SAGA_BRANCH_REGISTER_ENABLE; -import static io.seata.common.DefaultValues.DEFAULT_CLIENT_SAGA_COMPENSATE_PERSIST_MODE_UPDATE; -import static io.seata.common.DefaultValues.DEFAULT_CLIENT_SAGA_RETRY_PERSIST_MODE_UPDATE; -import static io.seata.common.DefaultValues.DEFAULT_CLIENT_TABLE_META_CHECK_ENABLE; -import static io.seata.common.DefaultValues.DEFAULT_SAGA_JSON_PARSER; -import static io.seata.common.DefaultValues.DEFAULT_TABLE_META_CHECKER_INTERVAL; -import static io.seata.common.DefaultValues.TCC_ACTION_INTERCEPTOR_ORDER; -import static io.seata.common.DefaultValues.DEFAULT_XA_BRANCH_EXECUTION_TIMEOUT; -import static io.seata.common.DefaultValues.DEFAULT_XA_CONNECTION_TWO_PHASE_HOLD_TIMEOUT; +import static io.seata.common.DefaultValues.*; import static io.seata.spring.boot.autoconfigure.StarterConstants.CLIENT_RM_PREFIX; /** @@ -49,6 +38,7 @@ public class RmProperties { private boolean sagaRetryPersistModeUpdate = DEFAULT_CLIENT_SAGA_RETRY_PERSIST_MODE_UPDATE; private boolean sagaCompensatePersistModeUpdate = DEFAULT_CLIENT_SAGA_COMPENSATE_PERSIST_MODE_UPDATE; private int tccActionInterceptorOrder = TCC_ACTION_INTERCEPTOR_ORDER; + private int sagaActionInterceptorOrder = SAGA_ACTION_INTERCEPTOR_ORDER; private int branchExecutionTimeoutXA = DEFAULT_XA_BRANCH_EXECUTION_TIMEOUT; private int connectionTwoPhaseHoldTimeoutXA = DEFAULT_XA_CONNECTION_TWO_PHASE_HOLD_TIMEOUT; private String sqlParserType = SqlParserType.SQL_PARSER_TYPE_DRUID; @@ -164,4 +154,11 @@ public void setConnectionTwoPhaseHoldTimeoutXA(int connectionTwoPhaseHoldTimeout this.connectionTwoPhaseHoldTimeoutXA = connectionTwoPhaseHoldTimeoutXA; } + public int getSagaActionInterceptorOrder() { + return sagaActionInterceptorOrder; + } + + public void setSagaActionInterceptorOrder(int sagaActionInterceptorOrder) { + this.sagaActionInterceptorOrder = sagaActionInterceptorOrder; + } } 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..b75a92642fc 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.spring.fence.config.TCCFenceConfig", "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.spring.fence.config.TCCFenceConfig", "defaultValue": "1d" }, { diff --git a/spring/pom.xml b/spring/pom.xml index 18acde766c4..5fa7386c857 100644 --- a/spring/pom.xml +++ b/spring/pom.xml @@ -58,6 +58,10 @@ org.springframework spring-context + + org.springframework + spring-jdbc + org.jetbrains.kotlin kotlin-stdlib-jdk8 @@ -72,8 +76,10 @@ org.jetbrains.kotlinx kotlinx-coroutines-core - - + + com.alibaba + fastjson + diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java b/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java similarity index 99% rename from tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java rename to spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java index f11b3249940..8c5a8a8c6e1 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java +++ b/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java @@ -20,7 +20,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import io.seata.rm.tcc.interceptor.ActionContextUtil; +import io.seata.spring.interceptor.ActionContextUtil; /** * The type Business action context. diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java b/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java similarity index 85% rename from tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java rename to spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java index 518a7c5dec4..786b8a8549b 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java +++ b/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java @@ -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; } diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java b/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java similarity index 70% rename from tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java rename to spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java index 30a52ae0500..8756a788294 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java +++ b/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java @@ -16,17 +16,19 @@ package io.seata.rm.tcc.api; import java.util.Collections; +import java.util.HashMap; import java.util.Map; 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.rm.DefaultResourceManager; -import io.seata.rm.tcc.interceptor.ActionContextUtil; +import io.seata.spring.interceptor.ActionContextUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -134,4 +136,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.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; + } + + 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; + } } diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/ParamType.java b/spring/src/main/java/io/seata/rm/tcc/api/ParamType.java similarity index 100% rename from tcc/src/main/java/io/seata/rm/tcc/api/ParamType.java rename to spring/src/main/java/io/seata/rm/tcc/api/ParamType.java 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 bc309fc6fb3..b211e3aa312 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java @@ -38,6 +38,9 @@ import io.seata.rm.RMClient; import io.seata.spring.annotation.scannercheckers.PackageScannerChecker; import io.seata.spring.autoproxy.DefaultTransactionAutoProxy; +import io.seata.spring.autoproxy.IsTransactionProxyResult; +import io.seata.spring.interceptor.TCCBeanParserUtils; +import io.seata.spring.remoting.parser.LocalServiceRemotingParser; import io.seata.spring.util.OrderUtil; import io.seata.spring.util.SpringProxyUtils; import io.seata.tm.TMClient; @@ -258,9 +261,18 @@ private void registerSpringShutdownHook() { * 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.rm.tcc.interceptor.TccActionInterceptor // the interceptor of TCC mode + * + * SAGA annotation mode: + * @see LocalService // local service annotation on interface + * @see io.seata.saga.api.SagaTransactional // SAGA annotation on commit method + * @see LocalServiceRemotingParser // Remote SAGA service parser + * @see io.seata.saga.autoproxy.SagaTransactionAutoProxy // SAGA transaction auto proxy + * Corresponding interceptor: + * @see io.seata.saga.interceptor.SagaActionInterceptor // the interceptor of SAGA annotation mode + * */ @Override protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { @@ -276,8 +288,11 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) } interceptor = null; //check Transaction proxy - interceptor = DefaultTransactionAutoProxy.get().isTransactionAutoProxy(bean, beanName, applicationContext); - if (interceptor != null) { + if (TCCBeanParserUtils.isTccAutoProxy(bean, beanName, applicationContext)) { + IsTransactionProxyResult isTransactionProxyResult = DefaultTransactionAutoProxy.get().getIsProxyTargetBeanResult(beanName); + // init tcc fence clean task if enable useTccFence + TCCBeanParserUtils.initTccFenceCleanTask(TCCBeanParserUtils.getRemotingDesc(beanName), applicationContext, isTransactionProxyResult.isUseFence()); + interceptor = isTransactionProxyResult.getMethodInterceptor(); ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, (ConfigurationChangeListener) interceptor); } else { diff --git a/spring/src/main/java/io/seata/spring/annotation/LocalService.java b/spring/src/main/java/io/seata/spring/annotation/LocalService.java new file mode 100644 index 00000000000..e0ea6b31611 --- /dev/null +++ b/spring/src/main/java/io/seata/spring/annotation/LocalService.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.spring.annotation; + +import io.seata.spring.remoting.parser.LocalServiceRemotingParser; + +import java.lang.annotation.*; + +/** + * Local transaction bean annotation, add on the TCC/SAGA interface + * + * @author ruishansun + * @see io.seata.spring.annotation.GlobalTransactionScanner#wrapIfNecessary(Object, String, Object) // the scanner for TM, GlobalLock, TCC mode and SAGA mode + * @see LocalServiceRemotingParser // the RemotingParser impl for Local transaction + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Inherited +public @interface LocalService { +} diff --git a/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java b/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java index 33d71799a37..421f7e38b43 100644 --- a/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java +++ b/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java @@ -17,11 +17,12 @@ import io.seata.common.loader.EnhancedServiceLoader; import io.seata.common.util.CollectionUtils; -import org.aopalliance.intercept.MethodInterceptor; -import org.springframework.context.ApplicationContext; +import io.seata.spring.remoting.RemotingDesc; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * the default transaction auto proxy @@ -34,6 +35,10 @@ public class DefaultTransactionAutoProxy { * all the transaction auto proxy */ protected static List allTransactionAutoProxies = new ArrayList<>(); + /** + * method interceptor map, beanName -> IsTransactionProxyResult + */ + private final Map methodInterceptorMap = new ConcurrentHashMap<>(); private static class SingletonHolder { private static final DefaultTransactionAutoProxy INSTANCE = new DefaultTransactionAutoProxy(); @@ -66,20 +71,31 @@ private void initTransactionAutoProxy() { } /** - * is transaction auto proxy ? + * whether is transaction auto proxy * - * @param bean the bean - * @param beanName the beanName - * @param applicationContext the applicationContext - * @return the MethodInterceptor or null + * @param beanName the beanName + * @param remotingDesc the remotingDesc + * @return true or false */ - public MethodInterceptor isTransactionAutoProxy(Object bean, String beanName, ApplicationContext applicationContext) { + public boolean isTransactionAutoProxy(String beanName, RemotingDesc remotingDesc) { for (TransactionAutoProxy proxy : allTransactionAutoProxies) { - MethodInterceptor methodInterceptor = proxy.isTransactionAutoProxy(bean, beanName, applicationContext); - if (methodInterceptor != null) { - return methodInterceptor; + IsTransactionProxyResult result = proxy.isTransactionProxyTargetBean(remotingDesc); + if (result.isProxyTargetBean()) { + methodInterceptorMap.put(beanName, result); + return true; } } - return null; + return false; + } + + /** + * get the IsTransactionProxyResult + * + * @param beanName the beanName + * @return the IsTransactionProxyResult + */ + public IsTransactionProxyResult getIsProxyTargetBeanResult(String beanName) { + IsTransactionProxyResult result = methodInterceptorMap.get(beanName); + return result != null ? result : new IsTransactionProxyResult(); } } diff --git a/spring/src/main/java/io/seata/spring/autoproxy/IsTransactionProxyResult.java b/spring/src/main/java/io/seata/spring/autoproxy/IsTransactionProxyResult.java new file mode 100644 index 00000000000..0ba74692642 --- /dev/null +++ b/spring/src/main/java/io/seata/spring/autoproxy/IsTransactionProxyResult.java @@ -0,0 +1,65 @@ +/* + * 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.spring.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 fence + */ + private boolean useFence; + + /** + * transaction proxy method + */ + private MethodInterceptor methodInterceptor; + + public boolean isProxyTargetBean() { + return isProxyTargetBean; + } + + public void setProxyTargetBean(boolean proxyTargetBean) { + isProxyTargetBean = proxyTargetBean; + } + + public boolean isUseFence() { + return useFence; + } + + public void setUseFence(boolean useFence) { + this.useFence = useFence; + } + + public MethodInterceptor getMethodInterceptor() { + return methodInterceptor; + } + + public void setMethodInterceptor(MethodInterceptor methodInterceptor) { + this.methodInterceptor = methodInterceptor; + } +} diff --git a/spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java b/spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java index a770f8802f1..1f54cf24992 100644 --- a/spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java +++ b/spring/src/main/java/io/seata/spring/autoproxy/TransactionAutoProxy.java @@ -15,24 +15,20 @@ */ package io.seata.spring.autoproxy; -import org.aopalliance.intercept.MethodInterceptor; -import org.springframework.context.ApplicationContext; +import io.seata.spring.remoting.RemotingDesc; /** - * The interface Transaction Auto Proxy. - * if result is not null, then proxied by tcc/saga with SPI. + * The interface Transaction Auto Proxy. Proxied by tcc/saga with SPI. * * @author ruishansun */ public interface TransactionAutoProxy { /** - * if it is transaction auto proxy? (tcc or saga) + * Whether it is transaction auto proxy? (tcc or saga) * - * @param bean the bean - * @param beanName the beanName - * @param applicationContext the applicationContext - * @return the MethodInterceptor + * @param remotingDesc the remotingDesc + * @return the IsTransactionProxyResult */ - MethodInterceptor isTransactionAutoProxy(Object bean, String beanName, ApplicationContext applicationContext); + IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remotingDesc); } diff --git a/tcc/src/main/java/io/seata/rm/tcc/TCCFenceHandler.java b/spring/src/main/java/io/seata/spring/fence/TCCFenceHandler.java similarity index 97% rename from tcc/src/main/java/io/seata/rm/tcc/TCCFenceHandler.java rename to spring/src/main/java/io/seata/spring/fence/TCCFenceHandler.java index f5a4dee1021..dfbe37a3d9c 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TCCFenceHandler.java +++ b/spring/src/main/java/io/seata/spring/fence/TCCFenceHandler.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.spring.fence; import java.lang.reflect.Method; import java.sql.Connection; @@ -28,11 +28,12 @@ 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.spring.fence.constant.TCCFenceConstant; +import io.seata.spring.fence.exception.TCCFenceException; +import io.seata.spring.fence.store.TCCFenceDO; +import io.seata.spring.fence.store.TCCFenceStore; +import io.seata.spring.fence.store.db.TCCFenceStoreDataBaseDAO; +import io.seata.spring.remoting.TwoPhaseResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.datasource.DataSourceUtils; diff --git a/tcc/src/main/java/io/seata/rm/tcc/config/TCCFenceConfig.java b/spring/src/main/java/io/seata/spring/fence/config/TCCFenceConfig.java similarity index 96% rename from tcc/src/main/java/io/seata/rm/tcc/config/TCCFenceConfig.java rename to spring/src/main/java/io/seata/spring/fence/config/TCCFenceConfig.java index fffc08ab993..bef13fec8f8 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/config/TCCFenceConfig.java +++ b/spring/src/main/java/io/seata/spring/fence/config/TCCFenceConfig.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.spring.fence.config; import java.time.Duration; import java.util.Date; @@ -27,9 +27,9 @@ import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.thread.NamedThreadFactory; 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.spring.fence.TCCFenceHandler; +import io.seata.spring.fence.exception.TCCFenceException; +import io.seata.spring.fence.store.db.TCCFenceStoreDataBaseDAO; import org.apache.commons.lang.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/tcc/src/main/java/io/seata/rm/tcc/constant/TCCFenceConstant.java b/spring/src/main/java/io/seata/spring/fence/constant/TCCFenceConstant.java similarity index 96% rename from tcc/src/main/java/io/seata/rm/tcc/constant/TCCFenceConstant.java rename to spring/src/main/java/io/seata/spring/fence/constant/TCCFenceConstant.java index 7c9a2b416cf..41e5262df10 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/constant/TCCFenceConstant.java +++ b/spring/src/main/java/io/seata/spring/fence/constant/TCCFenceConstant.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.constant; +package io.seata.spring.fence.constant; /** * TCC Fence Constant diff --git a/tcc/src/main/java/io/seata/rm/tcc/exception/TCCFenceException.java b/spring/src/main/java/io/seata/spring/fence/exception/TCCFenceException.java similarity index 97% rename from tcc/src/main/java/io/seata/rm/tcc/exception/TCCFenceException.java rename to spring/src/main/java/io/seata/spring/fence/exception/TCCFenceException.java index 716da66ed1f..b945203ccde 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/exception/TCCFenceException.java +++ b/spring/src/main/java/io/seata/spring/fence/exception/TCCFenceException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.exception; +package io.seata.spring.fence.exception; import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.exception.FrameworkException; diff --git a/tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceDO.java b/spring/src/main/java/io/seata/spring/fence/store/TCCFenceDO.java similarity index 98% rename from tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceDO.java rename to spring/src/main/java/io/seata/spring/fence/store/TCCFenceDO.java index 6878a9a0c74..98437858834 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceDO.java +++ b/spring/src/main/java/io/seata/spring/fence/store/TCCFenceDO.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.spring.fence.store; import java.util.Date; diff --git a/tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceStore.java b/spring/src/main/java/io/seata/spring/fence/store/TCCFenceStore.java similarity index 98% rename from tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceStore.java rename to spring/src/main/java/io/seata/spring/fence/store/TCCFenceStore.java index 9cbd6ba255e..04ac5915904 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/store/TCCFenceStore.java +++ b/spring/src/main/java/io/seata/spring/fence/store/TCCFenceStore.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.spring.fence.store; import java.sql.Connection; import java.util.Date; diff --git a/tcc/src/main/java/io/seata/rm/tcc/store/db/TCCFenceStoreDataBaseDAO.java b/spring/src/main/java/io/seata/spring/fence/store/db/TCCFenceStoreDataBaseDAO.java similarity index 95% rename from tcc/src/main/java/io/seata/rm/tcc/store/db/TCCFenceStoreDataBaseDAO.java rename to spring/src/main/java/io/seata/spring/fence/store/db/TCCFenceStoreDataBaseDAO.java index 10e6c2979fd..43bb775e263 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/store/db/TCCFenceStoreDataBaseDAO.java +++ b/spring/src/main/java/io/seata/spring/fence/store/db/TCCFenceStoreDataBaseDAO.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.spring.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.spring.fence.exception.TCCFenceException; +import io.seata.spring.fence.store.TCCFenceDO; +import io.seata.spring.fence.store.TCCFenceStore; +import io.seata.spring.fence.store.db.sql.TCCFenceStoreSqls; import java.sql.Connection; import java.sql.PreparedStatement; diff --git a/tcc/src/main/java/io/seata/rm/tcc/store/db/sql/TCCFenceStoreSqls.java b/spring/src/main/java/io/seata/spring/fence/store/db/sql/TCCFenceStoreSqls.java similarity index 97% rename from tcc/src/main/java/io/seata/rm/tcc/store/db/sql/TCCFenceStoreSqls.java rename to spring/src/main/java/io/seata/spring/fence/store/db/sql/TCCFenceStoreSqls.java index 130cb132c46..06436d3ff72 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/store/db/sql/TCCFenceStoreSqls.java +++ b/spring/src/main/java/io/seata/spring/fence/store/db/sql/TCCFenceStoreSqls.java @@ -13,9 +13,9 @@ * 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.spring.fence.store.db.sql; -import io.seata.rm.tcc.constant.TCCFenceConstant; +import io.seata.spring.fence.constant.TCCFenceConstant; /** * TCC Fence Store Sqls diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextFilter.java b/spring/src/main/java/io/seata/spring/interceptor/ActionContextFilter.java similarity index 96% rename from tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextFilter.java rename to spring/src/main/java/io/seata/spring/interceptor/ActionContextFilter.java index 32a6f492161..e0f86ad70a9 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextFilter.java +++ b/spring/src/main/java/io/seata/spring/interceptor/ActionContextFilter.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.spring.interceptor; import io.seata.rm.tcc.api.BusinessActionContextParameter; diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextUtil.java b/spring/src/main/java/io/seata/spring/interceptor/ActionContextUtil.java similarity index 99% rename from tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextUtil.java rename to spring/src/main/java/io/seata/spring/interceptor/ActionContextUtil.java index 8b50b52bce9..4cc9ee1085c 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionContextUtil.java +++ b/spring/src/main/java/io/seata/spring/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.spring.interceptor; import java.lang.reflect.Field; import java.util.Collections; diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java b/spring/src/main/java/io/seata/spring/interceptor/ActionInterceptorHandler.java similarity index 69% rename from tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java rename to spring/src/main/java/io/seata/spring/interceptor/ActionInterceptorHandler.java index d02fc6c55fe..7dc0c3f2c98 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandler.java +++ b/spring/src/main/java/io/seata/spring/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.spring.interceptor; import com.alibaba.fastjson.JSON; import io.seata.common.Constants; @@ -31,18 +23,29 @@ import io.seata.common.util.CollectionUtils; import io.seata.common.util.NetUtil; import io.seata.core.context.RootContext; -import io.seata.core.model.BranchType; 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 io.seata.spring.fence.TCCFenceHandler; +import io.seata.spring.remoting.RemotingDesc; +import io.seata.spring.util.DubboUtil; +import io.seata.spring.util.SpringProxyUtils; +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 * @@ -55,28 +58,28 @@ public class ActionInterceptorHandler { /** * Handler the TCC Aspect * - * @param method the method - * @param arguments the arguments - * @param businessAction the business action - * @param targetCallback the target callback + * @param method the method + * @param arguments the arguments + * @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()); //Creating Branch Record - String branchId = doTccActionLogStore(method, arguments, businessAction, actionContext); + String branchId = doTccActionLogStore(method, arguments, businessActionParam, actionContext); actionContext.setBranchId(branchId); //MDC put branchId MDC.put(RootContext.MDC_KEY_BRANCH_ID, branchId); @@ -87,7 +90,7 @@ public Object proceed(Method method, Object[] arguments, String xid, TwoPhaseBus //share actionContext implicitly BusinessActionContextUtil.setContext(actionContext); - if (businessAction.useTCCFence()) { + if (businessActionParam.getUseFence()) { try { // Use TCC Fence, and return the business result return TCCFenceHandler.prepareFence(xid, Long.valueOf(branchId), actionName, targetCallback); @@ -133,7 +136,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(); @@ -157,13 +160,13 @@ 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, + protected String doTccActionLogStore(Method method, Object[] arguments, TwoPhaseBusinessActionParam businessActionParam, BusinessActionContext actionContext) { String actionName = actionContext.getActionName(); String xid = actionContext.getXid(); @@ -174,7 +177,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); @@ -195,7 +198,7 @@ protected String doTccActionLogStore(Method method, Object[] arguments, TwoPhase 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) { @@ -221,23 +224,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.put(Constants.MODE_TYPE, businessAction.modeType()); + context.putAll(businessActionContext); } } @@ -248,7 +247,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(); @@ -256,7 +255,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"); } @@ -274,4 +273,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 interfaceType = null; + try { + if (remotingDesc == null) { + interfaceType = getProxyInterface(invocation.getThis()); + } else { + interfaceType = remotingDesc.getInterfaceClass(); + } + if (interfaceType == null && remotingDesc != null && remotingDesc.getInterfaceClassName() != null) { + interfaceType = Class.forName(remotingDesc.getInterfaceClassName(), true, + Thread.currentThread().getContextClassLoader()); + } + if (interfaceType == null) { + return invocation.getMethod(); + } + return interfaceType.getMethod(invocation.getMethod().getName(), + invocation.getMethod().getParameterTypes()); + } catch (NoSuchMethodException e) { + if (interfaceType != null && !"toString".equals(invocation.getMethod().getName())) { + LOGGER.warn("no such method '{}' from interface {}", invocation.getMethod().getName(), interfaceType.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); + } + } } diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/TCCBeanParserUtils.java b/spring/src/main/java/io/seata/spring/interceptor/TCCBeanParserUtils.java similarity index 67% rename from tcc/src/main/java/io/seata/rm/tcc/interceptor/TCCBeanParserUtils.java rename to spring/src/main/java/io/seata/spring/interceptor/TCCBeanParserUtils.java index c90242fa3c1..11d87234494 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/TCCBeanParserUtils.java +++ b/spring/src/main/java/io/seata/spring/interceptor/TCCBeanParserUtils.java @@ -13,21 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.interceptor; +package io.seata.spring.interceptor; 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.autoproxy.DefaultTransactionAutoProxy; +import io.seata.spring.fence.config.TCCFenceConfig; +import io.seata.spring.remoting.Protocols; +import io.seata.spring.remoting.RemotingDesc; +import io.seata.spring.remoting.RemotingParser; +import io.seata.spring.remoting.parser.DefaultRemotingParser; import io.seata.spring.util.SpringProxyUtils; +import org.aopalliance.intercept.MethodInterceptor; import org.springframework.aop.framework.ProxyFactory; import org.springframework.context.ApplicationContext; -import java.lang.reflect.Method; - /** * parser TCC bean * @@ -54,7 +53,7 @@ public static boolean isTccAutoProxy(Object bean, String beanName, ApplicationCo if (isRemotingBean) { if (remotingDesc != null && remotingDesc.getProtocol() == Protocols.IN_JVM) { //LocalTCC - return isTccProxyTargetBean(remotingDesc); + return DefaultTransactionAutoProxy.get().isTransactionAutoProxy(beanName, remotingDesc); } else { // sofa:reference / dubbo:reference, factory bean return false; @@ -64,12 +63,12 @@ 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); } } } @@ -101,48 +100,13 @@ protected static boolean isRemotingFactoryBean(Object bean, String beanName, return parserRemotingServiceInfo(factoryBean, beanName); } - /** - * is TCC proxy-bean/target-bean: LocalTCC , the proxy bean of sofa:reference/dubbo:reference - * - * @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 tccInterfaceClazz = remotingDesc.getInterfaceClass(); - Method[] methods = tccInterfaceClazz.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 applicationContext applicationContext */ - public static void initTccFenceCleanTask(RemotingDesc remotingDesc, ApplicationContext applicationContext) { + public static void initTccFenceCleanTask(RemotingDesc remotingDesc, ApplicationContext applicationContext, boolean useFence) { if (remotingDesc == null) { return; } @@ -151,17 +115,10 @@ public static void initTccFenceCleanTask(RemotingDesc remotingDesc, ApplicationC if (tccFenceConfig == null || tccFenceConfig.getInitialized().get()) { return; } - Class tccInterfaceClazz = remotingDesc.getInterfaceClass(); - Method[] methods = tccInterfaceClazz.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 (useFence && tccFenceConfig.getInitialized().compareAndSet(false, true)) { + // init tcc fence clean task if enable useTccFence + tccFenceConfig.initCleanTask(); } } } @@ -199,7 +156,7 @@ public static RemotingDesc getRemotingDesc(String beanName) { * @param actionInterceptor * @return */ - 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); diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccAnnotationProcessor.java b/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java similarity index 76% rename from tcc/src/main/java/io/seata/rm/tcc/interceptor/TccAnnotationProcessor.java rename to spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java index 6ea40955cff..0bae6c992e5 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccAnnotationProcessor.java +++ b/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.rm.tcc.interceptor; +package io.seata.spring.interceptor; -import io.seata.rm.tcc.api.TwoPhaseBusinessAction; -import io.seata.rm.tcc.remoting.RemotingDesc; +import io.seata.spring.autoproxy.DefaultTransactionAutoProxy; +import io.seata.spring.autoproxy.IsTransactionProxyResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; @@ -25,13 +25,8 @@ 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; -import java.util.List; -import java.util.Objects; -import java.util.Set; +import java.util.*; /** * An annotation adapter for TCC @@ -97,17 +92,13 @@ public void addTccAdvise(Object bean, String beanName, Field field, Class interf if (fieldValue == null) { return; } - for (Method method : field.getType().getMethods()) { - if (!Modifier.isStatic(method.getModifiers()) && (method.isAnnotationPresent(TwoPhaseBusinessAction.class))) { - RemotingDesc remotingDesc = new RemotingDesc(); - remotingDesc.setInterfaceClass(interfaceClass); - - TccActionInterceptor actionInterceptor = new TccActionInterceptor(remotingDesc); - Object proxyBean = TCCBeanParserUtils.createProxy(interfaceClass, 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 = TCCBeanParserUtils.createProxy(interfaceClass, 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() + "]"); } } diff --git a/spring/src/main/java/io/seata/spring/interceptor/TwoPhaseBusinessActionParam.java b/spring/src/main/java/io/seata/spring/interceptor/TwoPhaseBusinessActionParam.java new file mode 100644 index 00000000000..c7249700cb1 --- /dev/null +++ b/spring/src/main/java/io/seata/spring/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.spring.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 useFence; + + 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 getUseFence() { + return useFence; + } + + public void setUseFence(Boolean useFence) { + this.useFence = useFence; + } + + 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; + } +} diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/Protocols.java b/spring/src/main/java/io/seata/spring/remoting/Protocols.java similarity index 96% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/Protocols.java rename to spring/src/main/java/io/seata/spring/remoting/Protocols.java index 3d38f71e82a..a1048f494ff 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/Protocols.java +++ b/spring/src/main/java/io/seata/spring/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.spring.remoting; /** * remoting protocols enum diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingDesc.java b/spring/src/main/java/io/seata/spring/remoting/RemotingDesc.java similarity index 99% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingDesc.java rename to spring/src/main/java/io/seata/spring/remoting/RemotingDesc.java index df91bad93b0..ef57d8814b6 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingDesc.java +++ b/spring/src/main/java/io/seata/spring/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.spring.remoting; /** * remoting bean info diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/RemotingParser.java similarity index 98% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java rename to spring/src/main/java/io/seata/spring/remoting/RemotingParser.java index 2ff32ca4980..bbed5d2e101 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java +++ b/spring/src/main/java/io/seata/spring/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.spring.remoting; import io.seata.common.exception.FrameworkException; diff --git a/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java b/spring/src/main/java/io/seata/spring/remoting/TwoPhaseResult.java similarity index 98% rename from tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java rename to spring/src/main/java/io/seata/spring/remoting/TwoPhaseResult.java index 54b4c3139ee..7dbab5c81e6 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java +++ b/spring/src/main/java/io/seata/spring/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.spring.remoting; import io.seata.common.util.StringUtils; diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/AbstractedRemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/AbstractedRemotingParser.java similarity index 91% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/AbstractedRemotingParser.java rename to spring/src/main/java/io/seata/spring/remoting/parser/AbstractedRemotingParser.java index 153326688ea..2bc018772ee 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/AbstractedRemotingParser.java +++ b/spring/src/main/java/io/seata/spring/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.spring.remoting.parser; import io.seata.common.exception.FrameworkException; -import io.seata.rm.tcc.remoting.RemotingParser; +import io.seata.spring.remoting.RemotingParser; /** * The type Abstracted remoting parser. diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DefaultRemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/DefaultRemotingParser.java similarity index 70% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DefaultRemotingParser.java rename to spring/src/main/java/io/seata/spring/remoting/parser/DefaultRemotingParser.java index aebd385bb02..d140295186c 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DefaultRemotingParser.java +++ b/spring/src/main/java/io/seata/spring/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.spring.remoting.parser; + +import io.seata.common.exception.FrameworkException; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.util.CollectionUtils; +import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.rm.tcc.api.BusinessActionContextParameter; +import io.seata.spring.interceptor.ActionContextUtil; +import io.seata.spring.remoting.RemotingDesc; +import io.seata.spring.remoting.RemotingParser; 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 * @@ -169,42 +166,7 @@ public RemotingDesc parserRemotingServiceInfo(Object bean, String beanName, Remo return null; } remotingServiceMap.put(beanName, remotingBeanDesc); - - Class interfaceClass = remotingBeanDesc.getInterfaceClass(); - Method[] methods = interfaceClass.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(interfaceClass.getMethod(twoPhaseBusinessAction.commitMethod(), - twoPhaseBusinessAction.commitArgsClasses())); - tccResource.setRollbackMethodName(twoPhaseBusinessAction.rollbackMethod()); - tccResource.setRollbackMethod(interfaceClass.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]; /* diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboRemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/DubboRemotingParser.java similarity index 95% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboRemotingParser.java rename to spring/src/main/java/io/seata/spring/remoting/parser/DubboRemotingParser.java index c47f0342c59..673f10fa431 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/DubboRemotingParser.java +++ b/spring/src/main/java/io/seata/spring/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.spring.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.spring.remoting.Protocols; +import io.seata.spring.remoting.RemotingDesc; /** * dubbo remoting bean parsing diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/HSFRemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/HSFRemotingParser.java similarity index 97% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/HSFRemotingParser.java rename to spring/src/main/java/io/seata/spring/remoting/parser/HSFRemotingParser.java index 7dd4a8611f3..5fbb4e7aaf5 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/HSFRemotingParser.java +++ b/spring/src/main/java/io/seata/spring/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.spring.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.spring.remoting.Protocols; +import io.seata.spring.remoting.RemotingDesc; /** * HSF Remote Bean Parser diff --git a/spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java new file mode 100644 index 00000000000..0997f1f021b --- /dev/null +++ b/spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java @@ -0,0 +1,85 @@ +/* + * 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.spring.remoting.parser; + +import io.seata.common.exception.FrameworkException; +import io.seata.common.util.ReflectionUtil; +import io.seata.spring.annotation.LocalService; +import io.seata.spring.remoting.Protocols; +import io.seata.spring.remoting.RemotingDesc; + +import java.util.Set; + +/** + * Local Service Remote Bean Parser + * + * @author ruishansun + */ +public class LocalServiceRemotingParser extends AbstractedRemotingParser { + + @Override + public boolean isReference(Object bean, String beanName) { + return isLocalService(bean); + } + + @Override + public boolean isService(Object bean, String beanName) { + return isLocalService(bean); + } + + @Override + public RemotingDesc getServiceDesc(Object bean, String beanName) throws FrameworkException { + if (!this.isRemoting(bean, beanName)) { + return null; + } + RemotingDesc remotingDesc = new RemotingDesc(); + remotingDesc.setReference(true); + remotingDesc.setProtocol(Protocols.IN_JVM); + Class classType = bean.getClass(); + Set> interfaceClasses = ReflectionUtil.getInterfaces(classType); + for (Class interClass : interfaceClasses) { + if (interClass.isAnnotationPresent(LocalService.class)) { + remotingDesc.setInterfaceClassName(interClass.getName()); + remotingDesc.setInterfaceClass(interClass); + remotingDesc.setTargetBean(bean); + return remotingDesc; + } + } + throw new FrameworkException("Couldn't parser any Remoting info"); + } + + @Override + public short getProtocol() { + return Protocols.IN_JVM; + } + + /** + * Determine whether there is an annotation {@link LocalService} + * + * @param bean the bean + * @return boolean + */ + private boolean isLocalService(Object bean) { + Class classType = bean.getClass(); + Set> interfaceClasses = ReflectionUtil.getInterfaces(classType); + for (Class interClass : interfaceClasses) { + if (interClass.isAnnotationPresent(LocalService.class)) { + return true; + } + } + return false; + } +} diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/SofaRpcRemotingParser.java similarity index 95% rename from tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java rename to spring/src/main/java/io/seata/spring/remoting/parser/SofaRpcRemotingParser.java index 6673be5fe61..4ea2d825117 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java +++ b/spring/src/main/java/io/seata/spring/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.spring.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.spring.remoting.Protocols; +import io.seata.spring.remoting.RemotingDesc; /** * sofa-rpc remoting bean parsing diff --git a/spring/src/main/resources/META-INF/services/io.seata.spring.remoting.RemotingParser b/spring/src/main/resources/META-INF/services/io.seata.spring.remoting.RemotingParser new file mode 100644 index 00000000000..491f15d2119 --- /dev/null +++ b/spring/src/main/resources/META-INF/services/io.seata.spring.remoting.RemotingParser @@ -0,0 +1,5 @@ +io.seata.spring.remoting.parser.DubboRemotingParser +io.seata.rm.tcc.remoting.parser.LocalTCCRemotingParser +io.seata.spring.remoting.parser.SofaRpcRemotingParser +io.seata.spring.remoting.parser.HSFRemotingParser +io.seata.spring.remoting.parser.LocalServiceRemotingParser \ No newline at end of file diff --git a/tcc/pom.xml b/tcc/pom.xml index 8086afaa5e0..b6bde844468 100644 --- a/tcc/pom.xml +++ b/tcc/pom.xml @@ -44,14 +44,6 @@ seata-spring ${project.version} - - org.springframework - spring-jdbc - - - com.alibaba - fastjson - 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 2aa14a234b3..e205807ba6c 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java +++ b/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java @@ -32,7 +32,9 @@ import io.seata.core.model.Resource; import io.seata.rm.AbstractResourceManager; import io.seata.rm.tcc.api.BusinessActionContext; -import io.seata.rm.tcc.api.ModeType; +import io.seata.rm.tcc.api.BusinessActionContextUtil; +import io.seata.spring.fence.TCCFenceHandler; +import io.seata.spring.remoting.TwoPhaseResult; /** * TCC resource manager @@ -96,15 +98,8 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI } try { //BusinessActionContext - BusinessActionContext businessActionContext = getBusinessActionContext(xid, branchId, resourceId, + BusinessActionContext businessActionContext = BusinessActionContextUtil.getBusinessActionContext(xid, branchId, resourceId, applicationData); - - // if the TwoPhaseBusinessAction annotation's mode is SAGA, cancel the commit - ModeType modeType = (ModeType) businessActionContext.getActionContext(Constants.MODE_TYPE); - if (modeType != null && modeType.equals(ModeType.SAGA)) { - LOGGER.info("TwoPhaseBusinessAction's ModeType is SAGA, cancel the commit, xid: {}, branchId: {}, resourceId: {}", xid, branchId, resourceId); - return BranchStatus.PhaseTwo_Committed; - } Object[] args = this.getTwoPhaseCommitArgs(tccResource, businessActionContext); Object ret; @@ -162,7 +157,7 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc } try { //BusinessActionContext - BusinessActionContext businessActionContext = getBusinessActionContext(xid, branchId, resourceId, + BusinessActionContext businessActionContext = BusinessActionContextUtil.getBusinessActionContext(xid, branchId, resourceId, applicationData); Object[] args = this.getTwoPhaseRollbackArgs(tccResource, businessActionContext); Object ret; @@ -196,33 +191,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 @@ -232,7 +200,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); } /** @@ -244,19 +212,7 @@ 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 diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/ModeType.java b/tcc/src/main/java/io/seata/rm/tcc/api/ModeType.java deleted file mode 100644 index 557606c935c..00000000000 --- a/tcc/src/main/java/io/seata/rm/tcc/api/ModeType.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.seata.rm.tcc.api; - -/** - * The enum ModeType - * - * @author ruishan - */ -public enum ModeType { - - /** - * TCC Mode - */ - TCC, - /** - * SAGA Mode - */ - SAGA; -} 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 40e4e481e58..28319d1baff 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 @@ -89,11 +89,4 @@ * @return the Class[] */ Class[] rollbackArgsClasses() default {BusinessActionContext.class}; - - /** - * Define TCC or SAGA mode - * - * @return the mode - */ - ModeType modeType() default ModeType.TCC; } 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 index 72d95213e01..3fb930c6fab 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java +++ b/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java @@ -15,11 +15,18 @@ */ package io.seata.rm.tcc.autoproxy; -import io.seata.rm.tcc.interceptor.TCCBeanParserUtils; +import io.seata.common.exception.FrameworkException; +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.spring.autoproxy.IsTransactionProxyResult; import io.seata.spring.autoproxy.TransactionAutoProxy; -import org.aopalliance.intercept.MethodInterceptor; -import org.springframework.context.ApplicationContext; +import io.seata.spring.remoting.Protocols; +import io.seata.spring.remoting.RemotingDesc; +import io.seata.spring.remoting.parser.DefaultRemotingParser; + +import java.lang.reflect.Method; /** * the tcc implements of TransactionAutoProxy @@ -28,14 +35,95 @@ */ 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 MethodInterceptor isTransactionAutoProxy(Object bean, String beanName, ApplicationContext applicationContext) { - if (TCCBeanParserUtils.isTccAutoProxy(bean, beanName, applicationContext)) { - // 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 - return new TccActionInterceptor(TCCBeanParserUtils.getRemotingDesc(beanName)); + public IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remotingDesc) { + if (remotingDesc == null) { + return new IsTransactionProxyResult(); + } + //check if it is TCC bean + boolean isTccClazz = false; + boolean userFence = false; + Class tccInterfaceClazz = remotingDesc.getInterfaceClass(); + Method[] methods = tccInterfaceClazz.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(); + } + short protocols = remotingDesc.getProtocol(); + //LocalTCC + if (Protocols.IN_JVM == protocols) { + this.registryResource(remotingDesc); + //in jvm TCC bean , AOP + IsTransactionProxyResult result = new IsTransactionProxyResult(); + result.setProxyTargetBean(true); + result.setUseFence(userFence); + result.setMethodInterceptor(new TccActionInterceptor(remotingDesc)); + return result; + } + // sofa:reference / dubbo:reference, AOP + if (remotingDesc.isReference()) { + this.registryResource(remotingDesc); + IsTransactionProxyResult result = new IsTransactionProxyResult(); + result.setProxyTargetBean(true); + result.setUseFence(userFence); + result.setMethodInterceptor(new TccActionInterceptor(remotingDesc)); + return result; + } else { + return new IsTransactionProxyResult(); + } + } + + private void registryResource(RemotingDesc remotingDesc) { + if (!remotingDesc.isReference()) { + try { + Class interfaceClass = remotingDesc.getInterfaceClass(); + Method[] methods = interfaceClass.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(interfaceClass.getMethod(twoPhaseBusinessAction.commitMethod(), + twoPhaseBusinessAction.commitArgsClasses())); + tccResource.setRollbackMethodName(twoPhaseBusinessAction.rollbackMethod()); + tccResource.setRollbackMethod(interfaceClass.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"); + } } - return null; } } diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptor.java b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptor.java index e2183945dcd..28ef3bd2f82 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptor.java +++ b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptor.java @@ -15,9 +15,7 @@ */ package io.seata.rm.tcc.interceptor; -import java.lang.reflect.Method; -import javax.annotation.Nullable; - +import io.seata.common.Constants; import io.seata.common.DefaultValues; import io.seata.config.ConfigurationChangeEvent; import io.seata.config.ConfigurationChangeListener; @@ -26,9 +24,9 @@ import io.seata.core.context.RootContext; import io.seata.core.model.BranchType; import io.seata.rm.tcc.api.TwoPhaseBusinessAction; -import io.seata.rm.tcc.remoting.RemotingDesc; -import io.seata.spring.util.DubboUtil; -import io.seata.spring.util.SpringProxyUtils; +import io.seata.spring.interceptor.ActionInterceptorHandler; +import io.seata.spring.interceptor.TwoPhaseBusinessActionParam; +import io.seata.spring.remoting.RemotingDesc; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.slf4j.Logger; @@ -36,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; @@ -50,7 +52,10 @@ public class TccActionInterceptor implements MethodInterceptor, ConfigurationCha private static final Logger LOGGER = LoggerFactory.getLogger(TccActionInterceptor.class); private static final int ORDER_NUM = ConfigurationFactory.getInstance().getInt(TCC_ACTION_INTERCEPTOR_ORDER, DefaultValues.TCC_ACTION_INTERCEPTOR_ORDER); - + + /** + * TODO singleTone? + */ private ActionInterceptorHandler actionInterceptorHandler = new ActionInterceptorHandler(); private volatile boolean disable = ConfigurationFactory.getInstance().getBoolean( @@ -82,7 +87,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) { @@ -95,8 +100,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.setUseFence(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_TCC_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 @@ -112,58 +129,6 @@ 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 interfaceType = null; - try { - if (remotingDesc == null) { - interfaceType = getProxyInterface(invocation.getThis()); - } else { - interfaceType = remotingDesc.getInterfaceClass(); - } - if (interfaceType == null && remotingDesc != null && remotingDesc.getInterfaceClassName() != null) { - interfaceType = Class.forName(remotingDesc.getInterfaceClassName(), true, - Thread.currentThread().getContextClassLoader()); - } - if (interfaceType == null) { - return invocation.getMethod(); - } - return interfaceType.getMethod(invocation.getMethod().getName(), - invocation.getMethod().getParameterTypes()); - } catch (NoSuchMethodException e) { - if (interfaceType != null && !"toString".equals(invocation.getMethod().getName())) { - LOGGER.warn("no such method '{}' from interface {}", invocation.getMethod().getName(), interfaceType.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())) { 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 c1a36c8b9ec..a16b203c304 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 @@ -20,8 +20,9 @@ import io.seata.common.exception.FrameworkException; import io.seata.common.util.ReflectionUtil; import io.seata.rm.tcc.api.LocalTCC; -import io.seata.rm.tcc.remoting.Protocols; -import io.seata.rm.tcc.remoting.RemotingDesc; +import io.seata.spring.remoting.Protocols; +import io.seata.spring.remoting.RemotingDesc; +import io.seata.spring.remoting.parser.AbstractedRemotingParser; /** * local tcc bean parsing 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/interceptor/ActionInterceptorHandlerTest.java b/tcc/src/test/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandlerTest.java index 1fb8f1b5fb8..f3ae613f2c2 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 @@ -18,6 +18,7 @@ import io.seata.rm.tcc.TccAction; import io.seata.rm.tcc.TccParam; import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.spring.interceptor.ActionInterceptorHandler; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; 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..13f9ae38e48 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 @@ -17,6 +17,7 @@ import io.seata.rm.tcc.TccParam; import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.spring.remoting.parser.DefaultRemotingParser; 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 { 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 f8cae88b070..87454ce64ed 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 @@ -17,7 +17,7 @@ import io.seata.rm.tcc.TccAction; import io.seata.rm.tcc.TccActionImpl; -import io.seata.rm.tcc.remoting.RemotingDesc; +import io.seata.spring.remoting.RemotingDesc; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; From 475ebdb1970a05bc2e4a95d04291c6a4e15ae898 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Wed, 15 Jun 2022 14:26:47 +0800 Subject: [PATCH 06/24] fix saga module problem --- pom.xml | 1 - saga/{anotation-mode => annotation-mode}/pom.xml | 9 ++------- .../main/java/io/seata/saga/api/SagaTransactional.java | 0 .../seata/saga/autoproxy/SagaTransactionAutoProxy.java | 0 .../io/seata/saga/interceptor/SagaActionInterceptor.java | 0 saga/pom.xml | 2 +- 6 files changed, 3 insertions(+), 9 deletions(-) rename saga/{anotation-mode => annotation-mode}/pom.xml (81%) rename saga/{anotation-mode => annotation-mode}/src/main/java/io/seata/saga/api/SagaTransactional.java (100%) rename saga/{anotation-mode => annotation-mode}/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java (100%) rename saga/{anotation-mode => annotation-mode}/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java (100%) diff --git a/pom.xml b/pom.xml index b454f19a2f8..c7bf5287b5b 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,6 @@ sqlparser server ext/apm-seata-skywalking-plugin - anotation-mode diff --git a/saga/anotation-mode/pom.xml b/saga/annotation-mode/pom.xml similarity index 81% rename from saga/anotation-mode/pom.xml rename to saga/annotation-mode/pom.xml index 4f96e62ceb5..51ebc140fb0 100644 --- a/saga/anotation-mode/pom.xml +++ b/saga/annotation-mode/pom.xml @@ -8,13 +8,8 @@ ${revision} 4.0.0 - - anotation-mode - - - 8 - 8 - + seata-saga-annotation-mode ${project.version} + annotation-mode diff --git a/saga/anotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java b/saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java similarity index 100% rename from saga/anotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java rename to saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java diff --git a/saga/anotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java b/saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java similarity index 100% rename from saga/anotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java rename to saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java diff --git a/saga/anotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java b/saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java similarity index 100% rename from saga/anotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java rename to saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java diff --git a/saga/pom.xml b/saga/pom.xml index 3b0ee1108e3..dd8c0361f97 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -35,7 +35,7 @@ seata-saga-rm seata-saga-tm seata-saga-engine-store - anotation-mode + annotation-mode From b6c271ef1affaf11f84b9190f7e9bfc6595fee3f Mon Sep 17 00:00:00 2001 From: ruishansun Date: Wed, 15 Jun 2022 14:57:21 +0800 Subject: [PATCH 07/24] avoid use '.*' import --- .../main/java/io/seata/spring/annotation/LocalService.java | 6 +++++- .../io/seata/spring/interceptor/TccAnnotationProcessor.java | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/spring/src/main/java/io/seata/spring/annotation/LocalService.java b/spring/src/main/java/io/seata/spring/annotation/LocalService.java index e0ea6b31611..d2ac7db7897 100644 --- a/spring/src/main/java/io/seata/spring/annotation/LocalService.java +++ b/spring/src/main/java/io/seata/spring/annotation/LocalService.java @@ -17,7 +17,11 @@ import io.seata.spring.remoting.parser.LocalServiceRemotingParser; -import java.lang.annotation.*; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; /** * Local transaction bean annotation, add on the TCC/SAGA interface diff --git a/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java b/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java index 0bae6c992e5..45ebfd2f2e8 100644 --- a/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java +++ b/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java @@ -26,7 +26,11 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; /** * An annotation adapter for TCC From f2e32d34c65639bc33feb874d3f2b6a30a65a334 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Wed, 15 Jun 2022 15:11:14 +0800 Subject: [PATCH 08/24] fix check style --- .../io/seata/spring/interceptor/TccAnnotationProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java b/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java index 45ebfd2f2e8..0d9a812815e 100644 --- a/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java +++ b/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java @@ -98,7 +98,7 @@ public void addTccAdvise(Object bean, String beanName, Field field, Class interf } IsTransactionProxyResult isProxyTargetBeanResult = DefaultTransactionAutoProxy.get().getIsProxyTargetBeanResult(beanName); - if(isProxyTargetBeanResult.isProxyTargetBean()) { + if (isProxyTargetBeanResult.isProxyTargetBean()) { Object proxyBean = TCCBeanParserUtils.createProxy(interfaceClass, fieldValue, isProxyTargetBeanResult.getMethodInterceptor()); field.setAccessible(true); field.set(bean, proxyBean); From 9af0ee1f5f8bd27be7baa0554f835a07d1c139bb Mon Sep 17 00:00:00 2001 From: ruishansun Date: Wed, 15 Jun 2022 15:17:24 +0800 Subject: [PATCH 09/24] fix check style --- .../java/io/seata/rm/tcc/TCCResourceManager.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) 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 e205807ba6c..43c60a67853 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java +++ b/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java @@ -15,17 +15,9 @@ */ 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; @@ -36,6 +28,11 @@ import io.seata.spring.fence.TCCFenceHandler; import io.seata.spring.remoting.TwoPhaseResult; +import java.lang.reflect.Method; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** * TCC resource manager * From 7d30bdb3f97187586b00916f875256c2498fc89e Mon Sep 17 00:00:00 2001 From: ruishansun Date: Wed, 15 Jun 2022 15:28:03 +0800 Subject: [PATCH 10/24] fix check style --- .../seata/saga/rm/SagaAnnotationResource.java | 15 ++++++++ .../io/seata/saga/rm/SagaResourceManager.java | 35 ++++++++++--------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaAnnotationResource.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaAnnotationResource.java index a4e7c2e487b..d49e389a633 100644 --- a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaAnnotationResource.java +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaAnnotationResource.java @@ -1,3 +1,18 @@ +/* + * 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.saga.rm; import java.lang.reflect.Method; diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java index 88947e90e26..8842a951212 100644 --- a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java @@ -69,7 +69,7 @@ public SagaResourceManager() { */ @Override public void registerResource(Resource resource) { - SagaResource sagaResource = (SagaResource)resource; + SagaResource sagaResource = (SagaResource) resource; sagaResourceCache.put(sagaResource.getResourceId(), sagaResource); super.registerResource(sagaResource); } @@ -95,28 +95,28 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI String applicationData) throws TransactionException { // Saga annotation mode - SagaResource sagaResource = (SagaResource)sagaResourceCache.get(resourceId); + SagaResource sagaResource = (SagaResource) sagaResourceCache.get(resourceId); if (sagaResource == null) { throw new ShouldNeverHappenException(String.format("Saga resource is not exist, resourceId: %s", resourceId)); } - if(sagaResource.isUseSagaAnnotationMode()) { + if (sagaResource.isUseSagaAnnotationMode()) { return BranchStatus.PhaseTwo_Committed; } - + // Saga state machine mode try { StateMachineInstance machineInstance = StateMachineEngineHolder.getStateMachineEngine().forward(xid, null); if (ExecutionStatus.SU.equals(machineInstance.getStatus()) - && machineInstance.getCompensationStatus() == null) { + && machineInstance.getCompensationStatus() == null) { return BranchStatus.PhaseTwo_Committed; } else if (ExecutionStatus.SU.equals(machineInstance.getCompensationStatus())) { return BranchStatus.PhaseTwo_Rollbacked; } else if (ExecutionStatus.FA.equals(machineInstance.getCompensationStatus()) || ExecutionStatus.UN.equals( - machineInstance.getCompensationStatus())) { + machineInstance.getCompensationStatus())) { return BranchStatus.PhaseTwo_RollbackFailed_Retryable; } else if (ExecutionStatus.FA.equals(machineInstance.getStatus()) - && machineInstance.getCompensationStatus() == null) { + && machineInstance.getCompensationStatus() == null) { return BranchStatus.PhaseOne_Failed; } @@ -149,11 +149,11 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc String applicationData) throws TransactionException { // Saga annotation mode - SagaResource sagaResource = (SagaResource)sagaResourceCache.get(resourceId); + SagaResource sagaResource = (SagaResource) sagaResourceCache.get(resourceId); if (sagaResource == null) { throw new ShouldNeverHappenException(String.format("Saga resource is not exist, resourceId: %s", resourceId)); } - if(sagaResource.isUseSagaAnnotationMode()) { + if (sagaResource.isUseSagaAnnotationMode()) { return this.sagaCompensateBranch(xid, branchId, resourceId, applicationData, (SagaAnnotationResource) sagaResource); } @@ -164,14 +164,14 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc return BranchStatus.PhaseTwo_Rollbacked; } if (RecoverStrategy.Forward.equals(stateMachineInstance.getStateMachine().getRecoverStrategy()) - && (GlobalStatus.TimeoutRollbacking.name().equals(applicationData) - || GlobalStatus.TimeoutRollbackRetrying.name().equals(applicationData))) { + && (GlobalStatus.TimeoutRollbacking.name().equals(applicationData) + || GlobalStatus.TimeoutRollbackRetrying.name().equals(applicationData))) { LOGGER.warn("Retry by custom recover strategy [Forward] on timeout, SAGA global[{}]", xid); return BranchStatus.PhaseTwo_CommitFailed_Retryable; } stateMachineInstance = StateMachineEngineHolder.getStateMachineEngine().compensate(xid, - null); + null); if (ExecutionStatus.SU.equals(stateMachineInstance.getCompensationStatus())) { return BranchStatus.PhaseTwo_Rollbacked; } @@ -187,7 +187,7 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc } return BranchStatus.PhaseTwo_RollbackFailed_Retryable; } - + private BranchStatus sagaCompensateBranch(String xid, long branchId, String resourceId, String applicationData, SagaAnnotationResource sagaAnnotationResource) { if (sagaAnnotationResource == null) { throw new ShouldNeverHappenException(String.format("Saga annotation resource is not exist, resourceId: %s", resourceId)); @@ -202,7 +202,7 @@ private BranchStatus sagaCompensateBranch(String xid, long branchId, String reso BusinessActionContext businessActionContext = BusinessActionContextUtil.getBusinessActionContext(xid, branchId, resourceId, applicationData); Object[] args = this.getTwoPhaseCompensationArgs(sagaAnnotationResource, businessActionContext); - + Object ret; boolean result; // add idempotent and anti hanging @@ -217,9 +217,9 @@ private BranchStatus sagaCompensateBranch(String xid, long branchId, String reso ret = compensationMethod.invoke(targetSagaBean, args); if (ret != null) { if (ret instanceof TwoPhaseResult) { - result = ((TwoPhaseResult)ret).isSuccess(); + result = ((TwoPhaseResult) ret).isSuccess(); } else { - result = (boolean)ret; + result = (boolean) ret; } } else { result = true; @@ -236,8 +236,9 @@ private BranchStatus sagaCompensateBranch(String xid, long branchId, String reso /** * get phase two compensate method's args + * * @param sagaAnnotationResource sagaAnnotationResource - * @param businessActionContext businessActionContext + * @param businessActionContext businessActionContext * @return args */ private Object[] getTwoPhaseCompensationArgs(SagaAnnotationResource sagaAnnotationResource, BusinessActionContext businessActionContext) { From 114737b488975ca8d7fb0c7d0ce2b3099002ce76 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Wed, 15 Jun 2022 15:41:34 +0800 Subject: [PATCH 11/24] fix check style --- .../src/main/java/io/seata/saga/api/SagaTransactional.java | 6 +++++- .../io/seata/saga/autoproxy/SagaTransactionAutoProxy.java | 5 +++-- .../spring/interceptor/TwoPhaseBusinessActionParam.java | 2 +- .../spring/remoting/parser/LocalServiceRemotingParser.java | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java b/saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java index 1bfbd09b791..edda2fdc17f 100644 --- a/saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java +++ b/saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java @@ -20,7 +20,11 @@ import io.seata.rm.tcc.api.BusinessActionContextUtil; import io.seata.saga.interceptor.SagaActionInterceptor; -import java.lang.annotation.*; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; /** * SAGA annotation. diff --git a/saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java b/saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java index 033cf1ecd3a..d08fc2f892b 100644 --- a/saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java +++ b/saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java @@ -34,7 +34,7 @@ * @author ruishansun */ public class SagaTransactionAutoProxy implements TransactionAutoProxy { - + @Override public IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remotingDesc) { @@ -46,7 +46,7 @@ public IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remoti Method[] methods = sagaInterfaceClazz.getMethods(); for (Method method : methods) { SagaTransactional sagaTransactional = method.getAnnotation(SagaTransactional.class); - if(sagaTransactional != null && (Protocols.IN_JVM == remotingDesc.getProtocol() || remotingDesc.isReference())) { + if (sagaTransactional != null && (Protocols.IN_JVM == remotingDesc.getProtocol() || remotingDesc.isReference())) { this.registryResource(remotingDesc); IsTransactionProxyResult result = new IsTransactionProxyResult(); result.setProxyTargetBean(true); @@ -60,6 +60,7 @@ public IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remoti /** * register saga resource + * * @param remotingDesc the remotingDesc */ private void registryResource(RemotingDesc remotingDesc) { diff --git a/spring/src/main/java/io/seata/spring/interceptor/TwoPhaseBusinessActionParam.java b/spring/src/main/java/io/seata/spring/interceptor/TwoPhaseBusinessActionParam.java index c7249700cb1..b7aba50832e 100644 --- a/spring/src/main/java/io/seata/spring/interceptor/TwoPhaseBusinessActionParam.java +++ b/spring/src/main/java/io/seata/spring/interceptor/TwoPhaseBusinessActionParam.java @@ -20,7 +20,7 @@ import java.util.Map; /** - * The two phase business action parameters. + * The two phase business action parameters. * * @author ruishansun */ diff --git a/spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java index 0997f1f021b..3aa0ca07fbd 100644 --- a/spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java +++ b/spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java @@ -29,7 +29,7 @@ * @author ruishansun */ public class LocalServiceRemotingParser extends AbstractedRemotingParser { - + @Override public boolean isReference(Object bean, String beanName) { return isLocalService(bean); From 4e06ffcb1844de22c476eda71027d4b3911b4495 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Wed, 15 Jun 2022 15:52:48 +0800 Subject: [PATCH 12/24] fix check style --- .../properties/client/RmProperties.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/RmProperties.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/RmProperties.java index f680d5842b7..b01c860eb52 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/RmProperties.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/properties/client/RmProperties.java @@ -19,7 +19,19 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; -import static io.seata.common.DefaultValues.*; +import static io.seata.common.DefaultValues.DEFAULT_CLIENT_ASYNC_COMMIT_BUFFER_LIMIT; +import static io.seata.common.DefaultValues.DEFAULT_CLIENT_REPORT_RETRY_COUNT; +import static io.seata.common.DefaultValues.DEFAULT_CLIENT_REPORT_SUCCESS_ENABLE; +import static io.seata.common.DefaultValues.DEFAULT_CLIENT_SAGA_BRANCH_REGISTER_ENABLE; +import static io.seata.common.DefaultValues.DEFAULT_CLIENT_SAGA_COMPENSATE_PERSIST_MODE_UPDATE; +import static io.seata.common.DefaultValues.DEFAULT_CLIENT_SAGA_RETRY_PERSIST_MODE_UPDATE; +import static io.seata.common.DefaultValues.DEFAULT_CLIENT_TABLE_META_CHECK_ENABLE; +import static io.seata.common.DefaultValues.DEFAULT_SAGA_JSON_PARSER; +import static io.seata.common.DefaultValues.DEFAULT_TABLE_META_CHECKER_INTERVAL; +import static io.seata.common.DefaultValues.TCC_ACTION_INTERCEPTOR_ORDER; +import static io.seata.common.DefaultValues.SAGA_ACTION_INTERCEPTOR_ORDER; +import static io.seata.common.DefaultValues.DEFAULT_XA_BRANCH_EXECUTION_TIMEOUT; +import static io.seata.common.DefaultValues.DEFAULT_XA_CONNECTION_TWO_PHASE_HOLD_TIMEOUT; import static io.seata.spring.boot.autoconfigure.StarterConstants.CLIENT_RM_PREFIX; /** From 5b0a5b3944d8b021a1278386da983d7689fd48fa Mon Sep 17 00:00:00 2001 From: ruishansun Date: Thu, 16 Jun 2022 09:53:47 +0800 Subject: [PATCH 13/24] fix add SAGA branch type in saga interceptor --- .../java/io/seata/saga/interceptor/SagaActionInterceptor.java | 1 + .../io/seata/spring/annotation/GlobalTransactionScanner.java | 1 + 2 files changed, 2 insertions(+) diff --git a/saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java b/saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java index d3951263341..e6686db02ea 100644 --- a/saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java +++ b/saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java @@ -107,6 +107,7 @@ public Object invoke(@NotNull MethodInvocation invocation) throws Throwable { businessActionParam.setActionName(sagaTransactional.name()); businessActionParam.setDelayReport(false); businessActionParam.setUseFence(true); + businessActionParam.setBranchType(BranchType.SAGA); Map businessActionContextMap = new HashMap<>(4); //the phase two method name businessActionContextMap.put(Constants.COMPENSATION_METHOD, sagaTransactional.compensationMethod()); 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 b211e3aa312..bb632086190 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java @@ -292,6 +292,7 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) IsTransactionProxyResult isTransactionProxyResult = DefaultTransactionAutoProxy.get().getIsProxyTargetBeanResult(beanName); // init tcc fence clean task if enable useTccFence TCCBeanParserUtils.initTccFenceCleanTask(TCCBeanParserUtils.getRemotingDesc(beanName), applicationContext, isTransactionProxyResult.isUseFence()); + //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); From dfffdc87386219634321415a0b7a56cf8d6f81bc Mon Sep 17 00:00:00 2001 From: ruishansun Date: Thu, 16 Jun 2022 10:26:30 +0800 Subject: [PATCH 14/24] fix add SagaTransactionAutoProxy SPI --- .../services/io.seata.spring.autoproxy.TransactionAutoProxy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy b/spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy index a27056a0435..347a93ab9b7 100644 --- a/spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy +++ b/spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy @@ -1 +1,2 @@ -io.seata.rm.tcc.autoproxy.TccTransactionAutoProxy \ No newline at end of file +io.seata.rm.tcc.autoproxy.TccTransactionAutoProxy +io.seata.saga.autoproxy.SagaTransactionAutoProxy \ No newline at end of file From 6b8e7f9d419cd645281b4e1d86b38e12100e68bf Mon Sep 17 00:00:00 2001 From: ruishansun Date: Fri, 17 Jun 2022 16:29:36 +0800 Subject: [PATCH 15/24] add local service remoting parser test. --- .../java/io/seata/rm/saga/SagaAction.java | 49 ++++++++++++ .../java/io/seata/rm/saga/SagaActionImpl.java | 36 +++++++++ .../LocalServiceRemotingParserTest.java | 74 +++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaAction.java create mode 100644 saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaActionImpl.java create mode 100644 saga/annotation-mode/src/test/java/io/seata/rm/saga/remoting/parser/LocalServiceRemotingParserTest.java diff --git a/saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaAction.java b/saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaAction.java new file mode 100644 index 00000000000..c0b788f1ef4 --- /dev/null +++ b/saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaAction.java @@ -0,0 +1,49 @@ +/* + * 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.saga; + +import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.rm.tcc.api.BusinessActionContextParameter; +import io.seata.saga.api.SagaTransactional; +import io.seata.spring.annotation.LocalService; + +/** + * The interface Saga action. + * + * @author ruishansun + */ +@LocalService +public interface SagaAction { + + /** + * Commit boolean. + * + * @param actionContext the action context + * @param a the a + * @return the boolean + */ + @SagaTransactional(name = "sagaActionForTest", compensationMethod = "compensation") + boolean commit(BusinessActionContext actionContext, + @BusinessActionContextParameter("a") int a); + + /** + * Compensation boolean. + * + * @param actionContext the action context + * @return the boolean + */ + boolean compensation(BusinessActionContext actionContext); +} diff --git a/saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaActionImpl.java b/saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaActionImpl.java new file mode 100644 index 00000000000..3f49382e0df --- /dev/null +++ b/saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaActionImpl.java @@ -0,0 +1,36 @@ +/* + * 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.saga; + +import io.seata.rm.tcc.api.BusinessActionContext; + +/** + * The type Saga action impl. + * + * @author ruishansun + */ +public class SagaActionImpl implements SagaAction { + + @Override + public boolean commit(BusinessActionContext actionContext, int a) { + return true; + } + + @Override + public boolean compensation(BusinessActionContext actionContext) { + return true; + } +} diff --git a/saga/annotation-mode/src/test/java/io/seata/rm/saga/remoting/parser/LocalServiceRemotingParserTest.java b/saga/annotation-mode/src/test/java/io/seata/rm/saga/remoting/parser/LocalServiceRemotingParserTest.java new file mode 100644 index 00000000000..80f99affed0 --- /dev/null +++ b/saga/annotation-mode/src/test/java/io/seata/rm/saga/remoting/parser/LocalServiceRemotingParserTest.java @@ -0,0 +1,74 @@ +/* + * 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.saga.remoting.parser; + +import io.seata.rm.saga.SagaAction; +import io.seata.rm.saga.SagaActionImpl; +import io.seata.spring.remoting.RemotingDesc; +import io.seata.spring.remoting.parser.LocalServiceRemotingParser; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * The type Local service remoting parser test. + * + * @author ruishansun + */ +public class LocalServiceRemotingParserTest { + + /** + * The Local service remoting parser. + */ + LocalServiceRemotingParser localServiceRemotingParser = new LocalServiceRemotingParser(); + + /** + * Test service parser. + */ + @Test + public void testServiceParser() { + SagaActionImpl sagaActionImpl = new SagaActionImpl(); + + boolean result = localServiceRemotingParser.isService(sagaActionImpl, "a"); + Assertions.assertTrue(result); + } + + /** + * Test reference parser. + */ + @Test + public void testReferenceParser() { + SagaActionImpl sagaActionImpl = new SagaActionImpl(); + + boolean result = localServiceRemotingParser.isReference(sagaActionImpl, "b"); + Assertions.assertTrue(result); + } + + /** + * Test service desc. + */ + @Test + public void testServiceDesc() { + SagaActionImpl sagaActionImpl = new SagaActionImpl(); + + RemotingDesc remotingDesc = localServiceRemotingParser.getServiceDesc(sagaActionImpl, "c"); + Assertions.assertNotNull(remotingDesc); + + Assertions.assertEquals("io.seata.rm.saga.SagaAction", remotingDesc.getInterfaceClassName()); + Assertions.assertEquals(remotingDesc.getInterfaceClass(), SagaAction.class); + Assertions.assertEquals(remotingDesc.getTargetBean(), sagaActionImpl); + } + +} From 18980496e13b458a35d32b4fa2bfd11d3c442946 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Fri, 17 Jun 2022 17:59:40 +0800 Subject: [PATCH 16/24] add test in spring : local service remoting parser test. --- .../spring/remoting/LocalServiceAction.java | 29 +++++++++++ .../remoting/LocalServiceActionImpl.java | 24 +++++++++ .../LocalServiceRemotingParserTest.java | 51 +++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 spring/src/test/java/io/seata/spring/remoting/LocalServiceAction.java create mode 100644 spring/src/test/java/io/seata/spring/remoting/LocalServiceActionImpl.java create mode 100644 spring/src/test/java/io/seata/spring/remoting/parser/LocalServiceRemotingParserTest.java diff --git a/spring/src/test/java/io/seata/spring/remoting/LocalServiceAction.java b/spring/src/test/java/io/seata/spring/remoting/LocalServiceAction.java new file mode 100644 index 00000000000..e58afa45a47 --- /dev/null +++ b/spring/src/test/java/io/seata/spring/remoting/LocalServiceAction.java @@ -0,0 +1,29 @@ +/* + * 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.spring.remoting; + +import io.seata.spring.annotation.LocalService; + +/** + * The interface local service action. + * + * @author ruishansun + */ +@LocalService +public interface LocalServiceAction { + + +} diff --git a/spring/src/test/java/io/seata/spring/remoting/LocalServiceActionImpl.java b/spring/src/test/java/io/seata/spring/remoting/LocalServiceActionImpl.java new file mode 100644 index 00000000000..75a8cd98b61 --- /dev/null +++ b/spring/src/test/java/io/seata/spring/remoting/LocalServiceActionImpl.java @@ -0,0 +1,24 @@ +/* + * 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.spring.remoting; + +/** + * The interface local service action impl. + * + * @author ruishansun + */ +public class LocalServiceActionImpl implements LocalServiceAction { +} diff --git a/spring/src/test/java/io/seata/spring/remoting/parser/LocalServiceRemotingParserTest.java b/spring/src/test/java/io/seata/spring/remoting/parser/LocalServiceRemotingParserTest.java new file mode 100644 index 00000000000..d6661408174 --- /dev/null +++ b/spring/src/test/java/io/seata/spring/remoting/parser/LocalServiceRemotingParserTest.java @@ -0,0 +1,51 @@ +/* + * 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.spring.remoting.parser; + +import io.seata.spring.remoting.LocalServiceAction; +import io.seata.spring.remoting.LocalServiceActionImpl; +import io.seata.spring.remoting.RemotingDesc; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * The type Local service remoting parser test. + * + * @author ruishansun + */ +public class LocalServiceRemotingParserTest { + + /** + * The Local service remoting parser. + */ + LocalServiceRemotingParser localServiceRemotingParser = new LocalServiceRemotingParser(); + + /** + * Test service desc. + */ + @Test + public void testServiceDesc() { + LocalServiceAction localServiceAction = new LocalServiceActionImpl(); + + RemotingDesc remotingDesc = localServiceRemotingParser.getServiceDesc(localServiceAction, "c"); + Assertions.assertNotNull(remotingDesc); + + Assertions.assertEquals("io.seata.spring.remoting.LocalServiceAction", remotingDesc.getInterfaceClassName()); + Assertions.assertEquals(remotingDesc.getInterfaceClass(), LocalServiceAction.class); + Assertions.assertEquals(remotingDesc.getTargetBean(), localServiceAction); + } + +} From c580b636505b77ff4e8e2c437b105c8ce388cb95 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Fri, 1 Jul 2022 10:40:03 +0800 Subject: [PATCH 17/24] add local service remoting parser test --- .../remoting/NormalServiceActionImpl.java | 4 ++++ .../LocalServiceRemotingParserTest.java | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 spring/src/test/java/io/seata/spring/remoting/NormalServiceActionImpl.java diff --git a/spring/src/test/java/io/seata/spring/remoting/NormalServiceActionImpl.java b/spring/src/test/java/io/seata/spring/remoting/NormalServiceActionImpl.java new file mode 100644 index 00000000000..a497c141513 --- /dev/null +++ b/spring/src/test/java/io/seata/spring/remoting/NormalServiceActionImpl.java @@ -0,0 +1,4 @@ +package io.seata.spring.remoting; + +public class NormalServiceActionImpl { +} diff --git a/spring/src/test/java/io/seata/spring/remoting/parser/LocalServiceRemotingParserTest.java b/spring/src/test/java/io/seata/spring/remoting/parser/LocalServiceRemotingParserTest.java index d6661408174..3dabdb2be87 100644 --- a/spring/src/test/java/io/seata/spring/remoting/parser/LocalServiceRemotingParserTest.java +++ b/spring/src/test/java/io/seata/spring/remoting/parser/LocalServiceRemotingParserTest.java @@ -18,6 +18,8 @@ import io.seata.spring.remoting.LocalServiceAction; import io.seata.spring.remoting.LocalServiceActionImpl; import io.seata.spring.remoting.RemotingDesc; +import io.seata.spring.remoting.Protocols; +import io.seata.spring.remoting.NormalServiceActionImpl; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -48,4 +50,22 @@ public void testServiceDesc() { Assertions.assertEquals(remotingDesc.getTargetBean(), localServiceAction); } + @Test + public void testProtocol() { + Assertions.assertEquals(Protocols.IN_JVM, localServiceRemotingParser.getProtocol()); + } + + @Test + public void testNoRemotingDesc() { + NormalServiceActionImpl normalServiceAction = new NormalServiceActionImpl(); + RemotingDesc remotingDesc = localServiceRemotingParser.getServiceDesc(normalServiceAction, "normalServiceAction"); + Assertions.assertNull(remotingDesc); + } + + @Test + public void testNotIsService() { + NormalServiceActionImpl normalServiceAction = new NormalServiceActionImpl(); + Assertions.assertFalse(localServiceRemotingParser.isService(normalServiceAction, "normalServiceAction")); + } + } From b2ef9900dd391d4e317010e18b6a2a4d4c7af0ba Mon Sep 17 00:00:00 2001 From: ruishansun Date: Fri, 1 Jul 2022 10:54:18 +0800 Subject: [PATCH 18/24] add saga annotation resource manager. rename tcc to saga. --- .../main/java/io/seata/common/Constants.java | 4 +- .../java/io/seata/common/DefaultValues.java | 12 +- .../java/io/seata/core/model/BranchType.java | 5 + .../io/seata/saga/api/SagaTransactional.java | 14 ++ .../autoproxy/SagaTransactionAutoProxy.java | 5 +- .../interceptor/SagaActionInterceptor.java | 14 +- .../java/io/seata/saga/rm/SagaResource.java | 14 +- .../io/seata/saga/rm/SagaResourceManager.java | 88 +---------- .../annotation/RMHandlerSagaAnnotation.java | 39 +++++ .../SagaAnnotationResource.java | 4 +- .../SagaAnnotationResourceManager.java | 146 ++++++++++++++++++ .../io.seata.core.model.ResourceManager | 1 + .../services/io.seata.rm.AbstractRMHandler | 3 +- .../SeataClientEnvironmentPostProcessor.java | 4 +- .../SeataTCCFenceAutoConfiguration.java | 8 +- ...itional-spring-configuration-metadata.json | 4 +- .../rm/tcc/api/BusinessActionContext.java | 15 ++ .../rm/tcc/api/BusinessActionContextUtil.java | 7 +- .../annotation/GlobalTransactionScanner.java | 6 +- .../autoproxy/IsTransactionProxyResult.java | 12 +- ...ceHandler.java => CommonFenceHandler.java} | 106 ++++++------- ...enceConfig.java => CommonFenceConfig.java} | 42 ++--- ...Constant.java => CommonFenceConstant.java} | 6 +- ...ception.java => CommonFenceException.java} | 16 +- .../{TCCFenceDO.java => CommonFenceDO.java} | 6 +- ...CFenceStore.java => CommonFenceStore.java} | 28 ++-- ....java => CommonFenceStoreDataBaseDAO.java} | 66 ++++---- ...oreSqls.java => CommonFenceStoreSqls.java} | 8 +- .../interceptor/ActionInterceptorHandler.java | 26 ++-- .../TwoPhaseBusinessActionParam.java | 10 +- ...cessor.java => TxAnnotationProcessor.java} | 14 +- ...arserUtils.java => TxBeanParserUtils.java} | 34 ++-- .../io/seata/rm/tcc/TCCResourceManager.java | 10 +- .../autoproxy/TccTransactionAutoProxy.java | 4 +- .../tcc/interceptor/TccActionInterceptor.java | 4 +- 35 files changed, 455 insertions(+), 330 deletions(-) create mode 100644 saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/RMHandlerSagaAnnotation.java rename saga/seata-saga-rm/src/main/java/io/seata/saga/rm/{ => annotation}/SagaAnnotationResource.java (97%) create mode 100644 saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResourceManager.java rename spring/src/main/java/io/seata/spring/fence/{TCCFenceHandler.java => CommonFenceHandler.java} (74%) rename spring/src/main/java/io/seata/spring/fence/config/{TCCFenceConfig.java => CommonFenceConfig.java} (76%) rename spring/src/main/java/io/seata/spring/fence/constant/{TCCFenceConstant.java => CommonFenceConstant.java} (92%) rename spring/src/main/java/io/seata/spring/fence/exception/{TCCFenceException.java => CommonFenceException.java} (67%) rename spring/src/main/java/io/seata/spring/fence/store/{TCCFenceDO.java => CommonFenceDO.java} (96%) rename spring/src/main/java/io/seata/spring/fence/store/{TCCFenceStore.java => CommonFenceStore.java} (65%) rename spring/src/main/java/io/seata/spring/fence/store/db/{TCCFenceStoreDataBaseDAO.java => CommonFenceStoreDataBaseDAO.java} (61%) rename spring/src/main/java/io/seata/spring/fence/store/db/sql/{TCCFenceStoreSqls.java => CommonFenceStoreSqls.java} (90%) rename spring/src/main/java/io/seata/spring/interceptor/{TccAnnotationProcessor.java => TxAnnotationProcessor.java} (87%) rename spring/src/main/java/io/seata/spring/interceptor/{TCCBeanParserUtils.java => TxBeanParserUtils.java} (82%) diff --git a/common/src/main/java/io/seata/common/Constants.java b/common/src/main/java/io/seata/common/Constants.java index e688044cc79..4aeb0a42500 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 diff --git a/common/src/main/java/io/seata/common/DefaultValues.java b/common/src/main/java/io/seata/common/DefaultValues.java index 8fe1fed26e0..d0d1b4f41db 100644 --- a/common/src/main/java/io/seata/common/DefaultValues.java +++ b/common/src/main/java/io/seata/common/DefaultValues.java @@ -158,17 +158,17 @@ public interface DefaultValues { 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 diff --git a/core/src/main/java/io/seata/core/model/BranchType.java b/core/src/main/java/io/seata/core/model/BranchType.java index f7ecfa09848..459655ffe57 100644 --- a/core/src/main/java/io/seata/core/model/BranchType.java +++ b/core/src/main/java/io/seata/core/model/BranchType.java @@ -37,6 +37,11 @@ public enum BranchType { * The SAGA. */ SAGA, + + /** + * The SAGA annotation mode + */ + SAGA_ANNOTATION, /** * The XA. diff --git a/saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java b/saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java index edda2fdc17f..a642c9c0353 100644 --- a/saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java +++ b/saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java @@ -58,6 +58,20 @@ */ String compensationMethod() default "compensation"; + /** + * delay branch report while sharing params to saga phase 2 to enhance performance + * + * @return isDelayReport + */ + boolean isDelayReport() default false; + + /** + * whether use common fence (idempotent,non_rollback,suspend) + * + * @return the boolean + */ + boolean useCommonFence() default false; + /** * compensation method's args * diff --git a/saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java b/saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java index d08fc2f892b..3e7bbe19a04 100644 --- a/saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java +++ b/saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java @@ -19,7 +19,7 @@ import io.seata.rm.DefaultResourceManager; import io.seata.saga.api.SagaTransactional; import io.seata.saga.interceptor.SagaActionInterceptor; -import io.seata.saga.rm.SagaAnnotationResource; +import io.seata.saga.rm.annotation.SagaAnnotationResource; import io.seata.spring.autoproxy.IsTransactionProxyResult; import io.seata.spring.autoproxy.TransactionAutoProxy; import io.seata.spring.remoting.Protocols; @@ -50,7 +50,7 @@ public IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remoti this.registryResource(remotingDesc); IsTransactionProxyResult result = new IsTransactionProxyResult(); result.setProxyTargetBean(true); - result.setUseFence(true); + result.setUseCommonFence(sagaTransactional.useCommonFence()); result.setMethodInterceptor(new SagaActionInterceptor(remotingDesc)); return result; } @@ -74,7 +74,6 @@ private void registryResource(RemotingDesc remotingDesc) { SagaTransactional sagaTransactional = m.getAnnotation(SagaTransactional.class); if (sagaTransactional != null) { SagaAnnotationResource sagaAnnotationResource = new SagaAnnotationResource(); - sagaAnnotationResource.setUseSagaAnnotationMode(true); sagaAnnotationResource.setActionName(sagaTransactional.name()); sagaAnnotationResource.setTargetBean(targetBean); sagaAnnotationResource.setCommitMethod(m); diff --git a/saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java b/saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java index e6686db02ea..6c5e1959434 100644 --- a/saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java +++ b/saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java @@ -99,27 +99,27 @@ public Object invoke(@NotNull MethodInvocation invocation) throws Throwable { //save the previous branchType BranchType previousBranchType = RootContext.getBranchType(); //if not SAGA, bind SAGA branchType - if (BranchType.SAGA != previousBranchType) { - RootContext.bindBranchType(BranchType.SAGA); + if (BranchType.SAGA_ANNOTATION != previousBranchType) { + RootContext.bindBranchType(BranchType.SAGA_ANNOTATION); } try { TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam(); businessActionParam.setActionName(sagaTransactional.name()); - businessActionParam.setDelayReport(false); - businessActionParam.setUseFence(true); - businessActionParam.setBranchType(BranchType.SAGA); + businessActionParam.setDelayReport(sagaTransactional.isDelayReport()); + businessActionParam.setUseCommonFence(sagaTransactional.useCommonFence()); + businessActionParam.setBranchType(BranchType.SAGA_ANNOTATION); Map businessActionContextMap = new HashMap<>(4); //the phase two method name businessActionContextMap.put(Constants.COMPENSATION_METHOD, sagaTransactional.compensationMethod()); businessActionContextMap.put(Constants.ACTION_NAME, sagaTransactional.name()); - businessActionContextMap.put(Constants.USE_TCC_FENCE, true); + businessActionContextMap.put(Constants.USE_COMMON_FENCE, sagaTransactional.useCommonFence()); businessActionParam.setBusinessActionContext(businessActionContextMap); //Handler the Saga Aspect, and return the business result return actionInterceptorHandler.proceed(method, invocation.getArguments(), xid, businessActionParam, invocation::proceed); } finally { //if not SAGA, unbind branchType - if (BranchType.SAGA != previousBranchType) { + if (BranchType.SAGA_ANNOTATION != previousBranchType) { RootContext.unbindBranchType(); } //MDC remove branchId diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResource.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResource.java index a64ca5f076e..eab48cad704 100644 --- a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResource.java +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResource.java @@ -29,11 +29,6 @@ public class SagaResource implements Resource { private String applicationId; - /** - * whether used saga annotation mode - */ - private boolean useSagaAnnotationMode; - /** * Gets get resource group id. * @@ -90,12 +85,5 @@ public String getApplicationId() { public void setApplicationId(String applicationId) { this.applicationId = applicationId; } - - public boolean isUseSagaAnnotationMode() { - return useSagaAnnotationMode; - } - - public void setUseSagaAnnotationMode(boolean useSagaAnnotationMode) { - this.useSagaAnnotationMode = useSagaAnnotationMode; - } + } \ No newline at end of file diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java index 8842a951212..41e29f5f4c5 100644 --- a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaResourceManager.java @@ -15,35 +15,26 @@ */ package io.seata.saga.rm; -import io.seata.common.Constants; import io.seata.common.exception.FrameworkErrorCode; -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.common.exception.SkipCallbackWrapperException; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; import io.seata.core.model.GlobalStatus; import io.seata.core.model.Resource; import io.seata.rm.AbstractResourceManager; -import io.seata.rm.tcc.api.BusinessActionContext; -import io.seata.rm.tcc.api.BusinessActionContextUtil; import io.seata.saga.engine.exception.EngineExecutionException; import io.seata.saga.engine.exception.ForwardInvalidException; import io.seata.saga.statelang.domain.ExecutionStatus; import io.seata.saga.statelang.domain.RecoverStrategy; import io.seata.saga.statelang.domain.StateMachineInstance; -import io.seata.spring.fence.TCCFenceHandler; -import io.seata.spring.remoting.TwoPhaseResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.lang.reflect.Method; -import java.lang.reflect.UndeclaredThrowableException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** - * Saga resource manager + * Saga state machine resource manager * * @author lorne.cl */ @@ -94,15 +85,6 @@ public Map getManagedResources() { public BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) throws TransactionException { - // Saga annotation mode - SagaResource sagaResource = (SagaResource) sagaResourceCache.get(resourceId); - if (sagaResource == null) { - throw new ShouldNeverHappenException(String.format("Saga resource is not exist, resourceId: %s", resourceId)); - } - if (sagaResource.isUseSagaAnnotationMode()) { - return BranchStatus.PhaseTwo_Committed; - } - // Saga state machine mode try { StateMachineInstance machineInstance = StateMachineEngineHolder.getStateMachineEngine().forward(xid, null); @@ -148,15 +130,6 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) throws TransactionException { - // Saga annotation mode - SagaResource sagaResource = (SagaResource) sagaResourceCache.get(resourceId); - if (sagaResource == null) { - throw new ShouldNeverHappenException(String.format("Saga resource is not exist, resourceId: %s", resourceId)); - } - if (sagaResource.isUseSagaAnnotationMode()) { - return this.sagaCompensateBranch(xid, branchId, resourceId, applicationData, (SagaAnnotationResource) sagaResource); - } - // Saga state machine mode try { StateMachineInstance stateMachineInstance = StateMachineEngineHolder.getStateMachineEngine().reloadStateMachineInstance(xid); @@ -188,65 +161,6 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc return BranchStatus.PhaseTwo_RollbackFailed_Retryable; } - private BranchStatus sagaCompensateBranch(String xid, long branchId, String resourceId, String applicationData, SagaAnnotationResource sagaAnnotationResource) { - if (sagaAnnotationResource == null) { - throw new ShouldNeverHappenException(String.format("Saga annotation resource is not exist, resourceId: %s", resourceId)); - } - Object targetSagaBean = sagaAnnotationResource.getTargetBean(); - Method compensationMethod = sagaAnnotationResource.getCompensationMethod(); - if (targetSagaBean == null || compensationMethod == null) { - throw new ShouldNeverHappenException(String.format("Saga target Bean or compensationMethod is not available, resourceId: %s", resourceId)); - } - try { - //BusinessActionContext - BusinessActionContext businessActionContext = BusinessActionContextUtil.getBusinessActionContext(xid, branchId, resourceId, - applicationData); - Object[] args = this.getTwoPhaseCompensationArgs(sagaAnnotationResource, businessActionContext); - - Object ret; - boolean result; - // add idempotent and anti hanging - if (Boolean.TRUE.equals(businessActionContext.getActionContext(Constants.USE_TCC_FENCE))) { - try { - result = TCCFenceHandler.rollbackFence(compensationMethod, targetSagaBean, xid, branchId, - args, sagaAnnotationResource.getActionName()); - } catch (SkipCallbackWrapperException | UndeclaredThrowableException e) { - throw e.getCause(); - } - } else { - ret = compensationMethod.invoke(targetSagaBean, args); - if (ret != null) { - if (ret instanceof TwoPhaseResult) { - result = ((TwoPhaseResult) ret).isSuccess(); - } else { - result = (boolean) ret; - } - } else { - result = true; - } - } - LOGGER.info("Saga resource compensation result : {}, xid: {}, branchId: {}, resourceId: {}", result, xid, branchId, resourceId); - return result ? BranchStatus.PhaseTwo_Rollbacked : BranchStatus.PhaseTwo_RollbackFailed_Retryable; - } catch (Throwable t) { - String msg = String.format("compensation Saga resource error, resourceId: %s, xid: %s.", resourceId, xid); - LOGGER.error(msg, t); - return BranchStatus.PhaseTwo_RollbackFailed_Retryable; - } - } - - /** - * get phase two compensate method's args - * - * @param sagaAnnotationResource sagaAnnotationResource - * @param businessActionContext businessActionContext - * @return args - */ - private Object[] getTwoPhaseCompensationArgs(SagaAnnotationResource sagaAnnotationResource, BusinessActionContext businessActionContext) { - String[] keys = sagaAnnotationResource.getPhaseTwoCompensationKeys(); - Class[] argsCommitClasses = sagaAnnotationResource.getCompensationArgsClasses(); - return BusinessActionContextUtil.getTwoPhaseMethodParams(keys, argsCommitClasses, businessActionContext); - } - @Override public BranchType getBranchType() { return BranchType.SAGA; diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/RMHandlerSagaAnnotation.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/RMHandlerSagaAnnotation.java new file mode 100644 index 00000000000..d4af54b561b --- /dev/null +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/RMHandlerSagaAnnotation.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.saga.rm.annotation; + +import io.seata.core.model.BranchType; +import io.seata.core.model.ResourceManager; +import io.seata.rm.AbstractRMHandler; +import io.seata.rm.DefaultResourceManager; + +/** + * The type Rm handler SAGA annotation. + * + * @author ruishansun + */ +public class RMHandlerSagaAnnotation extends AbstractRMHandler { + + @Override + protected ResourceManager getResourceManager() { + return DefaultResourceManager.get().getResourceManager(BranchType.SAGA_ANNOTATION); + } + + @Override + public BranchType getBranchType() { + return BranchType.SAGA_ANNOTATION; + } +} diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaAnnotationResource.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResource.java similarity index 97% rename from saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaAnnotationResource.java rename to saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResource.java index d49e389a633..de9f783e4b2 100644 --- a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/SagaAnnotationResource.java +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResource.java @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.saga.rm; +package io.seata.saga.rm.annotation; + +import io.seata.saga.rm.SagaResource; import java.lang.reflect.Method; diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResourceManager.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResourceManager.java new file mode 100644 index 00000000000..0513cb8b2fc --- /dev/null +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResourceManager.java @@ -0,0 +1,146 @@ +/* + * 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.saga.rm.annotation; + +import io.seata.common.Constants; +import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.exception.SkipCallbackWrapperException; +import io.seata.core.model.BranchStatus; +import io.seata.core.model.BranchType; +import io.seata.core.model.Resource; +import io.seata.rm.AbstractResourceManager; +import io.seata.rm.tcc.api.BusinessActionContext; +import io.seata.rm.tcc.api.BusinessActionContextUtil; +import io.seata.spring.fence.CommonFenceHandler; +import io.seata.spring.remoting.TwoPhaseResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Method; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Saga annotation resource manager + * + * @author ruishansun + */ +public class SagaAnnotationResourceManager extends AbstractResourceManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(SagaAnnotationResourceManager.class); + + /** + * Saga annotation resource cache + */ + private final Map sagaAnnotationResourceCache = new ConcurrentHashMap<>(); + + /** + * Instantiates a new saga annotation resource manager. + */ + public SagaAnnotationResourceManager() { + } + + /** + * registry saga annotation resource + * + * @param resource The resource to be managed. + */ + @Override + public void registerResource(Resource resource) { + SagaAnnotationResource sagaAnnotationResource = (SagaAnnotationResource) resource; + sagaAnnotationResourceCache.put(sagaAnnotationResource.getResourceId(), sagaAnnotationResource); + super.registerResource(sagaAnnotationResource); + } + + @Override + public Map getManagedResources() { + return sagaAnnotationResourceCache; + } + + @Override + public BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) { + + // Saga annotation mode + return BranchStatus.PhaseTwo_Committed; + } + + @Override + public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) { + // Saga annotation mode + SagaAnnotationResource sagaAnnotationResource = (SagaAnnotationResource) sagaAnnotationResourceCache.get(resourceId); + if (sagaAnnotationResource == null) { + throw new ShouldNeverHappenException(String.format("Saga annotation resource is not exist, resourceId: %s", resourceId)); + } + Object targetSagaBean = sagaAnnotationResource.getTargetBean(); + Method compensationMethod = sagaAnnotationResource.getCompensationMethod(); + if (targetSagaBean == null || compensationMethod == null) { + throw new ShouldNeverHappenException(String.format("Saga target Bean or compensationMethod is not available, resourceId: %s", resourceId)); + } + try { + //BusinessActionContext + BusinessActionContext businessActionContext = BusinessActionContextUtil.getBusinessActionContext(xid, branchId, resourceId, applicationData); + Object[] args = this.getTwoPhaseCompensationArgs(sagaAnnotationResource, businessActionContext); + + Object ret; + boolean result; + // add idempotent and anti hanging + if (Boolean.TRUE.equals(businessActionContext.getActionContext(Constants.USE_COMMON_FENCE))) { + try { + result = CommonFenceHandler.rollbackFence(compensationMethod, targetSagaBean, xid, branchId, args, sagaAnnotationResource.getActionName()); + } catch (SkipCallbackWrapperException | UndeclaredThrowableException e) { + throw e.getCause(); + } + } else { + ret = compensationMethod.invoke(targetSagaBean, args); + if (ret != null) { + if (ret instanceof TwoPhaseResult) { + result = ((TwoPhaseResult) ret).isSuccess(); + } else { + result = (boolean) ret; + } + } else { + result = true; + } + } + LOGGER.info("Saga resource compensation result : {}, xid: {}, branchId: {}, resourceId: {}", result, xid, branchId, resourceId); + return result ? BranchStatus.PhaseTwo_Rollbacked : BranchStatus.PhaseTwo_RollbackFailed_Retryable; + } catch (Throwable t) { + String msg = String.format("compensation Saga resource error, resourceId: %s, xid: %s.", resourceId, xid); + LOGGER.error(msg, t); + return BranchStatus.PhaseTwo_RollbackFailed_Retryable; + } + } + + + /** + * get phase two compensate method's args + * + * @param sagaAnnotationResource sagaAnnotationResource + * @param businessActionContext businessActionContext + * @return args + */ + private Object[] getTwoPhaseCompensationArgs(SagaAnnotationResource sagaAnnotationResource, BusinessActionContext businessActionContext) { + String[] keys = sagaAnnotationResource.getPhaseTwoCompensationKeys(); + Class[] argsCommitClasses = sagaAnnotationResource.getCompensationArgsClasses(); + return BusinessActionContextUtil.getTwoPhaseMethodParams(keys, argsCommitClasses, businessActionContext); + } + + @Override + public BranchType getBranchType() { + return BranchType.SAGA_ANNOTATION; + } +} diff --git a/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager b/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager index 69bc38af6f9..4e157dfa481 100644 --- a/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager +++ b/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.core.model.ResourceManager @@ -1 +1,2 @@ io.seata.saga.rm.SagaResourceManager +io.seata.saga.rm.annotation.SagaAnnotationResourceManager \ No newline at end of file diff --git a/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.rm.AbstractRMHandler b/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.rm.AbstractRMHandler index cd5b9a18bbb..b10cb62b3de 100644 --- a/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.rm.AbstractRMHandler +++ b/saga/seata-saga-rm/src/main/resources/META-INF/services/io.seata.rm.AbstractRMHandler @@ -1 +1,2 @@ -io.seata.saga.rm.RMHandlerSaga \ No newline at end of file +io.seata.saga.rm.RMHandlerSaga +io.seata.saga.rm.annotation.RMHandlerSagaAnnotation \ No newline at end of file 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 abd8f568d2d..48145b3ca73 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,7 +16,7 @@ package io.seata.spring.boot.autoconfigure; import io.seata.common.holder.ObjectHolder; -import io.seata.spring.fence.config.TCCFenceConfig; +import io.seata.spring.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; @@ -64,7 +64,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); } 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 2905734c4d2..a772ae66c4b 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.spring.fence.config.TCCFenceConfig; +import io.seata.spring.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,12 +46,12 @@ 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); } 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 b75a92642fc..0e16befe433 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.spring.fence.config.TCCFenceConfig", + "sourceType": "io.seata.spring.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.spring.fence.config.TCCFenceConfig", + "sourceType": "io.seata.spring.fence.config.CommonFenceConfig", "defaultValue": "1d" }, { diff --git a/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java b/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java index 8c5a8a8c6e1..0676adddcf0 100644 --- a/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java +++ b/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java @@ -20,6 +20,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import io.seata.core.model.BranchType; import io.seata.spring.interceptor.ActionContextUtil; /** @@ -50,6 +51,11 @@ public class BusinessActionContext implements Serializable { */ private Boolean isUpdated; + /** + * branch Type + */ + private BranchType branchType; + /** * action context */ @@ -219,6 +225,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,6 +241,7 @@ 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(); diff --git a/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java b/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java index 8756a788294..ac5cb348eb6 100644 --- a/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java +++ b/spring/src/main/java/io/seata/rm/tcc/api/BusinessActionContextUtil.java @@ -26,7 +26,6 @@ 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.rm.DefaultResourceManager; import io.seata.spring.interceptor.ActionContextUtil; import org.slf4j.Logger; @@ -108,11 +107,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 @@ -151,7 +150,7 @@ public static BusinessActionContext getBusinessActionContext(String xid, long br Map actionContextMap = null; if (StringUtils.isNotBlank(applicationData)) { Map tccContext = JSON.parseObject(applicationData, Map.class); - actionContextMap = (Map) tccContext.get(Constants.TCC_ACTION_CONTEXT); + actionContextMap = (Map) tccContext.get(Constants.TX_ACTION_CONTEXT); } if (actionContextMap == null) { actionContextMap = new HashMap<>(2); 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 bb632086190..aaf85fa2e49 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java @@ -39,7 +39,7 @@ import io.seata.spring.annotation.scannercheckers.PackageScannerChecker; import io.seata.spring.autoproxy.DefaultTransactionAutoProxy; import io.seata.spring.autoproxy.IsTransactionProxyResult; -import io.seata.spring.interceptor.TCCBeanParserUtils; +import io.seata.spring.interceptor.TxBeanParserUtils; import io.seata.spring.remoting.parser.LocalServiceRemotingParser; import io.seata.spring.util.OrderUtil; import io.seata.spring.util.SpringProxyUtils; @@ -288,10 +288,10 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) } interceptor = null; //check Transaction proxy - if (TCCBeanParserUtils.isTccAutoProxy(bean, beanName, applicationContext)) { + 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, isTransactionProxyResult.isUseFence()); + 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, diff --git a/spring/src/main/java/io/seata/spring/autoproxy/IsTransactionProxyResult.java b/spring/src/main/java/io/seata/spring/autoproxy/IsTransactionProxyResult.java index 0ba74692642..07d831a749e 100644 --- a/spring/src/main/java/io/seata/spring/autoproxy/IsTransactionProxyResult.java +++ b/spring/src/main/java/io/seata/spring/autoproxy/IsTransactionProxyResult.java @@ -30,9 +30,9 @@ public class IsTransactionProxyResult { private boolean isProxyTargetBean; /** - * whether used fence + * whether used common fence */ - private boolean useFence; + private boolean useCommonFence; /** * transaction proxy method @@ -47,12 +47,12 @@ public void setProxyTargetBean(boolean proxyTargetBean) { isProxyTargetBean = proxyTargetBean; } - public boolean isUseFence() { - return useFence; + public boolean isUseCommonFence() { + return useCommonFence; } - public void setUseFence(boolean useFence) { - this.useFence = useFence; + public void setUseCommonFence(boolean useCommonFence) { + this.useCommonFence = useCommonFence; } public MethodInterceptor getMethodInterceptor() { diff --git a/spring/src/main/java/io/seata/spring/fence/TCCFenceHandler.java b/spring/src/main/java/io/seata/spring/fence/CommonFenceHandler.java similarity index 74% rename from spring/src/main/java/io/seata/spring/fence/TCCFenceHandler.java rename to spring/src/main/java/io/seata/spring/fence/CommonFenceHandler.java index dfbe37a3d9c..e9240e98c4d 100644 --- a/spring/src/main/java/io/seata/spring/fence/TCCFenceHandler.java +++ b/spring/src/main/java/io/seata/spring/fence/CommonFenceHandler.java @@ -28,11 +28,11 @@ import io.seata.common.exception.SkipCallbackWrapperException; import io.seata.common.executor.Callback; import io.seata.common.thread.NamedThreadFactory; -import io.seata.spring.fence.constant.TCCFenceConstant; -import io.seata.spring.fence.exception.TCCFenceException; -import io.seata.spring.fence.store.TCCFenceDO; -import io.seata.spring.fence.store.TCCFenceStore; -import io.seata.spring.fence.store.db.TCCFenceStoreDataBaseDAO; +import io.seata.spring.fence.constant.CommonFenceConstant; +import io.seata.spring.fence.exception.CommonFenceException; +import io.seata.spring.fence.store.CommonFenceDO; +import io.seata.spring.fence.store.CommonFenceStore; +import io.seata.spring.fence.store.db.CommonFenceStoreDataBaseDAO; import io.seata.spring.remoting.TwoPhaseResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,19 +41,19 @@ import org.springframework.transaction.support.TransactionTemplate; /** - * 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; @@ -78,15 +78,15 @@ private TCCFenceHandler() { } 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 @@ -98,15 +98,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); @@ -121,10 +121,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 @@ -135,22 +135,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.RecordAlreadyExists); } - 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); @@ -159,7 +159,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 @@ -174,29 +174,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); @@ -205,7 +205,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 @@ -213,13 +213,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); } /** @@ -236,7 +236,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); @@ -256,7 +256,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 @@ -267,7 +267,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); @@ -277,7 +277,7 @@ public static boolean deleteFence(String xid, Long branchId) { } /** - * Delete TCC Fence By Datetime + * Delete Common Fence By Datetime * * @param datetime datetime * @return the deleted row count @@ -286,7 +286,7 @@ public static int deleteFenceByDate(Date datetime) { return transactionTemplate.execute(status -> { try { Connection conn = DataSourceUtils.getConnection(dataSource); - return TCC_FENCE_DAO.deleteTCCFenceDOByDate(conn, datetime); + return COMMON_FENCE_DAO.deleteCommonFenceDOByDate(conn, datetime); } catch (RuntimeException e) { status.setRollbackOnly(); throw e; @@ -317,7 +317,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 @@ -326,7 +326,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()); } diff --git a/spring/src/main/java/io/seata/spring/fence/config/TCCFenceConfig.java b/spring/src/main/java/io/seata/spring/fence/config/CommonFenceConfig.java similarity index 76% rename from spring/src/main/java/io/seata/spring/fence/config/TCCFenceConfig.java rename to spring/src/main/java/io/seata/spring/fence/config/CommonFenceConfig.java index bef13fec8f8..5b8037e9d69 100644 --- a/spring/src/main/java/io/seata/spring/fence/config/TCCFenceConfig.java +++ b/spring/src/main/java/io/seata/spring/fence/config/CommonFenceConfig.java @@ -27,9 +27,9 @@ import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.thread.NamedThreadFactory; import io.seata.core.rpc.Disposable; -import io.seata.spring.fence.TCCFenceHandler; -import io.seata.spring.fence.exception.TCCFenceException; -import io.seata.spring.fence.store.db.TCCFenceStoreDataBaseDAO; +import io.seata.spring.fence.CommonFenceHandler; +import io.seata.spring.fence.exception.CommonFenceException; +import io.seata.spring.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,19 +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/spring/src/main/java/io/seata/spring/fence/constant/TCCFenceConstant.java b/spring/src/main/java/io/seata/spring/fence/constant/CommonFenceConstant.java similarity index 92% rename from spring/src/main/java/io/seata/spring/fence/constant/TCCFenceConstant.java rename to spring/src/main/java/io/seata/spring/fence/constant/CommonFenceConstant.java index 41e5262df10..bc56d841559 100644 --- a/spring/src/main/java/io/seata/spring/fence/constant/TCCFenceConstant.java +++ b/spring/src/main/java/io/seata/spring/fence/constant/CommonFenceConstant.java @@ -16,13 +16,13 @@ package io.seata.spring.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"); } diff --git a/spring/src/main/java/io/seata/spring/fence/exception/TCCFenceException.java b/spring/src/main/java/io/seata/spring/fence/exception/CommonFenceException.java similarity index 67% rename from spring/src/main/java/io/seata/spring/fence/exception/TCCFenceException.java rename to spring/src/main/java/io/seata/spring/fence/exception/CommonFenceException.java index b945203ccde..0200dd993c5 100644 --- a/spring/src/main/java/io/seata/spring/fence/exception/TCCFenceException.java +++ b/spring/src/main/java/io/seata/spring/fence/exception/CommonFenceException.java @@ -19,33 +19,33 @@ 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); } diff --git a/spring/src/main/java/io/seata/spring/fence/store/TCCFenceDO.java b/spring/src/main/java/io/seata/spring/fence/store/CommonFenceDO.java similarity index 96% rename from spring/src/main/java/io/seata/spring/fence/store/TCCFenceDO.java rename to spring/src/main/java/io/seata/spring/fence/store/CommonFenceDO.java index 98437858834..ba079cb955c 100644 --- a/spring/src/main/java/io/seata/spring/fence/store/TCCFenceDO.java +++ b/spring/src/main/java/io/seata/spring/fence/store/CommonFenceDO.java @@ -18,11 +18,11 @@ 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; diff --git a/spring/src/main/java/io/seata/spring/fence/store/TCCFenceStore.java b/spring/src/main/java/io/seata/spring/fence/store/CommonFenceStore.java similarity index 65% rename from spring/src/main/java/io/seata/spring/fence/store/TCCFenceStore.java rename to spring/src/main/java/io/seata/spring/fence/store/CommonFenceStore.java index 04ac5915904..ff9d04b3434 100644 --- a/spring/src/main/java/io/seata/spring/fence/store/TCCFenceStore.java +++ b/spring/src/main/java/io/seata/spring/fence/store/CommonFenceStore.java @@ -19,50 +19,50 @@ import java.util.Date; /** - * 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 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); /** - * Insert tcc fence do boolean. - * @param tccFenceDO the tcc fence do + * Insert common fence do boolean. + * @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 xid the global transaction id * @param branchId the branch transaction id * @param newStatus the new 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 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 by datetime. + * Delete common fence by datetime. * @param datetime datetime * @return the deleted row count */ - int deleteTCCFenceDOByDate(Connection conn, Date datetime); + int deleteCommonFenceDOByDate(Connection conn, Date datetime); /** * Set LogTable Name diff --git a/spring/src/main/java/io/seata/spring/fence/store/db/TCCFenceStoreDataBaseDAO.java b/spring/src/main/java/io/seata/spring/fence/store/db/CommonFenceStoreDataBaseDAO.java similarity index 61% rename from spring/src/main/java/io/seata/spring/fence/store/db/TCCFenceStoreDataBaseDAO.java rename to spring/src/main/java/io/seata/spring/fence/store/db/CommonFenceStoreDataBaseDAO.java index 43bb775e263..5da3f2393ae 100644 --- a/spring/src/main/java/io/seata/spring/fence/store/db/TCCFenceStoreDataBaseDAO.java +++ b/spring/src/main/java/io/seata/spring/fence/store/db/CommonFenceStoreDataBaseDAO.java @@ -20,10 +20,10 @@ import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.exception.StoreException; import io.seata.common.util.IOUtil; -import io.seata.spring.fence.exception.TCCFenceException; -import io.seata.spring.fence.store.TCCFenceDO; -import io.seata.spring.fence.store.TCCFenceStore; -import io.seata.spring.fence.store.db.sql.TCCFenceStoreSqls; +import io.seata.spring.fence.exception.CommonFenceException; +import io.seata.spring.fence.store.CommonFenceDO; +import io.seata.spring.fence.store.CommonFenceStore; +import io.seata.spring.fence.store.db.sql.CommonFenceStoreSqls; import java.sql.Connection; import java.sql.PreparedStatement; @@ -34,26 +34,26 @@ import java.util.Date; /** - * 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(); } } } @@ -61,21 +61,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; } @@ -87,22 +87,22 @@ public TCCFenceDO queryTCCFenceDO(Connection conn, String xid, Long branchId) { } @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); @@ -112,10 +112,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 @@ -132,10 +132,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); @@ -149,10 +149,10 @@ public boolean deleteTCCFenceDO(Connection conn, String xid, Long branchId) { } @Override - public int deleteTCCFenceDOByDate(Connection conn, Date datetime) { + public int deleteCommonFenceDOByDate(Connection conn, Date datetime) { 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())); return ps.executeUpdate(); diff --git a/spring/src/main/java/io/seata/spring/fence/store/db/sql/TCCFenceStoreSqls.java b/spring/src/main/java/io/seata/spring/fence/store/db/sql/CommonFenceStoreSqls.java similarity index 90% rename from spring/src/main/java/io/seata/spring/fence/store/db/sql/TCCFenceStoreSqls.java rename to spring/src/main/java/io/seata/spring/fence/store/db/sql/CommonFenceStoreSqls.java index 06436d3ff72..4fc94e91c84 100644 --- a/spring/src/main/java/io/seata/spring/fence/store/db/sql/TCCFenceStoreSqls.java +++ b/spring/src/main/java/io/seata/spring/fence/store/db/sql/CommonFenceStoreSqls.java @@ -15,16 +15,16 @@ */ package io.seata.spring.fence.store.db.sql; -import io.seata.spring.fence.constant.TCCFenceConstant; +import io.seata.spring.fence.constant.CommonFenceConstant; /** * TCC Fence Store Sqls * * @author kaka2code */ -public class TCCFenceStoreSqls { +public class CommonFenceStoreSqls { - private TCCFenceStoreSqls() { + private CommonFenceStoreSqls() { throw new IllegalStateException("Utility class"); } @@ -63,7 +63,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 + ")"; public static String getInsertLocalTCCLogSQL(String localTccTable) { return INSERT_LOCAL_TCC_LOG.replace(LOCAL_TCC_LOG_PLACEHOLD, localTccTable); diff --git a/spring/src/main/java/io/seata/spring/interceptor/ActionInterceptorHandler.java b/spring/src/main/java/io/seata/spring/interceptor/ActionInterceptorHandler.java index 7dc0c3f2c98..23a4c662ed4 100644 --- a/spring/src/main/java/io/seata/spring/interceptor/ActionInterceptorHandler.java +++ b/spring/src/main/java/io/seata/spring/interceptor/ActionInterceptorHandler.java @@ -28,7 +28,7 @@ import io.seata.rm.tcc.api.BusinessActionContextParameter; import io.seata.rm.tcc.api.BusinessActionContextUtil; import io.seata.rm.tcc.api.ParamType; -import io.seata.spring.fence.TCCFenceHandler; +import io.seata.spring.fence.CommonFenceHandler; import io.seata.spring.remoting.RemotingDesc; import io.seata.spring.util.DubboUtil; import io.seata.spring.util.SpringProxyUtils; @@ -47,7 +47,7 @@ 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 */ @@ -56,7 +56,7 @@ 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 @@ -77,9 +77,11 @@ public Object proceed(Method method, Object[] arguments, String xid, TwoPhaseBus actionContext.setActionName(actionName); //Set the delay report actionContext.setDelayReport(businessActionParam.getDelayReport()); + //Set branch type + actionContext.setBranchType(businessActionParam.getBranchType()); //Creating Branch Record - String branchId = doTccActionLogStore(method, arguments, businessActionParam, actionContext); + String branchId = doTxActionLogStore(method, arguments, businessActionParam, actionContext); actionContext.setBranchId(branchId); //MDC put branchId MDC.put(RootContext.MDC_KEY_BRANCH_ID, branchId); @@ -90,14 +92,14 @@ public Object proceed(Method method, Object[] arguments, String xid, TwoPhaseBus //share actionContext implicitly BusinessActionContextUtil.setContext(actionContext); - if (businessActionParam.getUseFence()) { + 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; } @@ -166,8 +168,8 @@ protected BusinessActionContext getOrCreateActionContextAndResetToArguments(Clas * @param actionContext the action context * @return the branchId */ - protected String doTccActionLogStore(Method method, Object[] arguments, TwoPhaseBusinessActionParam businessActionParam, - BusinessActionContext actionContext) { + protected String doTxActionLogStore(Method method, Object[] arguments, TwoPhaseBusinessActionParam businessActionParam, + BusinessActionContext actionContext) { String actionName = actionContext.getActionName(); String xid = actionContext.getXid(); @@ -194,7 +196,7 @@ 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 @@ -202,7 +204,7 @@ protected String doTccActionLogStore(Method method, Object[] arguments, TwoPhase 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); } diff --git a/spring/src/main/java/io/seata/spring/interceptor/TwoPhaseBusinessActionParam.java b/spring/src/main/java/io/seata/spring/interceptor/TwoPhaseBusinessActionParam.java index b7aba50832e..c9c4cfae035 100644 --- a/spring/src/main/java/io/seata/spring/interceptor/TwoPhaseBusinessActionParam.java +++ b/spring/src/main/java/io/seata/spring/interceptor/TwoPhaseBusinessActionParam.java @@ -30,7 +30,7 @@ public class TwoPhaseBusinessActionParam { private Boolean isDelayReport; - private Boolean useFence; + private Boolean useCommonFence; private Map businessActionContext; @@ -52,12 +52,12 @@ public void setDelayReport(Boolean delayReport) { isDelayReport = delayReport; } - public Boolean getUseFence() { - return useFence; + public Boolean getUseCommonFence() { + return useCommonFence; } - public void setUseFence(Boolean useFence) { - this.useFence = useFence; + public void setUseCommonFence(Boolean useCommonFence) { + this.useCommonFence = useCommonFence; } public Map getBusinessActionContext() { diff --git a/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java b/spring/src/main/java/io/seata/spring/interceptor/TxAnnotationProcessor.java similarity index 87% rename from spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java rename to spring/src/main/java/io/seata/spring/interceptor/TxAnnotationProcessor.java index 0d9a812815e..9fe395c6d83 100644 --- a/spring/src/main/java/io/seata/spring/interceptor/TccAnnotationProcessor.java +++ b/spring/src/main/java/io/seata/spring/interceptor/TxAnnotationProcessor.java @@ -33,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<>(); @@ -74,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))); @@ -83,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 @@ -91,7 +91,7 @@ protected void process(Object bean, String beanName, Class * @param interfaceClass the interface class * @throws IllegalAccessException the illegal access exception */ - public void addTccAdvise(Object bean, String beanName, Field field, Class interfaceClass) throws IllegalAccessException { + public void addTxAdvise(Object bean, String beanName, Field field, Class interfaceClass) throws IllegalAccessException { Object fieldValue = field.get(bean); if (fieldValue == null) { return; @@ -99,7 +99,7 @@ public void addTccAdvise(Object bean, String beanName, Field field, Class interf IsTransactionProxyResult isProxyTargetBeanResult = DefaultTransactionAutoProxy.get().getIsProxyTargetBeanResult(beanName); if (isProxyTargetBeanResult.isProxyTargetBean()) { - Object proxyBean = TCCBeanParserUtils.createProxy(interfaceClass, fieldValue, isProxyTargetBeanResult.getMethodInterceptor()); + Object proxyBean = TxBeanParserUtils.createProxy(interfaceClass, 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() + "]"); diff --git a/spring/src/main/java/io/seata/spring/interceptor/TCCBeanParserUtils.java b/spring/src/main/java/io/seata/spring/interceptor/TxBeanParserUtils.java similarity index 82% rename from spring/src/main/java/io/seata/spring/interceptor/TCCBeanParserUtils.java rename to spring/src/main/java/io/seata/spring/interceptor/TxBeanParserUtils.java index 11d87234494..4554c648778 100644 --- a/spring/src/main/java/io/seata/spring/interceptor/TCCBeanParserUtils.java +++ b/spring/src/main/java/io/seata/spring/interceptor/TxBeanParserUtils.java @@ -17,7 +17,7 @@ import io.seata.common.DefaultValues; import io.seata.spring.autoproxy.DefaultTransactionAutoProxy; -import io.seata.spring.fence.config.TCCFenceConfig; +import io.seata.spring.fence.config.CommonFenceConfig; import io.seata.spring.remoting.Protocols; import io.seata.spring.remoting.RemotingDesc; import io.seata.spring.remoting.RemotingParser; @@ -28,31 +28,31 @@ import org.springframework.context.ApplicationContext; /** - * 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 + //LocalService return DefaultTransactionAutoProxy.get().isTransactionAutoProxy(beanName, remotingDesc); } else { // sofa:reference / dubbo:reference, factory bean @@ -101,24 +101,24 @@ protected static boolean isRemotingFactoryBean(Object bean, String beanName, } /** - * init tcc fence clean task if enable useTccFence + * init common fence clean task if enable useCommonFence * * @param remotingDesc the remoting desc * @param applicationContext applicationContext */ - public static void initTccFenceCleanTask(RemotingDesc remotingDesc, ApplicationContext applicationContext, boolean useFence) { + 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; } - if (useFence && tccFenceConfig.getInitialized().compareAndSet(false, true)) { - // init tcc fence clean task if enable useTccFence - tccFenceConfig.initCleanTask(); + if (useCommonFence && commonFenceConfig.getInitialized().compareAndSet(false, true)) { + // init common fence clean task if enable useCommonFence + commonFenceConfig.initCleanTask(); } } } @@ -139,7 +139,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 @@ -149,7 +149,7 @@ public static RemotingDesc getRemotingDesc(String beanName) { } /** - * Create a proxy bean for tcc service + * Create a proxy bean for transaction service * * @param interfaceClass * @param fieldValue 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 43c60a67853..75dea74b110 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java +++ b/tcc/src/main/java/io/seata/rm/tcc/TCCResourceManager.java @@ -25,7 +25,7 @@ import io.seata.rm.AbstractResourceManager; import io.seata.rm.tcc.api.BusinessActionContext; import io.seata.rm.tcc.api.BusinessActionContextUtil; -import io.seata.spring.fence.TCCFenceHandler; +import io.seata.spring.fence.CommonFenceHandler; import io.seata.spring.remoting.TwoPhaseResult; import java.lang.reflect.Method; @@ -102,9 +102,9 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI 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(); } @@ -160,9 +160,9 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc 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(); 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 index 3fb930c6fab..434878d7cf0 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java +++ b/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java @@ -72,7 +72,7 @@ public IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remoti //in jvm TCC bean , AOP IsTransactionProxyResult result = new IsTransactionProxyResult(); result.setProxyTargetBean(true); - result.setUseFence(userFence); + result.setUseCommonFence(userFence); result.setMethodInterceptor(new TccActionInterceptor(remotingDesc)); return result; } @@ -81,7 +81,7 @@ public IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remoti this.registryResource(remotingDesc); IsTransactionProxyResult result = new IsTransactionProxyResult(); result.setProxyTargetBean(true); - result.setUseFence(userFence); + result.setUseCommonFence(userFence); result.setMethodInterceptor(new TccActionInterceptor(remotingDesc)); return result; } else { diff --git a/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptor.java b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptor.java index 28ef3bd2f82..07a4dd20cb6 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptor.java +++ b/tcc/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptor.java @@ -103,14 +103,14 @@ public Object invoke(final MethodInvocation invocation) throws Throwable { TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam(); businessActionParam.setActionName(businessAction.name()); businessActionParam.setDelayReport(businessAction.isDelayReport()); - businessActionParam.setUseFence(businessAction.useTCCFence()); + 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_TCC_FENCE, businessAction.useTCCFence()); + 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, businessActionParam, From 100fbe553139e6fb6f02bc6e84b80aa6f89e6a3b Mon Sep 17 00:00:00 2001 From: ruishansun Date: Sat, 2 Jul 2022 18:20:21 +0800 Subject: [PATCH 19/24] add saga annotation build jar in pom --- all/pom.xml | 5 +++++ saga/pom.xml | 2 +- .../{annotation-mode => seata-saga-annotation-mode}/pom.xml | 2 +- .../io/seata/saga/annotation}/api/SagaTransactional.java | 4 ++-- .../annotation}/autoproxy/SagaTransactionAutoProxy.java | 6 +++--- .../saga/annotation}/interceptor/SagaActionInterceptor.java | 4 ++-- .../src/test/java/io/seata/rm/saga/SagaAction.java | 2 +- .../src/test/java/io/seata/rm/saga/SagaActionImpl.java | 0 .../remoting/parser/LocalServiceRemotingParserTest.java | 0 9 files changed, 15 insertions(+), 10 deletions(-) rename saga/{annotation-mode => seata-saga-annotation-mode}/pom.xml (94%) rename saga/{annotation-mode/src/main/java/io/seata/saga => seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation}/api/SagaTransactional.java (95%) rename saga/{annotation-mode/src/main/java/io/seata/saga => seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation}/autoproxy/SagaTransactionAutoProxy.java (96%) rename saga/{annotation-mode/src/main/java/io/seata/saga => seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation}/interceptor/SagaActionInterceptor.java (98%) rename saga/{annotation-mode => seata-saga-annotation-mode}/src/test/java/io/seata/rm/saga/SagaAction.java (96%) rename saga/{annotation-mode => seata-saga-annotation-mode}/src/test/java/io/seata/rm/saga/SagaActionImpl.java (100%) rename saga/{annotation-mode => seata-saga-annotation-mode}/src/test/java/io/seata/rm/saga/remoting/parser/LocalServiceRemotingParserTest.java (100%) diff --git a/all/pom.xml b/all/pom.xml index 99f6e8f1f4d..49d4b52838a 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -333,6 +333,11 @@ + + io.seata + seata-saga-annotation-mode + ${project.version} + diff --git a/saga/pom.xml b/saga/pom.xml index df46d9745d3..792b99a1c7a 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -36,7 +36,7 @@ seata-saga-rm seata-saga-tm seata-saga-engine-store - annotation-mode + seata-saga-annotation-mode diff --git a/saga/annotation-mode/pom.xml b/saga/seata-saga-annotation-mode/pom.xml similarity index 94% rename from saga/annotation-mode/pom.xml rename to saga/seata-saga-annotation-mode/pom.xml index 51ebc140fb0..4f1176c57ed 100644 --- a/saga/annotation-mode/pom.xml +++ b/saga/seata-saga-annotation-mode/pom.xml @@ -9,7 +9,7 @@ 4.0.0 seata-saga-annotation-mode ${project.version} - annotation-mode + seata-saga-annotation-mode diff --git a/saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java b/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/api/SagaTransactional.java similarity index 95% rename from saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java rename to saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/api/SagaTransactional.java index a642c9c0353..4566a3c952f 100644 --- a/saga/annotation-mode/src/main/java/io/seata/saga/api/SagaTransactional.java +++ b/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/api/SagaTransactional.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.saga.api; +package io.seata.saga.annotation.api; import io.seata.rm.tcc.api.BusinessActionContext; import io.seata.rm.tcc.api.BusinessActionContextParameter; import io.seata.rm.tcc.api.BusinessActionContextUtil; -import io.seata.saga.interceptor.SagaActionInterceptor; +import io.seata.saga.annotation.interceptor.SagaActionInterceptor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java b/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/autoproxy/SagaTransactionAutoProxy.java similarity index 96% rename from saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java rename to saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/autoproxy/SagaTransactionAutoProxy.java index 3e7bbe19a04..b32123daf18 100644 --- a/saga/annotation-mode/src/main/java/io/seata/saga/autoproxy/SagaTransactionAutoProxy.java +++ b/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/autoproxy/SagaTransactionAutoProxy.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.saga.autoproxy; +package io.seata.saga.annotation.autoproxy; import io.seata.common.exception.FrameworkException; import io.seata.rm.DefaultResourceManager; -import io.seata.saga.api.SagaTransactional; -import io.seata.saga.interceptor.SagaActionInterceptor; +import io.seata.saga.annotation.interceptor.SagaActionInterceptor; +import io.seata.saga.annotation.api.SagaTransactional; import io.seata.saga.rm.annotation.SagaAnnotationResource; import io.seata.spring.autoproxy.IsTransactionProxyResult; import io.seata.spring.autoproxy.TransactionAutoProxy; diff --git a/saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java b/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/interceptor/SagaActionInterceptor.java similarity index 98% rename from saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java rename to saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/interceptor/SagaActionInterceptor.java index 6c5e1959434..3db03d7f138 100644 --- a/saga/annotation-mode/src/main/java/io/seata/saga/interceptor/SagaActionInterceptor.java +++ b/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/interceptor/SagaActionInterceptor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.saga.interceptor; +package io.seata.saga.annotation.interceptor; import io.seata.common.Constants; import io.seata.common.DefaultValues; @@ -23,7 +23,7 @@ import io.seata.core.constants.ConfigurationKeys; import io.seata.core.context.RootContext; import io.seata.core.model.BranchType; -import io.seata.saga.api.SagaTransactional; +import io.seata.saga.annotation.api.SagaTransactional; import io.seata.spring.interceptor.ActionInterceptorHandler; import io.seata.spring.interceptor.TwoPhaseBusinessActionParam; import io.seata.spring.remoting.RemotingDesc; diff --git a/saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaAction.java b/saga/seata-saga-annotation-mode/src/test/java/io/seata/rm/saga/SagaAction.java similarity index 96% rename from saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaAction.java rename to saga/seata-saga-annotation-mode/src/test/java/io/seata/rm/saga/SagaAction.java index c0b788f1ef4..8fc5b40da48 100644 --- a/saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaAction.java +++ b/saga/seata-saga-annotation-mode/src/test/java/io/seata/rm/saga/SagaAction.java @@ -17,7 +17,7 @@ import io.seata.rm.tcc.api.BusinessActionContext; import io.seata.rm.tcc.api.BusinessActionContextParameter; -import io.seata.saga.api.SagaTransactional; +import io.seata.saga.annotation.api.SagaTransactional; import io.seata.spring.annotation.LocalService; /** diff --git a/saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaActionImpl.java b/saga/seata-saga-annotation-mode/src/test/java/io/seata/rm/saga/SagaActionImpl.java similarity index 100% rename from saga/annotation-mode/src/test/java/io/seata/rm/saga/SagaActionImpl.java rename to saga/seata-saga-annotation-mode/src/test/java/io/seata/rm/saga/SagaActionImpl.java diff --git a/saga/annotation-mode/src/test/java/io/seata/rm/saga/remoting/parser/LocalServiceRemotingParserTest.java b/saga/seata-saga-annotation-mode/src/test/java/io/seata/rm/saga/remoting/parser/LocalServiceRemotingParserTest.java similarity index 100% rename from saga/annotation-mode/src/test/java/io/seata/rm/saga/remoting/parser/LocalServiceRemotingParserTest.java rename to saga/seata-saga-annotation-mode/src/test/java/io/seata/rm/saga/remoting/parser/LocalServiceRemotingParserTest.java From 7bb7f8e3bdf90dec49322fecf270a56c5614c067 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Tue, 5 Jul 2022 18:28:22 +0800 Subject: [PATCH 20/24] fix add final in static method. --- .../autoproxy/DefaultTransactionAutoProxy.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java b/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java index 421f7e38b43..60e3bab6fc1 100644 --- a/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java +++ b/spring/src/main/java/io/seata/spring/autoproxy/DefaultTransactionAutoProxy.java @@ -34,11 +34,11 @@ public class DefaultTransactionAutoProxy { /** * all the transaction auto proxy */ - protected static List allTransactionAutoProxies = new ArrayList<>(); + protected static final List ALL_TRANSACTION_AUTO_PROXIES = new ArrayList<>(); /** * method interceptor map, beanName -> IsTransactionProxyResult */ - private final Map methodInterceptorMap = new ConcurrentHashMap<>(); + private static final Map METHOD_INTERCEPTOR_MAP = new ConcurrentHashMap<>(); private static class SingletonHolder { private static final DefaultTransactionAutoProxy INSTANCE = new DefaultTransactionAutoProxy(); @@ -66,7 +66,7 @@ protected DefaultTransactionAutoProxy() { private void initTransactionAutoProxy() { List proxies = EnhancedServiceLoader.loadAll(TransactionAutoProxy.class); if (CollectionUtils.isNotEmpty(proxies)) { - allTransactionAutoProxies.addAll(proxies); + ALL_TRANSACTION_AUTO_PROXIES.addAll(proxies); } } @@ -78,10 +78,10 @@ private void initTransactionAutoProxy() { * @return true or false */ public boolean isTransactionAutoProxy(String beanName, RemotingDesc remotingDesc) { - for (TransactionAutoProxy proxy : allTransactionAutoProxies) { + for (TransactionAutoProxy proxy : ALL_TRANSACTION_AUTO_PROXIES) { IsTransactionProxyResult result = proxy.isTransactionProxyTargetBean(remotingDesc); if (result.isProxyTargetBean()) { - methodInterceptorMap.put(beanName, result); + METHOD_INTERCEPTOR_MAP.put(beanName, result); return true; } } @@ -95,7 +95,7 @@ public boolean isTransactionAutoProxy(String beanName, RemotingDesc remotingDesc * @return the IsTransactionProxyResult */ public IsTransactionProxyResult getIsProxyTargetBeanResult(String beanName) { - IsTransactionProxyResult result = methodInterceptorMap.get(beanName); + IsTransactionProxyResult result = METHOD_INTERCEPTOR_MAP.get(beanName); return result != null ? result : new IsTransactionProxyResult(); } } From 06de501a6f18226774b3b677ea640b437d73105c Mon Sep 17 00:00:00 2001 From: ruishansun Date: Sat, 23 Jul 2022 14:55:24 +0800 Subject: [PATCH 21/24] bug fix --- .../services/io.seata.spring.autoproxy.TransactionAutoProxy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy b/spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy index 347a93ab9b7..fa72b433d45 100644 --- a/spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy +++ b/spring/src/main/resources/META-INF/services/io.seata.spring.autoproxy.TransactionAutoProxy @@ -1,2 +1,2 @@ io.seata.rm.tcc.autoproxy.TccTransactionAutoProxy -io.seata.saga.autoproxy.SagaTransactionAutoProxy \ No newline at end of file +io.seata.saga.annotation.autoproxy.SagaTransactionAutoProxy \ No newline at end of file From ac489eb56b4e4705342f4885a23e23b0c7b604f1 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Sat, 23 Jul 2022 17:37:12 +0800 Subject: [PATCH 22/24] bug fix --- .../autoproxy/SagaTransactionAutoProxy.java | 2 +- .../seata/spring/remoting/RemotingDesc.java | 22 +++++++++++++++++++ .../remoting/parser/DubboRemotingParser.java | 2 ++ .../remoting/parser/HSFRemotingParser.java | 4 ++++ .../parser/LocalServiceRemotingParser.java | 3 ++- .../parser/SofaRpcRemotingParser.java | 2 ++ .../autoproxy/TccTransactionAutoProxy.java | 2 +- .../parser/LocalTCCRemotingParser.java | 3 ++- 8 files changed, 36 insertions(+), 4 deletions(-) diff --git a/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/autoproxy/SagaTransactionAutoProxy.java b/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/autoproxy/SagaTransactionAutoProxy.java index b32123daf18..8f0bc2fd179 100644 --- a/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/autoproxy/SagaTransactionAutoProxy.java +++ b/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/autoproxy/SagaTransactionAutoProxy.java @@ -64,7 +64,7 @@ public IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remoti * @param remotingDesc the remotingDesc */ private void registryResource(RemotingDesc remotingDesc) { - if (!remotingDesc.isReference()) { + if (remotingDesc.isService()) { try { Class interfaceClass = remotingDesc.getInterfaceClass(); Method[] methods = interfaceClass.getMethods(); diff --git a/spring/src/main/java/io/seata/spring/remoting/RemotingDesc.java b/spring/src/main/java/io/seata/spring/remoting/RemotingDesc.java index ef57d8814b6..672ab4d55b0 100644 --- a/spring/src/main/java/io/seata/spring/remoting/RemotingDesc.java +++ b/spring/src/main/java/io/seata/spring/remoting/RemotingDesc.java @@ -26,6 +26,11 @@ public class RemotingDesc { * is referenc bean ? */ private boolean isReference = false; + + /** + * is service bean ? + */ + private boolean isService = false; /** * rpc target bean, the service bean has this property @@ -182,4 +187,21 @@ public boolean isReference() { 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; + } } diff --git a/spring/src/main/java/io/seata/spring/remoting/parser/DubboRemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/DubboRemotingParser.java index 673f10fa431..ecbd3bc5bae 100644 --- a/spring/src/main/java/io/seata/spring/remoting/parser/DubboRemotingParser.java +++ b/spring/src/main/java/io/seata/spring/remoting/parser/DubboRemotingParser.java @@ -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); diff --git a/spring/src/main/java/io/seata/spring/remoting/parser/HSFRemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/HSFRemotingParser.java index 5fbb4e7aaf5..6915fb3607b 100644 --- a/spring/src/main/java/io/seata/spring/remoting/parser/HSFRemotingParser.java +++ b/spring/src/main/java/io/seata/spring/remoting/parser/HSFRemotingParser.java @@ -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) { diff --git a/spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java index 3aa0ca07fbd..23970b28fcd 100644 --- a/spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java +++ b/spring/src/main/java/io/seata/spring/remoting/parser/LocalServiceRemotingParser.java @@ -46,7 +46,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(); Set> interfaceClasses = ReflectionUtil.getInterfaces(classType); diff --git a/spring/src/main/java/io/seata/spring/remoting/parser/SofaRpcRemotingParser.java b/spring/src/main/java/io/seata/spring/remoting/parser/SofaRpcRemotingParser.java index 4ea2d825117..95c0c10b949 100644 --- a/spring/src/main/java/io/seata/spring/remoting/parser/SofaRpcRemotingParser.java +++ b/spring/src/main/java/io/seata/spring/remoting/parser/SofaRpcRemotingParser.java @@ -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); 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 index 434878d7cf0..303a51197b8 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java +++ b/tcc/src/main/java/io/seata/rm/tcc/autoproxy/TccTransactionAutoProxy.java @@ -90,7 +90,7 @@ public IsTransactionProxyResult isTransactionProxyTargetBean(RemotingDesc remoti } private void registryResource(RemotingDesc remotingDesc) { - if (!remotingDesc.isReference()) { + if (remotingDesc.isService()) { try { Class interfaceClass = remotingDesc.getInterfaceClass(); Method[] methods = interfaceClass.getMethods(); 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 a16b203c304..be56b923ce2 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 @@ -47,7 +47,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(); Set> interfaceClasses = ReflectionUtil.getInterfaces(classType); From 4ab24874c893056b1a3a2b9f4c4db89864b8e293 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Sat, 23 Jul 2022 22:25:13 +0800 Subject: [PATCH 23/24] bug fix branch type --- .../saga/rm/annotation/SagaAnnotationResource.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResource.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResource.java index de9f783e4b2..4a2d278c7a3 100644 --- a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResource.java +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResource.java @@ -15,6 +15,7 @@ */ package io.seata.saga.rm.annotation; +import io.seata.core.model.BranchType; import io.seata.saga.rm.SagaResource; import java.lang.reflect.Method; @@ -95,4 +96,14 @@ public String[] getPhaseTwoCompensationKeys() { public void setPhaseTwoCompensationKeys(String[] phaseTwoCompensationKeys) { this.phaseTwoCompensationKeys = phaseTwoCompensationKeys; } + + /** + * Gets get branch type. + * + * @return the get branch type + */ + @Override + public BranchType getBranchType() { + return BranchType.SAGA_ANNOTATION; + } } From cec9e46e1cd75df2407a72a980976c4056f44d8a Mon Sep 17 00:00:00 2001 From: ruishansun Date: Sat, 23 Jul 2022 23:27:32 +0800 Subject: [PATCH 24/24] bug fix saga annotation resource id --- .../autoproxy/SagaTransactionAutoProxy.java | 3 ++- .../rm/annotation/SagaAnnotationResource.java | 26 +++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/autoproxy/SagaTransactionAutoProxy.java b/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/autoproxy/SagaTransactionAutoProxy.java index 8f0bc2fd179..e70e96a5edd 100644 --- a/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/autoproxy/SagaTransactionAutoProxy.java +++ b/saga/seata-saga-annotation-mode/src/main/java/io/seata/saga/annotation/autoproxy/SagaTransactionAutoProxy.java @@ -85,7 +85,8 @@ private void registryResource(RemotingDesc remotingDesc) { // set phase two method's keys sagaAnnotationResource.setPhaseTwoCompensationKeys(DefaultRemotingParser.get().getTwoPhaseArgs(sagaAnnotationResource.getCompensationMethod(), sagaTransactional.compensationArgsClasses())); - //registry tcc resource + //registry saga annotation resource + sagaAnnotationResource.setResourceGroupId(sagaTransactional.name()); DefaultResourceManager.get().registerResource(sagaAnnotationResource); } } diff --git a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResource.java b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResource.java index 4a2d278c7a3..0e3dcd2fe40 100644 --- a/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResource.java +++ b/saga/seata-saga-rm/src/main/java/io/seata/saga/rm/annotation/SagaAnnotationResource.java @@ -16,7 +16,7 @@ package io.seata.saga.rm.annotation; import io.seata.core.model.BranchType; -import io.seata.saga.rm.SagaResource; +import io.seata.core.model.Resource; import java.lang.reflect.Method; @@ -25,7 +25,9 @@ * * @author ruishansun */ -public class SagaAnnotationResource extends SagaResource { +public class SagaAnnotationResource implements Resource { + + private String resourceGroupId = "DEFAULT"; private Object targetBean; @@ -97,6 +99,26 @@ public void setPhaseTwoCompensationKeys(String[] phaseTwoCompensationKeys) { this.phaseTwoCompensationKeys = phaseTwoCompensationKeys; } + @Override + public String getResourceGroupId() { + return resourceGroupId; + } + + /** + * Sets resource group id. + * + * @param resourceGroupId the resource group id + */ + public void setResourceGroupId(String resourceGroupId) { + this.resourceGroupId = resourceGroupId; + } + + + @Override + public String getResourceId() { + return actionName; + } + /** * Gets get branch type. *