You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@seata.apache.org by ji...@apache.org on 2024/03/08 14:34:57 UTC
(incubator-seata) branch 2.x updated: optimize: tcc compatible (#6387)
This is an automated email from the ASF dual-hosted git repository.
jianbin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git
The following commit(s) were added to refs/heads/2.x by this push:
new 4027ff8b88 optimize: tcc compatible (#6387)
4027ff8b88 is described below
commit 4027ff8b88de6e47322058b7f11682a5b3448e09
Author: wt_better <yi...@alibaba-inc.com>
AuthorDate: Fri Mar 8 22:34:53 2024 +0800
optimize: tcc compatible (#6387)
---
changes/en-us/2.x.md | 1 +
changes/zh-cn/2.x.md | 1 +
.../io/seata/core/model/TransactionManager.java | 28 --
.../seata/core/rpc/RegisterCheckAuthHandler.java | 26 --
.../api/interceptor/ActionInterceptorHandler.java | 29 ++
.../rm/tcc/api/BusinessActionContextParameter.java | 10 +-
.../interceptor/TccActionInterceptorHandler.java | 217 ++----------
.../resource/parser/TccRegisterResourceParser.java | 56 ++--
.../seata/spring/tcc/TccAnnotationProcessor.java | 50 ---
...ation.tx.api.interceptor.parser.InterfaceParser | 3 +-
...x.api.interceptor.parser.RegisterResourceParser | 1 +
...eata.integration.tx.api.remoting.RemotingParser | 1 +
.../java/io/seata/rm/tcc/BranchSessionMock.java | 85 +++++
.../test/java/io/seata/rm/tcc/NestTccAction.java | 56 ++++
.../java/io/seata/rm/tcc/NestTccActionImpl.java | 59 ++++
.../test/java/io/seata/rm/tcc/NormalTccAction.java | 72 ++++
.../java/io/seata/rm/tcc/NormalTccActionImpl.java} | 38 ++-
.../java/io/seata/rm/tcc/Param.java} | 13 +-
.../src/test/java/io/seata/rm/tcc/TccAction.java | 67 ++++
.../test/java/io/seata/rm/tcc/TccActionImpl.java | 61 ++++
.../java/io/seata/rm/tcc/TccParam.java} | 46 ++-
.../rm/tcc/interceptor/ProxyUtilsTccTest.java | 34 +-
.../parser/TccActionInterceptorParserTest.java | 369 +++++++++++++++++++++
.../BusinessActionContextParameterDesc.java | 71 ----
.../rm/tcc/api/BusinessActionContextParameter.java | 12 +-
.../seata/spring/tcc/TccAnnotationProcessor.java | 3 +-
.../interceptor/TccActionInterceptorHandler.java | 77 +++--
.../resource/parser/TccRegisterResourceParser.java | 11 +-
.../rm/tcc/interceptor/ProxyUtilsTccTest.java | 12 +-
29 files changed, 1035 insertions(+), 474 deletions(-)
diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index c0680127c4..1f8275e60e 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -107,6 +107,7 @@ Add changes here for all PR submitted to the 2.x branch.
- [[#6386](https://github.com/apache/incubator-seata/pull/6386)] replace `byte-buddy` to JDK proxy in `ConfigurationCache`
- [[#6391](https://github.com/apache/incubator-seata/pull/6091)] forbid duplicate registration of TCC resources
- [[#6393](https://github.com/apache/incubator-seata/pull/6393)] determine the version before sync metadata and add retry mechanism
+- [[#6387](https://github.com/apache/incubator-seata/pull/6387)] optimize tcc use compatible
### refactor:
- [[#6269](https://github.com/apache/incubator-seata/pull/6269)] standardize Seata Exception
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 5d3eaf99eb..bdf42b02e5 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -111,6 +111,7 @@
- [[#6386](https://github.com/apache/incubator-seata/pull/6386)] 在 `ConfigurationCache` 类中,将 `byte-buddy` 替换为JDK代理
- [[#6391](https://github.com/apache/incubator-seata/pull/6091)] 禁止重复注册TCC资源
- [[#6393](https://github.com/apache/incubator-seata/pull/6393)] 元数据同步前判断版本,并增加重试功能
+- [[#6387](https://github.com/apache/incubator-seata/pull/6387)] 优化tcc使用兼容
### refactor:
diff --git a/compatible/src/main/java/io/seata/core/model/TransactionManager.java b/compatible/src/main/java/io/seata/core/model/TransactionManager.java
deleted file mode 100644
index 5f03357db5..0000000000
--- a/compatible/src/main/java/io/seata/core/model/TransactionManager.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.core.model;
-
-/**
- *
- *
- * Transaction Manager.
- *
- * Define a global transaction and control it.
- *
- */
-public interface TransactionManager extends org.apache.seata.core.model.TransactionManager {
-}
diff --git a/compatible/src/main/java/io/seata/core/rpc/RegisterCheckAuthHandler.java b/compatible/src/main/java/io/seata/core/rpc/RegisterCheckAuthHandler.java
deleted file mode 100644
index 42b137a475..0000000000
--- a/compatible/src/main/java/io/seata/core/rpc/RegisterCheckAuthHandler.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.core.rpc;
-
-/**
- *
- *
- * The interface Register check auth handler.
- *
- */
-public interface RegisterCheckAuthHandler extends org.apache.seata.core.rpc.RegisterCheckAuthHandler {
-}
diff --git a/compatible/src/main/java/io/seata/integration/tx/api/interceptor/ActionInterceptorHandler.java b/compatible/src/main/java/io/seata/integration/tx/api/interceptor/ActionInterceptorHandler.java
index a21b897a49..2a765ad943 100644
--- a/compatible/src/main/java/io/seata/integration/tx/api/interceptor/ActionInterceptorHandler.java
+++ b/compatible/src/main/java/io/seata/integration/tx/api/interceptor/ActionInterceptorHandler.java
@@ -16,6 +16,7 @@
*/
package io.seata.integration.tx.api.interceptor;
+import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import org.apache.seata.rm.tcc.api.ParamType;
@@ -30,6 +31,34 @@ import java.util.Map;
@Deprecated
public class ActionInterceptorHandler extends org.apache.seata.integration.tx.api.interceptor.ActionInterceptorHandler {
+ protected BusinessActionContext getOrCreateActionContextAndResetToArguments(Class<?>[] parameterTypes, Object[] arguments) {
+ BusinessActionContext actionContext = null;
+
+ // get the action context from arguments
+ int argIndex = 0;
+ for (Class<?> parameterType : parameterTypes) {
+ if (BusinessActionContext.class.isAssignableFrom(parameterType)) {
+ 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();
+ arguments[argIndex] = actionContext;
+ } else {
+ // Reset the updated, avoid unnecessary reporting
+ actionContext.setUpdated(null);
+ }
+ break;
+ }
+ argIndex++;
+ }
+
+ // if null, create a new one
+ if (actionContext == null) {
+ actionContext = new BusinessActionContext();
+ }
+ return actionContext;
+ }
+
/**
* Extracting context data from parameters, add them to the context
diff --git a/compatible/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java b/compatible/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java
index d9649587ef..ad4ef05c2f 100644
--- a/compatible/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java
+++ b/compatible/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java
@@ -29,7 +29,7 @@ public @interface BusinessActionContextParameter {
* parameter's name. Synonym for {@link #paramName()}.
*
* @return the name of the param or field
- * @see org.apache.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation
+ * @see io.seata.integration.tx.api.interceptor.ActionContextUtil#getParamNameFromAnnotation
*/
String value() default "";
@@ -37,7 +37,7 @@ public @interface BusinessActionContextParameter {
* parameter's name. Synonym for {@link #value()}.
*
* @return the name of the param or field
- * @see org.apache.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation
+ * @see io.seata.integration.tx.api.interceptor.ActionContextUtil#getParamNameFromAnnotation
*/
String paramName() default "";
@@ -54,7 +54,7 @@ public @interface BusinessActionContextParameter {
* Specify the index of the parameter in the List
*
* @return the index of the List
- * @see org.apache.seata.spring.interceptor.ActionContextUtil#getByIndex
+ * @see io.seata.integration.tx.api.interceptor.ActionContextUtil#getByIndex
*/
int index() default -1;
@@ -63,8 +63,8 @@ public @interface BusinessActionContextParameter {
* 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 org.apache.seata.spring.interceptor.ActionContextUtil#loadParamByAnnotationAndPutToContext
- * @see org.apache.seata.spring.interceptor.ActionContextUtil#fetchContextFromObject
+ * @see io.seata.integration.tx.api.interceptor.ActionContextUtil#loadParamByAnnotationAndPutToContext
+ * @see io.seata.integration.tx.api.interceptor.ActionContextUtil#fetchContextFromObject
*/
boolean isParamInProperty() default false;
}
diff --git a/compatible/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java b/compatible/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
index 25d19a588a..5b570e5b63 100644
--- a/compatible/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
+++ b/compatible/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
@@ -16,209 +16,52 @@
*/
package io.seata.rm.tcc.interceptor;
-import io.seata.core.context.RootContext;
-import io.seata.core.model.BranchType;
-import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
-import org.apache.seata.common.Constants;
-import org.apache.seata.common.holder.ObjectHolder;
-import org.apache.seata.common.util.ReflectionUtil;
-import org.apache.seata.integration.tx.api.fence.config.CommonFenceConfig;
-import org.apache.seata.integration.tx.api.interceptor.InvocationWrapper;
-import org.apache.seata.integration.tx.api.interceptor.TwoPhaseBusinessActionParam;
-import org.slf4j.MDC;
-
import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import static org.apache.seata.common.Constants.BEAN_NAME_SPRING_FENCE_CONFIG;
+import io.seata.integration.tx.api.interceptor.ActionInterceptorHandler;
+import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
+import org.apache.seata.common.Constants;
+import org.apache.seata.integration.tx.api.interceptor.TwoPhaseBusinessActionParam;
public class TccActionInterceptorHandler extends org.apache.seata.rm.tcc.interceptor.TccActionInterceptorHandler {
public TccActionInterceptorHandler(Object targetBean, Set<String> methodsToProxy) {
super(targetBean, methodsToProxy);
+ actionInterceptorHandler = new ActionInterceptorHandler();
}
@Override
- protected Object doInvoke(InvocationWrapper invocation) throws Throwable {
- if (!RootContext.inGlobalTransaction() || RootContext.inSagaBranch()) {
- //not in transaction, or this interceptor is disabled
- return invocation.proceed();
- }
- Method method = invocation.getMethod();
- TwoPhaseBusinessAction businessAction = parseAnnotation(method);
-
- //try method
- if (businessAction != null) {
- //save the xid
- String xid = RootContext.getXID();
- //save the previous branchType
- BranchType previousBranchType = RootContext.getBranchType();
- //if not TCC, bind TCC branchType
- if (BranchType.TCC != previousBranchType) {
- RootContext.bindBranchType(BranchType.TCC);
- }
- try {
- TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam();
- businessActionParam.setActionName(businessAction.name());
- businessActionParam.setDelayReport(businessAction.isDelayReport());
- businessActionParam.setUseCommonFence(businessAction.useTCCFence());
- businessActionParam.setBranchType(org.apache.seata.core.model.BranchType.TCC);
- Map<String, Object> businessActionContextMap = new HashMap<>(4);
- //the phase two method name
- businessActionContextMap.put(Constants.COMMIT_METHOD, businessAction.commitMethod());
- businessActionContextMap.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod());
- businessActionContextMap.put(Constants.ACTION_NAME, businessAction.name());
- businessActionContextMap.put(Constants.USE_COMMON_FENCE, businessAction.useTCCFence());
- businessActionParam.setBusinessActionContext(businessActionContextMap);
- //Handler the TCC Aspect, and return the business result
- return actionInterceptorHandler.proceed(method, invocation.getArguments(), xid, businessActionParam,
- invocation::proceed);
- } finally {
- //if not TCC, unbind branchType
- if (BranchType.TCC != previousBranchType) {
- RootContext.unbindBranchType();
- }
- //MDC remove branchId
- MDC.remove(org.apache.seata.core.context.RootContext.MDC_KEY_BRANCH_ID);
- }
- }
-
- //not TCC try method
- return invocation.proceed();
- }
-
- private TwoPhaseBusinessAction parseAnnotation(Method methodKey) throws NoSuchMethodException {
- TwoPhaseBusinessAction result = convertIoSeata(parseAnnotationCache.computeIfAbsent(methodKey, method -> {
- TwoPhaseBusinessAction businessAction = method.getAnnotation(TwoPhaseBusinessAction.class);
- if (businessAction == null && targetBean.getClass() != null) {
- Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(targetBean.getClass());
- if (interfaceClasses != null) {
- for (Class<?> interClass : interfaceClasses) {
- try {
- Method m = interClass.getMethod(method.getName(), method.getParameterTypes());
- businessAction = m.getAnnotation(TwoPhaseBusinessAction.class);
- if (businessAction != null) {
- // init common fence clean task if enable useTccFence
- initCommonFenceCleanTask(businessAction);
- break;
- }
- } catch (NoSuchMethodException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }
- return convertApacheSeata(businessAction);
- }));
- return result;
+ protected Class<? extends Annotation> getAnnotationClass() {
+ return TwoPhaseBusinessAction.class;
}
- private org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction convertApacheSeata(TwoPhaseBusinessAction twoPhaseBusinessAction) {
- org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction result = new org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction() {
-
- @Override
- public Class<? extends Annotation> annotationType() {
- return org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction.class;
- }
-
- @Override
- public String name() {
- return twoPhaseBusinessAction.name();
- }
-
- @Override
- public String commitMethod() {
- return twoPhaseBusinessAction.commitMethod();
- }
-
- @Override
- public String rollbackMethod() {
- return twoPhaseBusinessAction.rollbackMethod();
- }
-
- @Override
- public boolean isDelayReport() {
- return twoPhaseBusinessAction.isDelayReport();
- }
-
- @Override
- public boolean useTCCFence() {
- return twoPhaseBusinessAction.useTCCFence();
- }
-
- @Override
- public Class<?>[] commitArgsClasses() {
- return twoPhaseBusinessAction.commitArgsClasses();
- }
-
- @Override
- public Class<?>[] rollbackArgsClasses() {
- return twoPhaseBusinessAction.rollbackArgsClasses();
- }
- };
- return result;
- }
-
- private TwoPhaseBusinessAction convertIoSeata(org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction twoPhaseBusinessAction) {
- TwoPhaseBusinessAction result = new TwoPhaseBusinessAction() {
- @Override
- public Class<? extends Annotation> annotationType() {
- return TwoPhaseBusinessAction.class;
- }
-
- @Override
- public String name() {
- return twoPhaseBusinessAction.name();
- }
-
- @Override
- public String commitMethod() {
- return twoPhaseBusinessAction.commitMethod();
- }
-
- @Override
- public String rollbackMethod() {
- return twoPhaseBusinessAction.rollbackMethod();
- }
-
- @Override
- public boolean isDelayReport() {
- return twoPhaseBusinessAction.isDelayReport();
- }
-
- @Override
- public boolean useTCCFence() {
- return twoPhaseBusinessAction.useTCCFence();
- }
-
- @Override
- public Class<?>[] commitArgsClasses() {
- return twoPhaseBusinessAction.commitArgsClasses();
- }
-
- @Override
- public Class<?>[] rollbackArgsClasses() {
- return twoPhaseBusinessAction.rollbackArgsClasses();
- }
- };
- return result;
- }
-
-
- private void initCommonFenceCleanTask(TwoPhaseBusinessAction twoPhaseBusinessAction) {
- CommonFenceConfig commonFenceConfig = (CommonFenceConfig) ObjectHolder.INSTANCE.getObject(BEAN_NAME_SPRING_FENCE_CONFIG);
- if (commonFenceConfig == null || commonFenceConfig.getInitialized().get()) {
- return;
- }
- if (twoPhaseBusinessAction != null && twoPhaseBusinessAction.useTCCFence()) {
- if (commonFenceConfig.getInitialized().compareAndSet(false, true)) {
- // init common fence clean task if enable useTccFence
- commonFenceConfig.init();
- }
+ @Override
+ protected boolean parserCommonFenceConfig(Annotation annotation) {
+ if (annotation == null) {
+ return false;
}
+ TwoPhaseBusinessAction businessAction = (TwoPhaseBusinessAction) annotation;
+ return businessAction.useTCCFence();
}
+ @Override
+ protected TwoPhaseBusinessActionParam createTwoPhaseBusinessActionParam(Annotation annotation) {
+ TwoPhaseBusinessAction businessAction = (TwoPhaseBusinessAction) annotation;
+ TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam();
+ businessActionParam.setActionName(businessAction.name());
+ businessActionParam.setDelayReport(businessAction.isDelayReport());
+ businessActionParam.setUseCommonFence(businessAction.useTCCFence());
+ businessActionParam.setBranchType(getBranchType());
+ Map<String, Object> businessActionContextMap = new HashMap<>(4);
+ //the phase two method name
+ businessActionContextMap.put(Constants.COMMIT_METHOD, businessAction.commitMethod());
+ businessActionContextMap.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod());
+ businessActionContextMap.put(Constants.ACTION_NAME, businessAction.name());
+ businessActionContextMap.put(Constants.USE_COMMON_FENCE, businessAction.useTCCFence());
+ businessActionParam.setBusinessActionContext(businessActionContextMap);
+ return businessActionParam;
+ }
}
diff --git a/compatible/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java b/compatible/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
index b1570ec419..465d4337ac 100644
--- a/compatible/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
+++ b/compatible/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
@@ -16,36 +16,22 @@
*/
package io.seata.rm.tcc.resource.parser;
+import io.seata.integration.tx.api.interceptor.ActionContextUtil;
+import io.seata.rm.tcc.api.BusinessActionContext;
+import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
import org.apache.seata.common.exception.FrameworkException;
-import org.apache.seata.common.util.ReflectionUtil;
import org.apache.seata.common.util.StringUtils;
import org.apache.seata.rm.DefaultResourceManager;
import org.apache.seata.rm.tcc.TCCResource;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.HashSet;
import java.util.Set;
public class TccRegisterResourceParser extends org.apache.seata.rm.tcc.resource.parser.TccRegisterResourceParser {
- @Override
- public void registerResource(Object target, String beanName) {
- try {
- //service bean, registry resource
- Class<?> serviceClass = target.getClass();
- this.executeRegisterResource(target, new HashSet<>(Arrays.asList(serviceClass.getMethods())), target.getClass());
- Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(serviceClass);
- for (Class<?> interClass : interfaceClasses) {
- this.executeRegisterResource(target, new HashSet<>(Arrays.asList(interClass.getMethods())), interClass);
- }
- } catch (Throwable t) {
- throw new FrameworkException(t, "parser remoting service error");
- }
- }
-
- private void executeRegisterResource(Object target, Set<Method> methods, Class<?> targetServiceClass) throws NoSuchMethodException {
+ protected void executeRegisterResource(Object target, Set<Method> methods, Class<?> targetServiceClass) throws NoSuchMethodException {
for (Method m : methods) {
TwoPhaseBusinessAction twoPhaseBusinessAction = m.getAnnotation(TwoPhaseBusinessAction.class);
if (twoPhaseBusinessAction != null) {
@@ -66,13 +52,41 @@ public class TccRegisterResourceParser extends org.apache.seata.rm.tcc.resource.
tccResource.setCommitArgsClasses(twoPhaseBusinessAction.commitArgsClasses());
tccResource.setRollbackArgsClasses(twoPhaseBusinessAction.rollbackArgsClasses());
// set phase two method's keys
- tccResource.setPhaseTwoCommitKeys(this.getTwoPhaseArgs(tccResource.getCommitMethod(),
+ tccResource.setPhaseTwoCommitKeys(getTwoPhaseArgs(tccResource.getCommitMethod(),
twoPhaseBusinessAction.commitArgsClasses()));
- tccResource.setPhaseTwoRollbackKeys(this.getTwoPhaseArgs(tccResource.getRollbackMethod(),
+ tccResource.setPhaseTwoRollbackKeys(getTwoPhaseArgs(tccResource.getRollbackMethod(),
twoPhaseBusinessAction.rollbackArgsClasses()));
//registry tcc resource
DefaultResourceManager.get().registerResource(tccResource);
}
}
}
+
+ @Override
+ protected String[] getTwoPhaseArgs(Method method, Class<?>[] argsClasses) {
+ Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+ String[] keys = new String[parameterAnnotations.length];
+ /*
+ * get parameter's key
+ * if method's parameter list is like
+ * (BusinessActionContext, @BusinessActionContextParameter("a") A a, @BusinessActionContextParameter("b") B b)
+ * the keys will be [null, a, b]
+ */
+ for (int i = 0; i < parameterAnnotations.length; i++) {
+ for (int j = 0; j < parameterAnnotations[i].length; j++) {
+ if (parameterAnnotations[i][j] instanceof BusinessActionContextParameter) {
+ BusinessActionContextParameter param = (BusinessActionContextParameter) parameterAnnotations[i][j];
+ String key = ActionContextUtil.getParamNameFromAnnotation(param);
+ keys[i] = key;
+ break;
+ }
+ }
+ if (keys[i] == null && !(argsClasses[i].equals(BusinessActionContext.class))) {
+ throw new IllegalArgumentException("non-BusinessActionContext parameter should use annotation " +
+ "BusinessActionContextParameter");
+ }
+ }
+ return keys;
+ }
+
}
diff --git a/compatible/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java b/compatible/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java
deleted file mode 100644
index 9e7744928a..0000000000
--- a/compatible/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.tcc;
-
-import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
-import org.apache.seata.integration.tx.api.remoting.RemotingDesc;
-import org.apache.seata.integration.tx.api.util.ProxyUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-public class TccAnnotationProcessor extends org.apache.seata.spring.tcc.TccAnnotationProcessor {
- private static final Logger LOGGER = LoggerFactory.getLogger(org.apache.seata.spring.tcc.TccAnnotationProcessor.class);
-
- @Override
- public void addTccAdvise(Object bean, String beanName, Field field, Class serviceClass) throws IllegalAccessException {
- Object fieldValue = field.get(bean);
- if (fieldValue == null) {
- return;
- }
- for (Method method : field.getType().getMethods()) {
- if (!Modifier.isStatic(method.getModifiers()) && (method.isAnnotationPresent(TwoPhaseBusinessAction.class))) {
- RemotingDesc remotingDesc = new RemotingDesc();
- remotingDesc.setServiceClass(serviceClass);
-
- Object proxyBean = ProxyUtil.createProxy(bean, beanName);
- field.setAccessible(true);
- field.set(bean, proxyBean);
- LOGGER.info("Bean[" + bean.getClass().getName() + "] with name [" + field.getName() + "] would use proxy");
- }
- }
- }
-}
diff --git a/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.InterfaceParser b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.InterfaceParser
index b9e1043dc3..3bf5b41bb2 100644
--- a/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.InterfaceParser
+++ b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.InterfaceParser
@@ -1 +1,2 @@
-io.seata.integration.tx.api.interceptor.parser.GlobalTransactionalInterceptorParser
\ No newline at end of file
+io.seata.rm.tcc.interceptor.parser.TccActionInterceptorParser
+io.seata.integration.tx.api.interceptor.parser.GlobalTransactionalInterceptorParser
diff --git a/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.RegisterResourceParser b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.RegisterResourceParser
new file mode 100644
index 0000000000..9501e9d87c
--- /dev/null
+++ b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.RegisterResourceParser
@@ -0,0 +1 @@
+io.seata.rm.tcc.resource.parser.TccRegisterResourceParser
\ No newline at end of file
diff --git a/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.remoting.RemotingParser b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.remoting.RemotingParser
new file mode 100644
index 0000000000..78ff6f2e84
--- /dev/null
+++ b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.remoting.RemotingParser
@@ -0,0 +1 @@
+io.seata.rm.tcc.remoting.parser.LocalTCCRemotingParser
\ No newline at end of file
diff --git a/compatible/src/test/java/io/seata/rm/tcc/BranchSessionMock.java b/compatible/src/test/java/io/seata/rm/tcc/BranchSessionMock.java
new file mode 100644
index 0000000000..9ec015d11e
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/BranchSessionMock.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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;
+
+import org.apache.seata.core.model.BranchType;
+
+public class BranchSessionMock {
+
+ private String xid;
+
+ private long branchId;
+
+ private String resourceGroupId;
+
+ private String resourceId;
+
+
+ private BranchType branchType;
+
+
+ private String applicationData;
+
+
+ public String getXid() {
+ return xid;
+ }
+
+ public void setXid(String xid) {
+ this.xid = xid;
+ }
+
+ public long getBranchId() {
+ return branchId;
+ }
+
+ public void setBranchId(long branchId) {
+ this.branchId = branchId;
+ }
+
+ public String getResourceGroupId() {
+ return resourceGroupId;
+ }
+
+ public void setResourceGroupId(String resourceGroupId) {
+ this.resourceGroupId = resourceGroupId;
+ }
+
+ public String getResourceId() {
+ return resourceId;
+ }
+
+ public void setResourceId(String resourceId) {
+ this.resourceId = resourceId;
+ }
+
+ public BranchType getBranchType() {
+ return branchType;
+ }
+
+ public void setBranchType(BranchType branchType) {
+ this.branchType = branchType;
+ }
+
+ public String getApplicationData() {
+ return applicationData;
+ }
+
+ public void setApplicationData(String applicationData) {
+ this.applicationData = applicationData;
+ }
+}
diff --git a/compatible/src/test/java/io/seata/rm/tcc/NestTccAction.java b/compatible/src/test/java/io/seata/rm/tcc/NestTccAction.java
new file mode 100644
index 0000000000..fe74cc0bd0
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/NestTccAction.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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;
+
+import io.seata.rm.tcc.api.BusinessActionContext;
+import io.seata.rm.tcc.api.LocalTCC;
+import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
+
+/**
+ * The interface Tcc action.
+ */
+@LocalTCC
+public interface NestTccAction {
+
+ /**
+ * Prepare boolean.
+ *
+ * @param actionContext the action context
+ * @return the boolean
+ */
+ @TwoPhaseBusinessAction(name = "tccNestActionForCompatibleTest")
+ boolean prepare(BusinessActionContext actionContext, int count);
+
+ @TwoPhaseBusinessAction(name = "tccNestActionRequiredNewForCompatibleTest")
+ boolean prepareNestRequiredNew(BusinessActionContext actionContext, int count);
+
+ /**
+ * Commit boolean.
+ *
+ * @param actionContext the action context
+ * @return the boolean
+ */
+ boolean commit(BusinessActionContext actionContext);
+
+ /**
+ * Rollback boolean.
+ *
+ * @param actionContext the action context
+ * @return the boolean
+ */
+ boolean rollback(BusinessActionContext actionContext);
+}
diff --git a/compatible/src/test/java/io/seata/rm/tcc/NestTccActionImpl.java b/compatible/src/test/java/io/seata/rm/tcc/NestTccActionImpl.java
new file mode 100644
index 0000000000..0b34b57e9e
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/NestTccActionImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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;
+import io.seata.rm.tcc.api.BusinessActionContext;
+import io.seata.spring.annotation.GlobalTransactional;
+import io.seata.tm.api.transaction.Propagation;
+
+public class NestTccActionImpl implements NestTccAction {
+
+ private TccAction tccAction;
+ private boolean isCommit;
+
+ @Override
+ @GlobalTransactional()
+ public boolean prepare(BusinessActionContext actionContext, int count) {
+ tccAction.prepare(actionContext);
+ return count > 1;
+ }
+
+ @GlobalTransactional(propagation = Propagation.REQUIRES_NEW)
+ @Override
+ public boolean prepareNestRequiredNew(BusinessActionContext actionContext, int count) {
+ tccAction.prepare(actionContext);
+ return count > 1;
+ }
+
+ @Override
+ public boolean commit(BusinessActionContext actionContext) {
+ isCommit = true;
+ return true;
+ }
+
+ @Override
+ public boolean rollback(BusinessActionContext actionContext) {
+ return true;
+ }
+
+ public void setTccAction(TccAction tccAction) {
+ this.tccAction = tccAction;
+ }
+
+ public boolean isCommit() {
+ return isCommit;
+ }
+}
diff --git a/compatible/src/test/java/io/seata/rm/tcc/NormalTccAction.java b/compatible/src/test/java/io/seata/rm/tcc/NormalTccAction.java
new file mode 100644
index 0000000000..58221f4bae
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/NormalTccAction.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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;
+
+import java.util.List;
+
+import io.seata.rm.tcc.api.BusinessActionContext;
+import io.seata.rm.tcc.api.BusinessActionContextParameter;
+import io.seata.rm.tcc.api.LocalTCC;
+import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
+
+/**
+ * The interface Tcc action.
+ *
+ */
+@LocalTCC
+public interface NormalTccAction {
+
+ /**
+ * Prepare boolean.
+ *
+ * @param actionContext the action context
+ * @param a the a
+ * @param b the b
+ * @param tccParam the tcc param
+ * @return the boolean
+ */
+ @TwoPhaseBusinessAction(name = "tccActionForCompatibleTest", commitMethod = "commit", rollbackMethod = "rollback", commitArgsClasses = {BusinessActionContext.class, TccParam.class}, rollbackArgsClasses = {BusinessActionContext.class, TccParam.class})
+ String prepare(BusinessActionContext actionContext,
+ @BusinessActionContextParameter("a") int a,
+ @BusinessActionContextParameter(paramName = "b", index = 0) List b,
+ @BusinessActionContextParameter(isParamInProperty = true) TccParam tccParam);
+
+ /**
+ * Commit boolean.
+ *
+ * @param actionContext the action context
+ * @return the boolean
+ */
+ boolean commit(BusinessActionContext actionContext,
+ @BusinessActionContextParameter("tccParam") TccParam param);
+
+ /**
+ * Rollback boolean.
+ *
+ * @param actionContext the action context
+ * @return the boolean
+ */
+ boolean rollback(BusinessActionContext actionContext, @BusinessActionContextParameter("tccParam") TccParam param);
+
+
+ @TwoPhaseBusinessAction(name = "tccActionForCompatibleTestWithException", commitMethod = "commit", rollbackMethod = "rollback", commitArgsClasses = {BusinessActionContext.class, TccParam.class}, rollbackArgsClasses = {BusinessActionContext.class, TccParam.class})
+ String prepareWithException(BusinessActionContext actionContext,
+ @BusinessActionContextParameter("a") int a,
+ @BusinessActionContextParameter(paramName = "b", index = 0) List b,
+ @BusinessActionContextParameter(isParamInProperty = true) TccParam tccParam);
+
+}
diff --git a/compatible/src/main/java/io/seata/metrics/exporter/Exporter.java b/compatible/src/test/java/io/seata/rm/tcc/NormalTccActionImpl.java
similarity index 50%
rename from compatible/src/main/java/io/seata/metrics/exporter/Exporter.java
rename to compatible/src/test/java/io/seata/rm/tcc/NormalTccActionImpl.java
index 612b848442..b3dcc1a17b 100644
--- a/compatible/src/main/java/io/seata/metrics/exporter/Exporter.java
+++ b/compatible/src/test/java/io/seata/rm/tcc/NormalTccActionImpl.java
@@ -14,12 +14,38 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.seata.metrics.exporter;
+package io.seata.rm.tcc;
-/**
- * Exporter interface for metrics
- *
- */
-public interface Exporter extends org.apache.seata.metrics.exporter.Exporter {
+import java.util.List;
+
+import io.seata.rm.tcc.api.BusinessActionContext;
+
+
+public class NormalTccActionImpl implements NormalTccAction {
+
+ @Override
+ public String prepare(BusinessActionContext actionContext, int a, List b, TccParam tccParam) {
+ return "a";
+ }
+
+ @Override
+ public boolean commit(BusinessActionContext actionContext, TccParam param) {
+ return false;
+ }
+
+ @Override
+ public boolean rollback(BusinessActionContext actionContext, TccParam param) {
+ return false;
+ }
+
+ public boolean otherMethod() {
+ return true;
+ }
+
+ @Override
+ public String prepareWithException(BusinessActionContext actionContext, int a, List b, TccParam tccParam) {
+ throw new IllegalArgumentException();
+ }
+
}
diff --git a/compatible/src/main/java/io/seata/metrics/registry/Registry.java b/compatible/src/test/java/io/seata/rm/tcc/Param.java
similarity index 69%
rename from compatible/src/main/java/io/seata/metrics/registry/Registry.java
rename to compatible/src/test/java/io/seata/rm/tcc/Param.java
index 7bb8b78f79..65af4f832a 100644
--- a/compatible/src/main/java/io/seata/metrics/registry/Registry.java
+++ b/compatible/src/test/java/io/seata/rm/tcc/Param.java
@@ -14,12 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.seata.metrics.registry;
+package io.seata.rm.tcc;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
/**
- * Registry interface for metrics
+ * customized annotation
*
*/
-public interface Registry extends org.apache.seata.metrics.registry.Registry {
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER, ElementType.FIELD})
+public @interface Param {
+ String value() default "";
}
diff --git a/compatible/src/test/java/io/seata/rm/tcc/TccAction.java b/compatible/src/test/java/io/seata/rm/tcc/TccAction.java
new file mode 100644
index 0000000000..2f2037ebe0
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/TccAction.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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;
+
+import io.seata.rm.tcc.api.BusinessActionContext;
+import io.seata.rm.tcc.api.BusinessActionContextParameter;
+import io.seata.rm.tcc.api.LocalTCC;
+import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
+
+/**
+ * The interface Tcc action.
+ */
+@LocalTCC
+public interface TccAction {
+
+ /**
+ * Prepare boolean.
+ *
+ * @param actionContext the action context
+ * @return the boolean
+ */
+ @TwoPhaseBusinessAction(name = "tccActionForTest")
+ boolean prepare(BusinessActionContext actionContext);
+
+ /**
+ * Commit boolean.
+ *
+ * @param actionContext the action context
+ * @return the boolean
+ */
+ boolean commit(BusinessActionContext actionContext);
+
+ /**
+ * Commit boolean.
+ *
+ * @param actionContext the action context
+ * @return the boolean
+ */
+ boolean commitWithArg(BusinessActionContext actionContext, @BusinessActionContextParameter("tccParam")
+ TccParam param, @Param("a") Integer a);
+
+ /**
+ * Rollback boolean.
+ *
+ * @param actionContext the action context
+ * @return the boolean
+ */
+ boolean rollback(BusinessActionContext actionContext);
+
+ boolean rollbackWithArg(BusinessActionContext actionContext, @BusinessActionContextParameter("tccParam")
+ TccParam param);
+
+}
diff --git a/compatible/src/test/java/io/seata/rm/tcc/TccActionImpl.java b/compatible/src/test/java/io/seata/rm/tcc/TccActionImpl.java
new file mode 100644
index 0000000000..f3d5dba0f4
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/TccActionImpl.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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;
+
+import io.seata.rm.tcc.api.BusinessActionContext;
+
+/**
+ * The type Tcc action.
+ *
+ */
+public class TccActionImpl implements TccAction {
+
+ private boolean isCommit;
+
+
+ @Override
+ public boolean prepare(BusinessActionContext actionContext) {
+ return true;
+ }
+
+ @Override
+ public boolean commit(BusinessActionContext actionContext) {
+ isCommit = true;
+ return true;
+ }
+
+ @Override
+ public boolean commitWithArg(BusinessActionContext actionContext, TccParam param, Integer a) {
+ return false;
+ }
+
+
+ @Override
+ public boolean rollback(BusinessActionContext actionContext) {
+ return true;
+ }
+
+ @Override
+ public boolean rollbackWithArg(BusinessActionContext actionContext, TccParam param) {
+ return false;
+ }
+
+
+ public boolean isCommit() {
+ return isCommit;
+ }
+}
diff --git a/compatible/src/main/java/io/seata/core/model/ResourceManager.java b/compatible/src/test/java/io/seata/rm/tcc/TccParam.java
similarity index 51%
rename from compatible/src/main/java/io/seata/core/model/ResourceManager.java
rename to compatible/src/test/java/io/seata/rm/tcc/TccParam.java
index 01420df6a5..da82abaeee 100644
--- a/compatible/src/main/java/io/seata/core/model/ResourceManager.java
+++ b/compatible/src/test/java/io/seata/rm/tcc/TccParam.java
@@ -14,13 +14,53 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.seata.core.model;
+package io.seata.rm.tcc;
+import io.seata.rm.tcc.api.BusinessActionContextParameter;
/**
- * Resource Manager: common behaviors.
+ * The type Tcc param.
*
*/
-public interface ResourceManager extends org.apache.seata.core.model.ResourceManager {
+public class TccParam {
+ /**
+ * The Num.
+ */
+ protected int num;
+
+ /**
+ * The Email.
+ */
+ @BusinessActionContextParameter(paramName = "email")
+ protected String email;
+
+ /**
+ * Instantiates a new Tcc param.
+ *
+ * @param num the num
+ * @param email the email
+ */
+ public TccParam(int num, String email) {
+ this.num = num;
+ this.email = email;
+ }
+
+ /**
+ * Gets num.
+ *
+ * @return the num
+ */
+ public int getNum() {
+ return num;
+ }
+
+ /**
+ * Sets num.
+ *
+ * @param num the num
+ */
+ public void setNum(int num) {
+ this.num = num;
+ }
}
diff --git a/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java b/compatible/src/test/java/io/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
similarity index 82%
copy from tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
copy to compatible/src/test/java/io/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
index 87fb8083b1..b2ebb77c95 100644
--- a/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
+++ b/compatible/src/test/java/io/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
@@ -14,15 +14,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.seata.rm.tcc.interceptor;
+package io.seata.rm.tcc.interceptor;
-import java.io.IOException;
-import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
-import org.apache.seata.core.context.RootContext;
+import io.seata.rm.tcc.NormalTccActionImpl;
+import io.seata.rm.tcc.TccParam;
+import io.seata.core.context.RootContext;
import org.apache.seata.core.exception.TransactionException;
import org.apache.seata.core.model.BranchStatus;
import org.apache.seata.core.model.BranchType;
@@ -31,25 +32,17 @@ import org.apache.seata.core.model.Resource;
import org.apache.seata.core.model.ResourceManager;
import org.apache.seata.integration.tx.api.util.ProxyUtil;
import org.apache.seata.rm.DefaultResourceManager;
-import org.apache.seata.rm.tcc.NormalTccActionImpl;
-import org.apache.seata.rm.tcc.TccParam;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
-
public class ProxyUtilsTccTest {
private final String DEFAULT_XID = "default_xid";
- private static NormalTccActionImpl tccAction;
-
- private static NormalTccActionImpl tccActionProxy;
-
- AtomicReference<String> branchReference = new AtomicReference<String>();
+ private final AtomicReference<String> branchReference = new AtomicReference<String>();
- ResourceManager resourceManager = new ResourceManager() {
+ private final ResourceManager resourceManager = new ResourceManager() {
@Override
public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String applicationData, String lockKeys) throws TransactionException {
@@ -105,11 +98,7 @@ public class ProxyUtilsTccTest {
};
- @BeforeAll
- public static void init() throws IOException {
- tccAction = new NormalTccActionImpl();
- tccActionProxy = ProxyUtil.createProxy(tccAction);
- }
+ private final NormalTccActionImpl tccActionProxy= ProxyUtil.createProxy(new NormalTccActionImpl());
@Test
@@ -118,17 +107,16 @@ public class ProxyUtilsTccTest {
RootContext.bind(DEFAULT_XID);
TccParam tccParam = new TccParam(1, "abc@163.com");
- List<String> listB = Arrays.asList("b");
+ List<String> listB = Collections.singletonList("b");
DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
- //when
String result = tccActionProxy.prepare(null, 0, listB, tccParam);
//then
Assertions.assertEquals("a", result);
Assertions.assertNotNull(result);
- Assertions.assertEquals("normalTccActionForTest", branchReference.get());
+ Assertions.assertEquals("tccActionForCompatibleTest", branchReference.get());
}
@Test
@@ -137,7 +125,7 @@ public class ProxyUtilsTccTest {
RootContext.bind(DEFAULT_XID);
TccParam tccParam = new TccParam(1, "abc@163.com");
- List<String> listB = Arrays.asList("b");
+ List<String> listB = Collections.singletonList("b");
DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
diff --git a/compatible/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java b/compatible/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java
new file mode 100644
index 0000000000..b8dc1f9a92
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java
@@ -0,0 +1,369 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.seata.rm.tcc.interceptor.parser;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+import io.seata.core.context.RootContext;
+import io.seata.rm.tcc.BranchSessionMock;
+import io.seata.rm.tcc.NestTccAction;
+import io.seata.rm.tcc.NestTccActionImpl;
+import io.seata.rm.tcc.NormalTccActionImpl;
+import io.seata.rm.tcc.TccAction;
+import io.seata.rm.tcc.TccActionImpl;
+import io.seata.tm.api.GlobalTransaction;
+import io.seata.tm.api.GlobalTransactionContext;
+import org.apache.seata.core.exception.TransactionException;
+import org.apache.seata.core.model.BranchType;
+import org.apache.seata.core.model.GlobalStatus;
+import org.apache.seata.core.model.ResourceManager;
+import org.apache.seata.core.model.TransactionManager;
+import org.apache.seata.integration.tx.api.interceptor.handler.ProxyInvocationHandler;
+import org.apache.seata.integration.tx.api.interceptor.parser.DefaultInterfaceParser;
+import org.apache.seata.integration.tx.api.util.ProxyUtil;
+import org.apache.seata.rm.DefaultResourceManager;
+import org.apache.seata.rm.tcc.TCCResourceManager;
+import org.apache.seata.tm.TransactionManagerHolder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+
+class TccActionInterceptorParserTest {
+
+ @BeforeAll
+ public static void init() throws IOException {
+ System.setProperty("config.type", "file");
+ System.setProperty("config.file.name", "file.conf");
+ System.setProperty("txServiceGroup", "default_tx_group");
+ System.setProperty("service.vgroupMapping.default_tx_group", "default");
+ }
+
+ @Test
+ void parserInterfaceToProxy() {
+
+ //given
+ TccActionInterceptorParser tccActionInterceptorParser = new TccActionInterceptorParser();
+ NormalTccActionImpl tccAction = new NormalTccActionImpl();
+
+ //when
+ ProxyInvocationHandler proxyInvocationHandler = tccActionInterceptorParser.parserInterfaceToProxy(tccAction, tccAction.getClass().getName());
+
+ //then
+ Assertions.assertNotNull(proxyInvocationHandler);
+
+ }
+
+
+ @Test
+ public void testNestTcc_should_commit() throws Exception {
+ //given
+ RootContext.unbind();
+ DefaultResourceManager.get();
+ DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
+
+ TransactionManagerHolder.set(transactionManager);
+
+ TccActionImpl tccAction = new TccActionImpl();
+ TccAction tccActionProxy = ProxyUtil.createProxy(tccAction);
+ Assertions.assertNotNull(tccActionProxy);
+
+ NestTccActionImpl nestTccAction = new NestTccActionImpl();
+ nestTccAction.setTccAction(tccActionProxy);
+
+ //when
+ ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(nestTccAction, nestTccAction.getClass().getName());
+
+ //then
+ Assertions.assertNotNull(proxyInvocationHandler);
+
+
+ //when
+ NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction);
+ //then
+ Assertions.assertNotNull(nestTccActionProxy);
+
+
+ // transaction commit test
+ GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
+
+ try {
+ tx.begin(60000, "testBiz");
+
+ boolean result = nestTccActionProxy.prepare(null, 2);
+
+ Assertions.assertTrue(result);
+
+ if (result) {
+ tx.commit();
+ } else {
+ tx.rollback();
+ }
+ } catch (Exception exx) {
+ tx.rollback();
+ throw exx;
+ }
+
+ Assertions.assertTrue(nestTccAction.isCommit());
+ Assertions.assertTrue(tccAction.isCommit());
+
+ }
+
+
+ @Test
+ public void testNestTcc_should_rollback() throws Exception {
+ //given
+ RootContext.unbind();
+ DefaultResourceManager.get();
+ DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
+
+ TransactionManagerHolder.set(transactionManager);
+
+ TccActionImpl tccAction = new TccActionImpl();
+ TccAction tccActionProxy = ProxyUtil.createProxy(tccAction);
+ Assertions.assertNotNull(tccActionProxy);
+
+ NestTccActionImpl nestTccAction = new NestTccActionImpl();
+ nestTccAction.setTccAction(tccActionProxy);
+
+ //when
+ ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(nestTccAction, nestTccAction.getClass().getName());
+
+ //then
+ Assertions.assertNotNull(proxyInvocationHandler);
+
+
+ //when
+ NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction);
+ //then
+ Assertions.assertNotNull(nestTccActionProxy);
+
+
+ // transaction commit test
+ GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
+
+ try {
+ tx.begin(60000, "testBiz");
+
+ boolean result = nestTccActionProxy.prepare(null, 1);
+
+ Assertions.assertFalse(result);
+
+ if (result) {
+ tx.commit();
+ } else {
+ tx.rollback();
+ }
+ } catch (Exception exx) {
+ tx.rollback();
+ throw exx;
+ }
+
+ Assertions.assertFalse(nestTccAction.isCommit());
+ Assertions.assertFalse(tccAction.isCommit());
+
+ }
+
+
+ @Test
+ public void testNestTcc_required_new_should_rollback_commit() throws Exception {
+ //given
+ RootContext.unbind();
+ DefaultResourceManager.get();
+ DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
+
+ TransactionManagerHolder.set(transactionManager);
+
+ TccActionImpl tccAction = new TccActionImpl();
+ TccAction tccActionProxy = ProxyUtil.createProxy(tccAction);
+ Assertions.assertNotNull(tccActionProxy);
+
+ NestTccActionImpl nestTccAction = new NestTccActionImpl();
+ nestTccAction.setTccAction(tccActionProxy);
+
+ //when
+ ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(nestTccAction, nestTccAction.getClass().getName());
+
+ //then
+ Assertions.assertNotNull(proxyInvocationHandler);
+
+ //when
+ NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction);
+ //then
+ Assertions.assertNotNull(nestTccActionProxy);
+
+
+ // transaction commit test
+ GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
+
+ try {
+ tx.begin(60000, "testBiz");
+
+ boolean result = nestTccActionProxy.prepareNestRequiredNew(null, 1);
+
+ Assertions.assertFalse(result);
+
+ if (result) {
+ tx.commit();
+ } else {
+ tx.rollback();
+ }
+ } catch (Exception exx) {
+ tx.rollback();
+ throw exx;
+ }
+
+ Assertions.assertTrue(nestTccAction.isCommit());
+ Assertions.assertTrue(tccAction.isCommit());
+
+ }
+
+
+
+ @Test
+ public void testNestTcc_required_new_should_both_commit() throws Exception {
+ //given
+ RootContext.unbind();
+ DefaultResourceManager.get();
+ DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
+
+ TransactionManagerHolder.set(transactionManager);
+
+ TccActionImpl tccAction = new TccActionImpl();
+ TccAction tccActionProxy = ProxyUtil.createProxy(tccAction);
+ Assertions.assertNotNull(tccActionProxy);
+
+ NestTccActionImpl nestTccAction = new NestTccActionImpl();
+ nestTccAction.setTccAction(tccActionProxy);
+
+ //when
+ ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(nestTccAction, nestTccAction.getClass().getName());
+
+ //then
+ Assertions.assertNotNull(proxyInvocationHandler);
+
+ //when
+ NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction);
+ //then
+ Assertions.assertNotNull(nestTccActionProxy);
+
+
+ // transaction commit test
+ GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
+
+ try {
+ tx.begin(60000, "testBiz");
+
+ boolean result = nestTccActionProxy.prepareNestRequiredNew(null, 2);
+
+ Assertions.assertTrue(result);
+
+ if (result) {
+ tx.commit();
+ } else {
+ tx.rollback();
+ }
+ } catch (Exception exx) {
+ tx.rollback();
+ throw exx;
+ }
+
+ Assertions.assertTrue(nestTccAction.isCommit());
+ Assertions.assertTrue(tccAction.isCommit());
+
+ }
+
+
+
+ private static Map<String, List<BranchSessionMock>> applicationDataMap = new ConcurrentHashMap<>();
+
+
+ private static TransactionManager transactionManager = new TransactionManager() {
+ @Override
+ public String begin(String applicationId, String transactionServiceGroup, String name, int timeout) throws TransactionException {
+ return UUID.randomUUID().toString();
+ }
+
+ @Override
+ public GlobalStatus commit(String xid) throws TransactionException {
+ commitAll(xid);
+ return GlobalStatus.Committed;
+ }
+
+ @Override
+ public GlobalStatus rollback(String xid) throws TransactionException {
+
+ rollbackAll(xid);
+
+ return GlobalStatus.Rollbacked;
+ }
+
+ @Override
+ public GlobalStatus getStatus(String xid) throws TransactionException {
+ return GlobalStatus.Begin;
+ }
+
+ @Override
+ public GlobalStatus globalReport(String xid, GlobalStatus globalStatus) throws TransactionException {
+ return globalStatus;
+ }
+ };
+
+
+ private static ResourceManager resourceManager = new TCCResourceManager() {
+
+ @Override
+ public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String applicationData, String lockKeys) throws TransactionException {
+
+ long branchId = System.currentTimeMillis();
+
+ List<BranchSessionMock> branches = applicationDataMap.computeIfAbsent(xid, s -> new ArrayList<>());
+ BranchSessionMock branchSessionMock = new BranchSessionMock();
+ branchSessionMock.setXid(xid);
+ branchSessionMock.setBranchType(branchType);
+ branchSessionMock.setResourceId(resourceId);
+ branchSessionMock.setApplicationData(applicationData);
+ branchSessionMock.setBranchId(branchId);
+
+ branches.add(branchSessionMock);
+
+ return branchId;
+ }
+ };
+
+ public static void commitAll(String xid) throws TransactionException {
+
+ List<BranchSessionMock> branches = applicationDataMap.computeIfAbsent(xid, s -> new ArrayList<>());
+ for (BranchSessionMock branch : branches) {
+ resourceManager.branchCommit(branch.getBranchType(), branch.getXid(), branch.getBranchId(), branch.getResourceId(), branch.getApplicationData());
+ }
+ }
+
+ public static void rollbackAll(String xid) throws TransactionException {
+
+ List<BranchSessionMock> branches = applicationDataMap.computeIfAbsent(xid, s -> new ArrayList<>());
+ for (BranchSessionMock branch : branches) {
+ resourceManager.branchRollback(branch.getBranchType(), branch.getXid(), branch.getBranchId(), branch.getResourceId(), branch.getApplicationData());
+ }
+ }
+
+}
diff --git a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/annotation/BusinessActionContextParameterDesc.java b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/annotation/BusinessActionContextParameterDesc.java
deleted file mode 100644
index a68010fa7d..0000000000
--- a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/annotation/BusinessActionContextParameterDesc.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.seata.integration.tx.api.annotation;
-
-import java.lang.annotation.Annotation;
-
-import org.apache.seata.common.util.StringUtils;
-import org.apache.seata.rm.tcc.api.BusinessActionContextParameter;
-
-
-public class BusinessActionContextParameterDesc {
- private String paramName;
- private int index;
- private boolean isParamInProperty;
-
- private BusinessActionContextParameterDesc() {
- }
-
- public static BusinessActionContextParameterDesc createFromBusinessActionContextParameter(Annotation annotation) {
- if (annotation == null) {
- return null;
- }
- BusinessActionContextParameterDesc businessActionContextParameterDesc = null;
- if (annotation instanceof BusinessActionContextParameter) {
- businessActionContextParameterDesc = new BusinessActionContextParameterDesc();
- BusinessActionContextParameter businessActionContextParameter = (BusinessActionContextParameter) annotation;
- businessActionContextParameterDesc.setIndex(businessActionContextParameter.index());
- businessActionContextParameterDesc.setParamInProperty(businessActionContextParameter.isParamInProperty());
- businessActionContextParameterDesc.setParamName(StringUtils.isNotBlank(businessActionContextParameter.paramName()) ? businessActionContextParameter.paramName() : businessActionContextParameter.value());
- }
- return businessActionContextParameterDesc;
- }
-
- public String getParamName() {
- return paramName;
- }
-
- public void setParamName(String paramName) {
- this.paramName = paramName;
- }
-
- public int getIndex() {
- return index;
- }
-
- public void setIndex(int index) {
- this.index = index;
- }
-
- public boolean isParamInProperty() {
- return isParamInProperty;
- }
-
- public void setParamInProperty(boolean paramInProperty) {
- isParamInProperty = paramInProperty;
- }
-}
diff --git a/integration-tx-api/src/main/java/org/apache/seata/rm/tcc/api/BusinessActionContextParameter.java b/integration-tx-api/src/main/java/org/apache/seata/rm/tcc/api/BusinessActionContextParameter.java
index ca485f1c9b..f2a37ef56e 100644
--- a/integration-tx-api/src/main/java/org/apache/seata/rm/tcc/api/BusinessActionContextParameter.java
+++ b/integration-tx-api/src/main/java/org/apache/seata/rm/tcc/api/BusinessActionContextParameter.java
@@ -26,7 +26,7 @@ import java.lang.annotation.Target;
* <p>
* add this annotation on the parameters of the try method, and the parameters will be passed to the action context
*
- * @see org.apache.seata.spring.interceptor.ActionContextUtil
+ * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD})
@@ -36,7 +36,7 @@ public @interface BusinessActionContextParameter {
* parameter's name. Synonym for {@link #paramName()}.
*
* @return the name of the param or field
- * @see org.apache.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation
+ * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil#getParamNameFromAnnotation
*/
String value() default "";
@@ -44,7 +44,7 @@ public @interface BusinessActionContextParameter {
* parameter's name. Synonym for {@link #value()}.
*
* @return the name of the param or field
- * @see org.apache.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation
+ * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil#getParamNameFromAnnotation
*/
String paramName() default "";
@@ -61,7 +61,7 @@ public @interface BusinessActionContextParameter {
* Specify the index of the parameter in the List
*
* @return the index of the List
- * @see org.apache.seata.spring.interceptor.ActionContextUtil#getByIndex
+ * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil#getByIndex
*/
int index() default -1;
@@ -70,8 +70,8 @@ public @interface BusinessActionContextParameter {
* 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 org.apache.seata.spring.interceptor.ActionContextUtil#loadParamByAnnotationAndPutToContext
- * @see org.apache.seata.spring.interceptor.ActionContextUtil#fetchContextFromObject
+ * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil#loadParamByAnnotationAndPutToContext
+ * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil#fetchContextFromObject
*/
boolean isParamInProperty() default false;
}
diff --git a/spring/src/main/java/org/apache/seata/spring/tcc/TccAnnotationProcessor.java b/spring/src/main/java/org/apache/seata/spring/tcc/TccAnnotationProcessor.java
index 06afa1d7b1..448167439a 100644
--- a/spring/src/main/java/org/apache/seata/spring/tcc/TccAnnotationProcessor.java
+++ b/spring/src/main/java/org/apache/seata/spring/tcc/TccAnnotationProcessor.java
@@ -37,8 +37,9 @@ import java.util.Set;
/**
* An annotation adapter for TCC
- *
+ * Deprecated: Tcc advice move to rm side
*/
+@Deprecated
public class TccAnnotationProcessor implements BeanPostProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(TccAnnotationProcessor.class);
diff --git a/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java b/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
index 82a7d6a7dc..acf84663c1 100644
--- a/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
+++ b/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
@@ -16,6 +16,7 @@
*/
package org.apache.seata.rm.tcc.interceptor;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@@ -53,7 +54,7 @@ public class TccActionInterceptorHandler extends AbstractProxyInvocationHandler
private Set<String> methodsToProxy;
protected Object targetBean;
- protected Map<Method, TwoPhaseBusinessAction> parseAnnotationCache = new ConcurrentHashMap<>();
+ protected Map<Method, Annotation> parseAnnotationCache = new ConcurrentHashMap<>();
public TccActionInterceptorHandler(Object targetBean, Set<String> methodsToProxy) {
this.targetBean = targetBean;
@@ -67,7 +68,7 @@ public class TccActionInterceptorHandler extends AbstractProxyInvocationHandler
return invocation.proceed();
}
Method method = invocation.getMethod();
- TwoPhaseBusinessAction businessAction = parseAnnotation(method);
+ Annotation businessAction = parseAnnotation(method);
//try method
if (businessAction != null) {
@@ -76,28 +77,17 @@ public class TccActionInterceptorHandler extends AbstractProxyInvocationHandler
//save the previous branchType
BranchType previousBranchType = RootContext.getBranchType();
//if not TCC, bind TCC branchType
- if (BranchType.TCC != previousBranchType) {
- RootContext.bindBranchType(BranchType.TCC);
+ if (getBranchType() != previousBranchType) {
+ RootContext.bindBranchType(getBranchType());
}
try {
- TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam();
- businessActionParam.setActionName(businessAction.name());
- businessActionParam.setDelayReport(businessAction.isDelayReport());
- businessActionParam.setUseCommonFence(businessAction.useTCCFence());
- businessActionParam.setBranchType(BranchType.TCC);
- Map<String, Object> businessActionContextMap = new HashMap<>(4);
- //the phase two method name
- businessActionContextMap.put(Constants.COMMIT_METHOD, businessAction.commitMethod());
- businessActionContextMap.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod());
- businessActionContextMap.put(Constants.ACTION_NAME, businessAction.name());
- businessActionContextMap.put(Constants.USE_COMMON_FENCE, businessAction.useTCCFence());
- businessActionParam.setBusinessActionContext(businessActionContextMap);
+ TwoPhaseBusinessActionParam businessActionParam = createTwoPhaseBusinessActionParam(businessAction);
//Handler the TCC Aspect, and return the business result
return actionInterceptorHandler.proceed(method, invocation.getArguments(), xid, businessActionParam,
invocation::proceed);
} finally {
//if not TCC, unbind branchType
- if (BranchType.TCC != previousBranchType) {
+ if (getBranchType() != previousBranchType) {
RootContext.unbindBranchType();
}
//MDC remove branchId
@@ -109,19 +99,19 @@ public class TccActionInterceptorHandler extends AbstractProxyInvocationHandler
return invocation.proceed();
}
- private TwoPhaseBusinessAction parseAnnotation(Method methodKey) throws NoSuchMethodException {
- TwoPhaseBusinessAction result = parseAnnotationCache.computeIfAbsent(methodKey, method -> {
- TwoPhaseBusinessAction businessAction = method.getAnnotation(TwoPhaseBusinessAction.class);
- if (businessAction == null && targetBean.getClass() != null) {
+ private Annotation parseAnnotation(Method methodKey) throws NoSuchMethodException {
+ Annotation result = parseAnnotationCache.computeIfAbsent(methodKey, method -> {
+ Annotation twoPhaseBusinessAction = method.getAnnotation(getAnnotationClass());
+ if (twoPhaseBusinessAction == null && targetBean.getClass() != null) {
Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(targetBean.getClass());
if (interfaceClasses != null) {
for (Class<?> interClass : interfaceClasses) {
try {
Method m = interClass.getMethod(method.getName(), method.getParameterTypes());
- businessAction = m.getAnnotation(TwoPhaseBusinessAction.class);
- if (businessAction != null) {
+ twoPhaseBusinessAction = m.getAnnotation(getAnnotationClass());
+ if (twoPhaseBusinessAction != null) {
// init common fence clean task if enable useTccFence
- initCommonFenceCleanTask(businessAction);
+ initCommonFenceCleanTask(twoPhaseBusinessAction);
break;
}
} catch (NoSuchMethodException e) {
@@ -130,22 +120,55 @@ public class TccActionInterceptorHandler extends AbstractProxyInvocationHandler
}
}
}
- return businessAction;
+ return twoPhaseBusinessAction;
});
return result;
}
+ protected TwoPhaseBusinessActionParam createTwoPhaseBusinessActionParam(Annotation annotation) {
+ TwoPhaseBusinessAction businessAction = (TwoPhaseBusinessAction) annotation;
+ TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam();
+ businessActionParam.setActionName(businessAction.name());
+ businessActionParam.setDelayReport(businessAction.isDelayReport());
+ businessActionParam.setUseCommonFence(businessAction.useTCCFence());
+ businessActionParam.setBranchType(getBranchType());
+ Map<String, Object> businessActionContextMap = new HashMap<>(4);
+ //the phase two method name
+ businessActionContextMap.put(Constants.COMMIT_METHOD, businessAction.commitMethod());
+ businessActionContextMap.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod());
+ businessActionContextMap.put(Constants.ACTION_NAME, businessAction.name());
+ businessActionContextMap.put(Constants.USE_COMMON_FENCE, businessAction.useTCCFence());
+ businessActionParam.setBusinessActionContext(businessActionContextMap);
+ return businessActionParam;
+ }
+
+ protected boolean parserCommonFenceConfig(Annotation annotation) {
+ if (annotation == null) {
+ return false;
+ }
+ TwoPhaseBusinessAction businessAction = (TwoPhaseBusinessAction) annotation;
+ return businessAction.useTCCFence();
+ }
+
+ protected BranchType getBranchType() {
+ return BranchType.TCC;
+ }
+
+ protected Class<? extends Annotation> getAnnotationClass() {
+ return TwoPhaseBusinessAction.class;
+ }
+
/**
* init common fence clean task if enable useTccFence
*
* @param twoPhaseBusinessAction the twoPhaseBusinessAction
*/
- private void initCommonFenceCleanTask(TwoPhaseBusinessAction twoPhaseBusinessAction) {
+ private void initCommonFenceCleanTask(Annotation twoPhaseBusinessAction) {
CommonFenceConfig commonFenceConfig = (CommonFenceConfig) ObjectHolder.INSTANCE.getObject(BEAN_NAME_SPRING_FENCE_CONFIG);
if (commonFenceConfig == null || commonFenceConfig.getInitialized().get()) {
return;
}
- if (twoPhaseBusinessAction != null && twoPhaseBusinessAction.useTCCFence()) {
+ if (twoPhaseBusinessAction != null && parserCommonFenceConfig(twoPhaseBusinessAction)) {
if (commonFenceConfig.getInitialized().compareAndSet(false, true)) {
// init common fence clean task if enable useTccFence
commonFenceConfig.init();
diff --git a/tcc/src/main/java/org/apache/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java b/tcc/src/main/java/org/apache/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
index d95e54e9d3..0d72824bf9 100644
--- a/tcc/src/main/java/org/apache/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
+++ b/tcc/src/main/java/org/apache/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
@@ -40,17 +40,18 @@ public class TccRegisterResourceParser implements RegisterResourceParser {
try {
//service bean, registry resource
Class<?> serviceClass = target.getClass();
- this.executeRegisterResource(target, new HashSet<>(Arrays.asList(serviceClass.getMethods())), target.getClass());
+ executeRegisterResource(target, new HashSet<>(Arrays.asList(serviceClass.getMethods())), target.getClass());
Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(serviceClass);
for (Class<?> interClass : interfaceClasses) {
- this.executeRegisterResource(target, new HashSet<>(Arrays.asList(interClass.getMethods())), interClass);
+ executeRegisterResource(target, new HashSet<>(Arrays.asList(interClass.getMethods())), interClass);
}
} catch (Throwable t) {
throw new FrameworkException(t, "parser remoting service error");
}
}
- private void executeRegisterResource(Object target, Set<Method> methods, Class<?> targetServiceClass) throws NoSuchMethodException {
+
+ protected void executeRegisterResource(Object target, Set<Method> methods, Class<?> targetServiceClass) throws NoSuchMethodException {
for (Method m : methods) {
TwoPhaseBusinessAction twoPhaseBusinessAction = m.getAnnotation(TwoPhaseBusinessAction.class);
if (twoPhaseBusinessAction != null) {
@@ -71,9 +72,9 @@ public class TccRegisterResourceParser implements RegisterResourceParser {
tccResource.setCommitArgsClasses(twoPhaseBusinessAction.commitArgsClasses());
tccResource.setRollbackArgsClasses(twoPhaseBusinessAction.rollbackArgsClasses());
// set phase two method's keys
- tccResource.setPhaseTwoCommitKeys(this.getTwoPhaseArgs(tccResource.getCommitMethod(),
+ tccResource.setPhaseTwoCommitKeys(getTwoPhaseArgs(tccResource.getCommitMethod(),
twoPhaseBusinessAction.commitArgsClasses()));
- tccResource.setPhaseTwoRollbackKeys(this.getTwoPhaseArgs(tccResource.getRollbackMethod(),
+ tccResource.setPhaseTwoRollbackKeys(getTwoPhaseArgs(tccResource.getRollbackMethod(),
twoPhaseBusinessAction.rollbackArgsClasses()));
//registry tcc resource
DefaultResourceManager.get().registerResource(tccResource);
diff --git a/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java b/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
index 87fb8083b1..5149377c4d 100644
--- a/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
+++ b/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
@@ -16,7 +16,6 @@
*/
package org.apache.seata.rm.tcc.interceptor;
-import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -34,7 +33,6 @@ import org.apache.seata.rm.DefaultResourceManager;
import org.apache.seata.rm.tcc.NormalTccActionImpl;
import org.apache.seata.rm.tcc.TccParam;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -42,10 +40,6 @@ public class ProxyUtilsTccTest {
private final String DEFAULT_XID = "default_xid";
- private static NormalTccActionImpl tccAction;
-
- private static NormalTccActionImpl tccActionProxy;
-
AtomicReference<String> branchReference = new AtomicReference<String>();
@@ -105,11 +99,7 @@ public class ProxyUtilsTccTest {
};
- @BeforeAll
- public static void init() throws IOException {
- tccAction = new NormalTccActionImpl();
- tccActionProxy = ProxyUtil.createProxy(tccAction);
- }
+ private final NormalTccActionImpl tccActionProxy= ProxyUtil.createProxy(new NormalTccActionImpl());
@Test
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org
For additional commands, e-mail: notifications-help@seata.apache.org