This is an automated email from the ASF dual-hosted git repository.
funky-eyes 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 1edc3e7ef4 reactor: refactor the integration-RPC module (#8103)
1edc3e7ef4 is described below
commit 1edc3e7ef44aa90599828b84b62b389ec914953a
Author: jimin <[email protected]>
AuthorDate: Mon May 25 10:13:59 2026 +0800
reactor: refactor the integration-RPC module (#8103)
---
.../etcd3/EtcdRegistryServiceImplMockTest.java | 55 +++++-
.../TransactionPropagationClientInterceptor.java | 54 ++----
.../TransactionPropagationServerInterceptor.java | 68 +++-----
extensions/rpc/seata-dubbo-alibaba/pom.xml | 2 +-
.../AlibabaDubboTransactionConsumerFilter.java | 46 ++---
.../AlibabaDubboTransactionProviderFilter.java | 132 +-------------
extensions/rpc/seata-grpc/pom.xml | 2 +-
.../client/ClientTransactionInterceptor.java | 19 ++-
.../interceptor/server/ServerListenerProxy.java | 54 +-----
.../server/ServerTransactionInterceptor.java | 48 +-----
.../server/ServerListenerProxyTest.java | 14 +-
.../server/ServerTransactionInterceptorTest.java | 16 --
extensions/rpc/seata-hsf/pom.xml | 2 +-
.../hsf/HsfTransactionConsumerFilter.java | 72 ++------
.../hsf/HsfTransactionProviderFilter.java | 159 ++---------------
.../integration/hsf/HsfTransactionFilterTest.java | 190 +++++++++++++++++++++
extensions/rpc/seata-http-jakarta/pom.xml | 6 +
.../http/JakartaSeataWebMvcConfigurerTest.java | 42 +++++
...kartaTransactionPropagationInterceptorTest.java | 116 +++++++++++++
extensions/rpc/seata-motan/pom.xml | 2 +-
.../motan/MotanTransactionConsumerFilter.java | 51 ++++++
.../integration/motan/MotanTransactionFilter.java | 114 -------------
.../motan/MotanTransactionProviderFilter.java | 57 +++++++
.../services/com.weibo.api.motan.filter.Filter | 3 +-
.../seata/integration/rpc/core/BaseRpcFilter.java | 59 -------
.../integration/rpc/core/ConsumerRpcFilter.java | 91 ----------
.../integration/rpc/core/ProviderRpcFilter.java | 110 ------------
.../rpc/core/TransactionPropagationHandler.java | 77 +++++++++
.../core/TransactionPropagationHandlerTest.java | 140 +++++++++++++++
extensions/rpc/seata-sofa-rpc/pom.xml | 2 +-
.../sofa/rpc/TransactionContextConsumerFilter.java | 91 +---------
.../sofa/rpc/TransactionContextProviderFilter.java | 83 +--------
.../seata/rm/datasource/ConnectionProxyTest.java | 77 +++++----
.../seata/rm/datasource/DataSourceProxyTest.java | 9 +-
.../seata/core/rpc/netty/TmNettyClientTest.java | 4 +-
35 files changed, 912 insertions(+), 1155 deletions(-)
diff --git
a/discovery/seata-discovery-etcd3/src/test/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImplMockTest.java
b/discovery/seata-discovery-etcd3/src/test/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImplMockTest.java
index 93b3cf20c1..e3c52f04b8 100644
---
a/discovery/seata-discovery-etcd3/src/test/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImplMockTest.java
+++
b/discovery/seata-discovery-etcd3/src/test/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImplMockTest.java
@@ -53,8 +53,11 @@ import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -100,7 +103,7 @@ public class EtcdRegistryServiceImplMockTest {
private static final String CLUSTER_NAME = "default";
@BeforeEach
- public void setUp() throws NoSuchFieldException, IllegalAccessException {
+ public void setUp() throws Exception {
MockitoAnnotations.openMocks(this);
registryService = (EtcdRegistryServiceImpl) spy(new
EtcdRegistryProvider().provide());
@@ -109,18 +112,64 @@ public class EtcdRegistryServiceImplMockTest {
when(mockClient.getWatchClient()).thenReturn(mockWatchClient);
when(mockClient.getKVClient()).thenReturn(mockKVClient);
- // inject spy executorService
+ // cancel any running lifeKeeper from previous tests
+ Field lifeKeeperFutureField =
EtcdRegistryServiceImpl.class.getDeclaredField("lifeKeeperFuture");
+ lifeKeeperFutureField.setAccessible(true);
+ Future<?> oldFuture = (Future<?>)
lifeKeeperFutureField.get(registryService);
+ if (oldFuture != null) {
+ oldFuture.cancel(true);
+ }
+ lifeKeeperFutureField.set(registryService, null);
+
+ // reset lifeKeeper
+ Field lifeKeeperField =
EtcdRegistryServiceImpl.class.getDeclaredField("lifeKeeper");
+ lifeKeeperField.setAccessible(true);
+ lifeKeeperField.set(registryService, null);
+
+ // reset static leaseId
+ Field leaseIdField =
EtcdRegistryServiceImpl.class.getDeclaredField("leaseId");
+ leaseIdField.setAccessible(true);
+ leaseIdField.set(null, 0L);
+
+ // shutdown old executor and create a fresh one
Field executorServiceField =
EtcdRegistryServiceImpl.class.getDeclaredField("executorService");
executorServiceField.setAccessible(true);
- executorService = spy((ExecutorService)
executorServiceField.get(registryService));
+ ExecutorService oldExecutor = (ExecutorService)
executorServiceField.get(registryService);
+ if (oldExecutor != null && !oldExecutor.isShutdown()) {
+ oldExecutor.shutdownNow();
+ }
+ ExecutorService freshExecutor = new
java.util.concurrent.ThreadPoolExecutor(
+ 2, 2, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new
LinkedBlockingQueue<>());
+ executorService = spy(freshExecutor);
executorServiceField.set(registryService, executorService);
+ // clear internal maps
+ Field clusterAddressMapField =
EtcdRegistryServiceImpl.class.getDeclaredField("clusterAddressMap");
+ clusterAddressMapField.setAccessible(true);
+ clusterAddressMapField.set(registryService, new ConcurrentHashMap<>());
+ Field listenerMapField =
EtcdRegistryServiceImpl.class.getDeclaredField("listenerMap");
+ listenerMapField.setAccessible(true);
+ listenerMapField.set(registryService, new ConcurrentHashMap<>());
+ Field watcherMapField =
EtcdRegistryServiceImpl.class.getDeclaredField("watcherMap");
+ watcherMapField.setAccessible(true);
+ watcherMapField.set(registryService, new ConcurrentHashMap<>());
+
// inject mock client
Field clientField =
EtcdRegistryServiceImpl.class.getDeclaredField("client");
clientField.setAccessible(true);
clientField.set(registryService, mockClient);
}
+ @org.junit.jupiter.api.AfterEach
+ public void tearDown() throws Exception {
+ Field executorServiceField =
EtcdRegistryServiceImpl.class.getDeclaredField("executorService");
+ executorServiceField.setAccessible(true);
+ ExecutorService executor = (ExecutorService)
executorServiceField.get(registryService);
+ if (executor != null && !executor.isShutdown()) {
+ executor.shutdownNow();
+ }
+ }
+
@BeforeAll
public static void beforeClass() {
String endPoint = String.format("http://%s:%s", HOST, PORT);
diff --git
a/extensions/rpc/seata-brpc/src/main/java/org/apache/seata/integration/brpc/TransactionPropagationClientInterceptor.java
b/extensions/rpc/seata-brpc/src/main/java/org/apache/seata/integration/brpc/TransactionPropagationClientInterceptor.java
index 123be97b68..913bffcc22 100644
---
a/extensions/rpc/seata-brpc/src/main/java/org/apache/seata/integration/brpc/TransactionPropagationClientInterceptor.java
+++
b/extensions/rpc/seata-brpc/src/main/java/org/apache/seata/integration/brpc/TransactionPropagationClientInterceptor.java
@@ -20,55 +20,33 @@ import com.baidu.brpc.interceptor.AbstractInterceptor;
import com.baidu.brpc.interceptor.InterceptorChain;
import com.baidu.brpc.protocol.Request;
import com.baidu.brpc.protocol.Response;
-import org.apache.seata.integration.rpc.core.ConsumerRpcFilter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
import java.util.HashMap;
import java.util.Map;
-/**
- * load SEATA xid for brpc request
- *
- */
-public class TransactionPropagationClientInterceptor extends
AbstractInterceptor implements ConsumerRpcFilter<Request> {
-
- private static final Logger LOGGER =
LoggerFactory.getLogger(TransactionPropagationClientInterceptor.class);
+public class TransactionPropagationClientInterceptor extends
AbstractInterceptor {
@Override
public void aroundProcess(Request brpcRequest, Response brpcResponse,
InterceptorChain chain) throws Exception {
-
- Map<String, String> rootContexts = getRootContexts();
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("SEATA-BRPC context:{}",
getJsonContext(rootContexts));
+ Map<String, String> context =
TransactionPropagationHandler.getTransactionPropagationContext();
+ if (!context.isEmpty()) {
+ Map<String, Object> kvAttachment = brpcRequest.getKvAttachment();
+ if (kvAttachment == null) {
+ kvAttachment = new HashMap<>();
+ brpcRequest.setKvAttachment(kvAttachment);
+ }
+ kvAttachment.putAll(context);
}
-
- if (null != getXidFromRootContexts(rootContexts)) {
- bindContextsToRequest(brpcRequest, rootContexts);
- }
-
try {
chain.intercept(brpcRequest, brpcResponse);
} finally {
- cleanRequestContexts(brpcRequest, rootContexts);
- }
- }
-
- @Override
- public void bindContextToRequest(Request rpcRequest, String key, String
value) {
- Map<String, Object> kvAttachment = rpcRequest.getKvAttachment();
- if (null == kvAttachment) {
- kvAttachment = new HashMap<>();
- rpcRequest.setKvAttachment(kvAttachment);
- }
- kvAttachment.put(key, value);
- }
-
- @Override
- public void cleanRequestContext(Request rpcRequest, String key) {
- Map<String, Object> requestAttachment = rpcRequest.getKvAttachment();
- if (null != requestAttachment) {
- requestAttachment.remove(key);
+ Map<String, Object> kvAttachment = brpcRequest.getKvAttachment();
+ if (kvAttachment != null) {
+ for (String key : context.keySet()) {
+ kvAttachment.remove(key);
+ }
+ }
}
}
}
diff --git
a/extensions/rpc/seata-brpc/src/main/java/org/apache/seata/integration/brpc/TransactionPropagationServerInterceptor.java
b/extensions/rpc/seata-brpc/src/main/java/org/apache/seata/integration/brpc/TransactionPropagationServerInterceptor.java
index 2cb2f37de6..efdd56e0e8 100644
---
a/extensions/rpc/seata-brpc/src/main/java/org/apache/seata/integration/brpc/TransactionPropagationServerInterceptor.java
+++
b/extensions/rpc/seata-brpc/src/main/java/org/apache/seata/integration/brpc/TransactionPropagationServerInterceptor.java
@@ -21,70 +21,40 @@ import com.baidu.brpc.interceptor.InterceptorChain;
import com.baidu.brpc.protocol.Request;
import com.baidu.brpc.protocol.Response;
import org.apache.seata.core.context.RootContext;
-import org.apache.seata.integration.rpc.core.ProviderRpcFilter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
import java.util.Map;
-/**
- * <p>1. load SEATA xid from brpc request in handleRequest</p>
- * <p>2. clear SEATA xid when brpc request done in aroundProcess</p>
- *
- */
-public class TransactionPropagationServerInterceptor extends
AbstractInterceptor implements ProviderRpcFilter<Request> {
-
- private static final Logger LOGGER =
LoggerFactory.getLogger(TransactionPropagationServerInterceptor.class);
-
- @Override
- public boolean handleRequest(Request request) {
-
- Map<String, String> rpcContexts = getRpcContexts(request);
- String xid = RootContext.getXID();
- String rpcXid = getXidFromContexts(rpcContexts);
- if (null == xid) {
- if (null != rpcXid) {
- bindRequestToContexts(rpcContexts);
- if (LOGGER.isInfoEnabled()) {
- LOGGER.info("SEATA-BRPC bind {} to RootContext",
getJsonContext(rpcContexts));
- }
- }
- }
-
- return super.handleRequest(request);
- }
+public class TransactionPropagationServerInterceptor extends
AbstractInterceptor {
@Override
public void aroundProcess(Request brpcRequest, Response brpcResponse,
InterceptorChain chain) throws Exception {
-
+ String rpcXid = getXidFromRequest(brpcRequest);
+ String rpcBranchType = getAttachment(brpcRequest,
RootContext.KEY_BRANCH_TYPE);
+ boolean bound =
TransactionPropagationHandler.bindProviderContext(rpcXid, rpcBranchType);
try {
chain.intercept(brpcRequest, brpcResponse);
} finally {
- Map<String, String> rootContexts = cleanRootContexts();
- Map<String, String> rpcContexts = getRpcContexts(brpcRequest);
- String rpcXid = getXidFromContexts(rpcContexts);
- String xid = getXidFromContexts(rootContexts);
- if (LOGGER.isInfoEnabled()) {
- LOGGER.info("SEATA-BRPC unbind {} from RootContext",
getJsonContext(rootContexts));
- }
- if (null != rpcXid && !rpcXid.equalsIgnoreCase(xid)) {
- if (LOGGER.isWarnEnabled()) {
- LOGGER.warn(
- "SEATA-BRPC context changed during RPC from {} to
{},will be reset.",
- getJsonContext(rpcContexts),
- getJsonContext(rootContexts));
- }
- resetRootContexts(rootContexts);
+ if (bound) {
+ TransactionPropagationHandler.unbindProviderContext(rpcXid);
}
}
}
- @Override
- public String getRpcContext(Request rpcContext, String key) {
- if (null == rpcContext.getKvAttachment()) {
+ private String getXidFromRequest(Request request) {
+ String xid = getAttachment(request, RootContext.KEY_XID);
+ if (xid == null) {
+ xid = getAttachment(request, RootContext.KEY_XID.toLowerCase());
+ }
+ return xid;
+ }
+
+ private String getAttachment(Request request, String key) {
+ Map<String, Object> kvAttachment = request.getKvAttachment();
+ if (kvAttachment == null) {
return null;
}
- Object value = rpcContext.getKvAttachment().get(key);
+ Object value = kvAttachment.get(key);
return value == null ? null : value.toString();
}
}
diff --git a/extensions/rpc/seata-dubbo-alibaba/pom.xml
b/extensions/rpc/seata-dubbo-alibaba/pom.xml
index 17bbec54ea..91b7e05cf3 100644
--- a/extensions/rpc/seata-dubbo-alibaba/pom.xml
+++ b/extensions/rpc/seata-dubbo-alibaba/pom.xml
@@ -35,7 +35,7 @@
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>seata-tm</artifactId>
+ <artifactId>seata-rpc-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git
a/extensions/rpc/seata-dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionConsumerFilter.java
b/extensions/rpc/seata-dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionConsumerFilter.java
index 4549dfd5dc..6cabcf3dd9 100644
---
a/extensions/rpc/seata-dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionConsumerFilter.java
+++
b/extensions/rpc/seata-dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionConsumerFilter.java
@@ -24,58 +24,32 @@ import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import org.apache.seata.core.constants.DubboConstants;
-import org.apache.seata.core.context.RootContext;
-import org.apache.seata.core.model.BranchType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
+
+import java.util.Map;
-/**
- * The type Alibaba dubbo transaction consumer filter.
- */
@Activate(
group = {DubboConstants.CONSUMER},
order = 100)
public class AlibabaDubboTransactionConsumerFilter implements Filter {
- private static final Logger LOGGER =
LoggerFactory.getLogger(AlibabaDubboTransactionConsumerFilter.class);
-
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws
RpcException {
if (!DubboConstants.ALIBABADUBBO) {
return invoker.invoke(invocation);
}
- return doInvoke(invoker, invocation);
- }
-
- private Result doInvoke(Invoker<?> invoker, Invocation invocation) throws
RpcException {
- String xid = RootContext.getXID();
- BranchType branchType = RootContext.getBranchType();
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("consumer xid in RootContext[{}], branchType in
RootContext[{}]", xid, branchType);
+ Map<String, String> context =
TransactionPropagationHandler.getTransactionPropagationContext();
+ if (!context.isEmpty()) {
+ for (Map.Entry<String, String> entry : context.entrySet()) {
+ RpcContext.getContext().setAttachment(entry.getKey(),
entry.getValue());
+ }
}
try {
- propagateTransactionContext(xid, branchType);
return invoker.invoke(invocation);
} finally {
- clearTransactionContext();
- }
- }
-
- private void propagateTransactionContext(String xid, BranchType
branchType) {
- if (xid != null) {
- RpcContext.getContext().setAttachment(RootContext.KEY_XID, xid);
- RpcContext.getContext().setAttachment(RootContext.KEY_BRANCH_TYPE,
branchType.name());
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("transaction context propagated: xid={},
branchType={}", xid, branchType);
+ for (String key : context.keySet()) {
+ RpcContext.getContext().removeAttachment(key);
}
}
}
-
- private void clearTransactionContext() {
- RpcContext.getContext().removeAttachment(RootContext.KEY_XID);
- RpcContext.getContext().removeAttachment(RootContext.KEY_BRANCH_TYPE);
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("transaction context cleared");
- }
- }
}
diff --git
a/extensions/rpc/seata-dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionProviderFilter.java
b/extensions/rpc/seata-dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionProviderFilter.java
index 7c8a4fddf9..89f5d84ac8 100644
---
a/extensions/rpc/seata-dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionProviderFilter.java
+++
b/extensions/rpc/seata-dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionProviderFilter.java
@@ -23,127 +23,34 @@ import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
-import org.apache.seata.common.util.StringUtils;
import org.apache.seata.core.constants.DubboConstants;
import org.apache.seata.core.context.RootContext;
-import org.apache.seata.core.model.BranchType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
-/**
- * The type Alibaba dubbo transaction provider filter.
- */
@Activate(
group = {DubboConstants.PROVIDER},
order = 100)
public class AlibabaDubboTransactionProviderFilter implements Filter {
- private static final Logger LOGGER =
LoggerFactory.getLogger(AlibabaDubboTransactionProviderFilter.class);
-
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws
RpcException {
if (!DubboConstants.ALIBABADUBBO) {
return invoker.invoke(invocation);
}
-
- return doInvoke(invoker, invocation);
- }
-
- private Result doInvoke(Invoker<?> invoker, Invocation invocation) throws
RpcException {
String rpcXid = getRpcXid();
String rpcBranchType =
RpcContext.getContext().getAttachment(RootContext.KEY_BRANCH_TYPE);
-
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("xid in RpcContext[{}], branchType in
RpcContext[{}]", rpcXid, rpcBranchType);
- }
-
- TransactionContextBinding binding = bindTransactionContext(rpcXid,
rpcBranchType);
-
+ boolean bound =
TransactionPropagationHandler.bindProviderContext(rpcXid, rpcBranchType);
try {
return invoker.invoke(invocation);
} finally {
- unbindTransactionContext(binding);
- clearServerContextAttachments();
- }
- }
-
- private TransactionContextBinding bindTransactionContext(String rpcXid,
String rpcBranchType) {
- TransactionContextBinding binding = new TransactionContextBinding();
-
- if (rpcXid != null) {
- RootContext.bind(rpcXid);
- binding.wasBound = true;
- binding.bindXid = rpcXid;
-
- if (StringUtils.equals(BranchType.TCC.name(), rpcBranchType)) {
- RootContext.bindBranchType(BranchType.TCC);
- binding.wasBranchTypeBound = true;
- }
-
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("bind xid [{}] branchType [{}] to RootContext",
rpcXid, rpcBranchType);
+ if (bound) {
+ TransactionPropagationHandler.unbindProviderContext(rpcXid);
}
+
RpcContext.getServerContext().removeAttachment(RootContext.KEY_XID);
+
RpcContext.getServerContext().removeAttachment(RootContext.KEY_BRANCH_TYPE);
}
-
- return binding;
}
- private void unbindTransactionContext(TransactionContextBinding binding) {
- if (!binding.wasBound) {
- return;
- }
-
- BranchType previousBranchType = RootContext.getBranchType();
- String unbindXid = RootContext.unbind();
- binding.unbindXid = unbindXid;
- binding.unbindBranchType = previousBranchType;
-
- if (binding.wasBranchTypeBound && BranchType.TCC ==
previousBranchType) {
- RootContext.unbindBranchType();
- }
-
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("unbind xid [{}] branchType [{}] from RootContext",
unbindXid, previousBranchType);
- }
-
- handleXidChange(binding);
- }
-
- private void handleXidChange(TransactionContextBinding binding) {
- if (!binding.bindXid.equalsIgnoreCase(binding.unbindXid)) {
- LOGGER.warn(
- "xid in change during RPC from {} to {},branchType from {}
to {}",
- binding.bindXid,
- binding.unbindXid,
- binding.bindBranchType != null ? binding.bindBranchType :
BranchType.AT,
- binding.unbindBranchType);
-
- if (binding.unbindXid != null) {
- restoreTransactionContext(binding);
- }
- }
- }
-
- private void restoreTransactionContext(TransactionContextBinding binding) {
- RootContext.bind(binding.unbindXid);
- LOGGER.warn("bind xid [{}] back to RootContext", binding.unbindXid);
-
- if (BranchType.TCC == binding.unbindBranchType) {
- RootContext.bindBranchType(BranchType.TCC);
- LOGGER.warn("bind branchType [{}] back to RootContext",
binding.unbindBranchType);
- }
- }
-
- private void clearServerContextAttachments() {
- RpcContext.getServerContext().removeAttachment(RootContext.KEY_XID);
-
RpcContext.getServerContext().removeAttachment(RootContext.KEY_BRANCH_TYPE);
- }
-
- /**
- * get rpc xid
- *
- * @return
- */
private String getRpcXid() {
String rpcXid =
RpcContext.getContext().getAttachment(RootContext.KEY_XID);
if (rpcXid == null) {
@@ -151,31 +58,4 @@ public class AlibabaDubboTransactionProviderFilter
implements Filter {
}
return rpcXid;
}
-
- private static class TransactionContextBinding {
- /**
- * The Was bound.
- */
- boolean wasBound = false;
- /**
- * The Was branch type bound.
- */
- boolean wasBranchTypeBound = false;
- /**
- * The Bind xid.
- */
- String bindXid;
- /**
- * The Bind branch type.
- */
- String bindBranchType;
- /**
- * The Unbind xid.
- */
- String unbindXid;
- /**
- * The Unbind branch type.
- */
- BranchType unbindBranchType;
- }
}
diff --git a/extensions/rpc/seata-grpc/pom.xml
b/extensions/rpc/seata-grpc/pom.xml
index 072f64afb4..ac78a50f68 100644
--- a/extensions/rpc/seata-grpc/pom.xml
+++ b/extensions/rpc/seata-grpc/pom.xml
@@ -35,7 +35,7 @@
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>seata-tm</artifactId>
+ <artifactId>seata-rpc-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git
a/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/client/ClientTransactionInterceptor.java
b/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/client/ClientTransactionInterceptor.java
index 51d7220c44..9843b76dc5 100644
---
a/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/client/ClientTransactionInterceptor.java
+++
b/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/client/ClientTransactionInterceptor.java
@@ -26,6 +26,9 @@ import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import org.apache.seata.core.context.RootContext;
import org.apache.seata.integration.grpc.interceptor.GrpcHeaderKey;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
+
+import java.util.Map;
public class ClientTransactionInterceptor implements ClientInterceptor {
@@ -33,16 +36,20 @@ public class ClientTransactionInterceptor implements
ClientInterceptor {
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions,
Channel next) {
- String xid = RootContext.getXID();
+ Map<String, String> context =
TransactionPropagationHandler.getTransactionPropagationContext();
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT,
RespT>(next.newCall(method, callOptions)) {
@Override
public void start(Listener<RespT> responseListener, Metadata
headers) {
- if (xid != null) {
- headers.put(GrpcHeaderKey.XID_HEADER_KEY, xid);
- headers.put(
- GrpcHeaderKey.BRANCH_HEADER_KEY,
- RootContext.getBranchType().name());
+ if (!context.isEmpty()) {
+ String xid = context.get(RootContext.KEY_XID);
+ if (xid != null) {
+ headers.put(GrpcHeaderKey.XID_HEADER_KEY, xid);
+ }
+ String branchType =
context.get(RootContext.KEY_BRANCH_TYPE);
+ if (branchType != null) {
+ headers.put(GrpcHeaderKey.BRANCH_HEADER_KEY,
branchType);
+ }
}
super.start(
new
ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT>(responseListener)
{
diff --git
a/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/server/ServerListenerProxy.java
b/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/server/ServerListenerProxy.java
index 408f4b21a8..71810188b4 100644
---
a/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/server/ServerListenerProxy.java
+++
b/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/server/ServerListenerProxy.java
@@ -17,56 +17,32 @@
package org.apache.seata.integration.grpc.interceptor.server;
import io.grpc.ServerCall;
-import org.apache.seata.common.util.StringUtils;
-import org.apache.seata.core.context.RootContext;
-import org.apache.seata.core.model.BranchType;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
-import java.util.Map;
import java.util.Objects;
public class ServerListenerProxy<ReqT> extends ServerCall.Listener<ReqT> {
- private ServerCall.Listener<ReqT> target;
- private final String xid;
- private final Map<String, String> context;
+ private final ServerCall.Listener<ReqT> target;
+ private final String rpcXid;
+ private final String rpcBranchType;
- /**
- * Constructs a ServerListenerProxy.
- *
- * @param xid the global transaction id to bind
- * @param context the context map containing metadata such as branch type
- * @param target the original ServerCall.Listener to delegate calls to
- */
- public ServerListenerProxy(String xid, Map<String, String> context,
ServerCall.Listener<ReqT> target) {
- super();
+ public ServerListenerProxy(String rpcXid, String rpcBranchType,
ServerCall.Listener<ReqT> target) {
Objects.requireNonNull(target);
this.target = target;
- this.xid = xid;
- this.context = context;
+ this.rpcXid = rpcXid;
+ this.rpcBranchType = rpcBranchType;
}
- /**
- * Delegates onMessage call to the target listener.
- */
@Override
public void onMessage(ReqT message) {
target.onMessage(message);
}
- /**
- * Cleans up previous transaction context and binds new XID and branch
type (if applicable)
- * before delegating onHalfClose call to the target listener.
- */
@Override
public void onHalfClose() {
- cleanContext();
- if (StringUtils.isNotBlank(xid)) {
- RootContext.bind(xid);
- String branchType = context.get(RootContext.KEY_BRANCH_TYPE);
- if (StringUtils.equals(BranchType.TCC.name(), branchType)) {
- RootContext.bindBranchType(BranchType.TCC);
- }
- }
+ TransactionPropagationHandler.unbindProviderContext(null);
+ TransactionPropagationHandler.bindProviderContext(rpcXid,
rpcBranchType);
target.onHalfClose();
}
@@ -84,16 +60,4 @@ public class ServerListenerProxy<ReqT> extends
ServerCall.Listener<ReqT> {
public void onReady() {
target.onReady();
}
-
- /**
- * Cleans up the transaction context from RootContext to avoid thread
context pollution.
- * Unbinds XID and branch type if previously set.
- */
- private void cleanContext() {
- RootContext.unbind();
- BranchType previousBranchType = RootContext.getBranchType();
- if (BranchType.TCC == previousBranchType) {
- RootContext.unbindBranchType();
- }
- }
}
diff --git
a/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/server/ServerTransactionInterceptor.java
b/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/server/ServerTransactionInterceptor.java
index 39cea8fd7c..e242bab676 100644
---
a/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/server/ServerTransactionInterceptor.java
+++
b/extensions/rpc/seata-grpc/src/main/java/org/apache/seata/integration/grpc/interceptor/server/ServerTransactionInterceptor.java
@@ -20,57 +20,21 @@ import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
-import org.apache.seata.core.context.RootContext;
import org.apache.seata.integration.grpc.interceptor.GrpcHeaderKey;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * ServerTransactionInterceptor intercepts incoming gRPC calls on the server
side
- * to extract global transaction context information (XID and branch type)
from request metadata,
- * and injects this context into a ServerListenerProxy to manage transaction
context lifecycle.
- */
public class ServerTransactionInterceptor implements ServerInterceptor {
- /**
- * Intercepts a gRPC call to extract transaction context and wrap the
ServerCall.Listener.
- *
- * @param serverCall the gRPC ServerCall object
- * @param metadata the request metadata (headers)
- * @param serverCallHandler the next handler in the interceptor chain
- * @param <ReqT> the request type
- * @param <RespT> the response type
- * @return a wrapped ServerCall.Listener that manages transaction context
- */
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> serverCall, Metadata metadata,
ServerCallHandler<ReqT, RespT> serverCallHandler) {
- String xid = getRpcXid(metadata);
- String branchName = getBranchName(metadata);
- Map<String, String> context = new HashMap<>();
- context.put(RootContext.KEY_BRANCH_TYPE, branchName);
- return new ServerListenerProxy<>(
- xid, Collections.unmodifiableMap(context),
serverCallHandler.startCall(serverCall, metadata));
+ String rpcXid = getRpcXid(metadata);
+ String rpcBranchType = metadata.get(GrpcHeaderKey.BRANCH_HEADER_KEY);
+ return new ServerListenerProxy<>(rpcXid, rpcBranchType,
serverCallHandler.startCall(serverCall, metadata));
}
- /**
- * Extracts the global transaction ID (XID) from metadata headers,
- * supporting both uppercase and lowercase keys.
- */
private String getRpcXid(Metadata metadata) {
- String rpcXid = metadata.get(GrpcHeaderKey.XID_HEADER_KEY);
- if (rpcXid == null) {
- rpcXid = metadata.get(GrpcHeaderKey.XID_HEADER_KEY_LOWERCASE);
- }
- return rpcXid;
- }
-
- /**
- * Extracts the branch transaction type name from metadata headers.
- */
- private String getBranchName(Metadata metadata) {
- return metadata.get(GrpcHeaderKey.BRANCH_HEADER_KEY);
+ return TransactionPropagationHandler.resolveXid(
+ metadata.get(GrpcHeaderKey.XID_HEADER_KEY),
metadata.get(GrpcHeaderKey.XID_HEADER_KEY_LOWERCASE));
}
}
diff --git
a/extensions/rpc/seata-grpc/src/test/java/org/apache/seata/integration/grpc/interceptor/server/ServerListenerProxyTest.java
b/extensions/rpc/seata-grpc/src/test/java/org/apache/seata/integration/grpc/interceptor/server/ServerListenerProxyTest.java
index 9495733fc2..9c59188a23 100644
---
a/extensions/rpc/seata-grpc/src/test/java/org/apache/seata/integration/grpc/interceptor/server/ServerListenerProxyTest.java
+++
b/extensions/rpc/seata-grpc/src/test/java/org/apache/seata/integration/grpc/interceptor/server/ServerListenerProxyTest.java
@@ -24,9 +24,6 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import java.util.HashMap;
-import java.util.Map;
-
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -61,18 +58,13 @@ class ServerListenerProxyTest {
@Test
void testOnHalfClose_withNonEmptyXid_andTCCBranchType_shouldBindContext() {
String xid = "test-xid";
- Map<String, String> context = new HashMap<>();
- context.put(RootContext.KEY_BRANCH_TYPE, BranchType.TCC.name());
-
- ServerListenerProxy<String> proxy = new ServerListenerProxy<>(xid,
context, target);
+ ServerListenerProxy<String> proxy = new ServerListenerProxy<>(xid,
BranchType.TCC.name(), target);
- // Pre-bind some context to test cleanup
RootContext.bind("old-xid");
RootContext.bindBranchType(BranchType.AT);
proxy.onHalfClose();
- // Verify RootContext binding updated
Assertions.assertEquals(xid, RootContext.getXID());
Assertions.assertEquals(BranchType.TCC, RootContext.getBranchType());
@@ -81,15 +73,13 @@ class ServerListenerProxyTest {
@Test
void testOnHalfClose_withEmptyXid_shouldOnlyCleanContext_andCallTarget() {
- ServerListenerProxy<String> proxy = new ServerListenerProxy<>(null,
new HashMap<>(), target);
+ ServerListenerProxy<String> proxy = new ServerListenerProxy<>(null,
null, target);
- // Pre-bind some context to test cleanup
RootContext.bind("old-xid");
RootContext.bindBranchType(BranchType.TCC);
proxy.onHalfClose();
- // Context should be cleaned (unbind XID and branch type)
Assertions.assertNull(RootContext.getXID());
Assertions.assertNull(RootContext.getBranchType());
diff --git
a/extensions/rpc/seata-grpc/src/test/java/org/apache/seata/integration/grpc/interceptor/server/ServerTransactionInterceptorTest.java
b/extensions/rpc/seata-grpc/src/test/java/org/apache/seata/integration/grpc/interceptor/server/ServerTransactionInterceptorTest.java
index bfc07a07d2..f96bd1a1c9 100644
---
a/extensions/rpc/seata-grpc/src/test/java/org/apache/seata/integration/grpc/interceptor/server/ServerTransactionInterceptorTest.java
+++
b/extensions/rpc/seata-grpc/src/test/java/org/apache/seata/integration/grpc/interceptor/server/ServerTransactionInterceptorTest.java
@@ -46,19 +46,16 @@ class ServerTransactionInterceptorTest {
@Test
void testInterceptCall_shouldExtractXidAndBranchTypeAndWrapListener() {
- // Ready
Metadata metadata = new Metadata();
metadata.put(GrpcHeaderKey.XID_HEADER_KEY, "test-xid");
metadata.put(GrpcHeaderKey.BRANCH_HEADER_KEY, "TCC");
- // Mocks
ServerCall<String, String> serverCall = mock(ServerCall.class);
ServerCallHandler<String, String> serverCallHandler =
mock(ServerCallHandler.class);
Listener<String> originalListener = mock(Listener.class);
when(serverCallHandler.startCall(serverCall,
metadata)).thenReturn(originalListener);
- // Call interceptor
ServerCall.Listener<String> listener =
interceptor.interceptCall(serverCall, metadata, serverCallHandler);
assertNotNull(listener);
@@ -78,17 +75,4 @@ class ServerTransactionInterceptorTest {
metadataLower.put(GrpcHeaderKey.XID_HEADER_KEY_LOWERCASE, "lower-xid");
assertEquals("lower-xid", getRpcXidMethod.invoke(interceptor,
metadataLower));
}
-
- @Test
- void testGetBranchName_shouldReturnCorrectValue() throws Exception {
- Metadata metadata = new Metadata();
- metadata.put(GrpcHeaderKey.BRANCH_HEADER_KEY, "branch-type");
-
- Method getBranchNameMethod =
interceptor.getClass().getDeclaredMethod("getBranchName", Metadata.class);
- getBranchNameMethod.setAccessible(true);
-
- String branchName = (String) getBranchNameMethod.invoke(interceptor,
metadata);
-
- assertEquals("branch-type", branchName);
- }
}
diff --git a/extensions/rpc/seata-hsf/pom.xml b/extensions/rpc/seata-hsf/pom.xml
index 95d4aa6940..452ccd2643 100644
--- a/extensions/rpc/seata-hsf/pom.xml
+++ b/extensions/rpc/seata-hsf/pom.xml
@@ -35,7 +35,7 @@
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>seata-tm</artifactId>
+ <artifactId>seata-rpc-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git
a/extensions/rpc/seata-hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionConsumerFilter.java
b/extensions/rpc/seata-hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionConsumerFilter.java
index 418b5a0865..fa0ed20219 100644
---
a/extensions/rpc/seata-hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionConsumerFilter.java
+++
b/extensions/rpc/seata-hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionConsumerFilter.java
@@ -22,79 +22,29 @@ import com.taobao.hsf.invocation.InvocationHandler;
import com.taobao.hsf.invocation.RPCResult;
import com.taobao.hsf.invocation.filter.ClientFilter;
import com.taobao.hsf.util.concurrent.ListenableFuture;
-import org.apache.seata.core.context.RootContext;
-import org.apache.seata.core.model.BranchType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
-/**
- * The type Hsf transaction consumer filter.
- */
-public class HsfTransactionConsumerFilter implements ClientFilter {
+import java.util.Map;
- private static final Logger LOGGER =
LoggerFactory.getLogger(HsfTransactionConsumerFilter.class);
+public class HsfTransactionConsumerFilter implements ClientFilter {
@Override
public ListenableFuture<RPCResult> invoke(InvocationHandler nextHandler,
Invocation invocation) throws Throwable {
- return doInvoke(nextHandler, invocation);
- }
-
- private ListenableFuture<RPCResult> doInvoke(InvocationHandler
nextHandler, Invocation invocation)
- throws Throwable {
- TransactionContext context = extractTransactionContext();
-
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("xid in RootContext[{}], branchType in
RootContext[{}]", context.xid, context.branchType);
+ Map<String, String> context =
TransactionPropagationHandler.getTransactionPropagationContext();
+ if (!context.isEmpty()) {
+ for (Map.Entry<String, String> entry : context.entrySet()) {
+ RPCContext.getClientContext().putAttachment(entry.getKey(),
entry.getValue());
+ }
}
-
try {
- propagateTransactionContext(context);
return nextHandler.invoke(invocation);
} finally {
- clearTransactionContext();
- }
- }
-
- private TransactionContext extractTransactionContext() {
- TransactionContext context = new TransactionContext();
- context.xid = RootContext.getXID();
- context.branchType = RootContext.getBranchType();
- return context;
- }
-
- private void propagateTransactionContext(TransactionContext context) {
- if (context.xid != null) {
- RPCContext.getClientContext().putAttachment(RootContext.KEY_XID,
context.xid);
-
RPCContext.getClientContext().putAttachment(RootContext.KEY_BRANCH_TYPE,
context.branchType.name());
-
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("transaction context propagated: xid={},
branchType={}", context.xid, context.branchType);
+ for (String key : context.keySet()) {
+ RPCContext.getClientContext().removeAttachment(key);
}
}
}
- private void clearTransactionContext() {
- RPCContext.getClientContext().removeAttachment(RootContext.KEY_XID);
-
RPCContext.getClientContext().removeAttachment(RootContext.KEY_BRANCH_TYPE);
-
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("transaction context cleared");
- }
- }
-
@Override
- public void onResponse(Invocation invocation, RPCResult rpcResult) {
- // No operation needed
- }
-
- private static class TransactionContext {
- /**
- * The Xid.
- */
- String xid;
- /**
- * The Branch type.
- */
- BranchType branchType;
- }
+ public void onResponse(Invocation invocation, RPCResult rpcResult) {}
}
diff --git
a/extensions/rpc/seata-hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionProviderFilter.java
b/extensions/rpc/seata-hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionProviderFilter.java
index b87d59a475..c17dcb70c5 100644
---
a/extensions/rpc/seata-hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionProviderFilter.java
+++
b/extensions/rpc/seata-hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionProviderFilter.java
@@ -22,165 +22,40 @@ import com.taobao.hsf.invocation.InvocationHandler;
import com.taobao.hsf.invocation.RPCResult;
import com.taobao.hsf.invocation.filter.ServerFilter;
import com.taobao.hsf.util.concurrent.ListenableFuture;
-import org.apache.seata.common.util.StringUtils;
import org.apache.seata.core.context.RootContext;
-import org.apache.seata.core.model.BranchType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
-/**
- * The type Hsf transaction provider filter.
- */
public class HsfTransactionProviderFilter implements ServerFilter {
- private static final Logger LOGGER =
LoggerFactory.getLogger(HsfTransactionProviderFilter.class);
-
@Override
public ListenableFuture<RPCResult> invoke(InvocationHandler nextHandler,
Invocation invocation) throws Throwable {
- return doInvoke(nextHandler, invocation);
- }
-
- private ListenableFuture<RPCResult> doInvoke(InvocationHandler
nextHandler, Invocation invocation)
- throws Throwable {
- RpcTransactionContext rpcContext = extractRpcTransactionContext();
-
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug(
- "xid in RpcContext[{}], branchType in RpcContext[{}]",
rpcContext.rpcXid, rpcContext.rpcBranchType);
- }
-
- TransactionContextBinding binding = bindTransactionContext(rpcContext);
-
+ String rpcXid = getRpcXid();
+ String rpcBranchType =
getStringAttachment(RootContext.KEY_BRANCH_TYPE);
+ boolean bound =
TransactionPropagationHandler.bindProviderContext(rpcXid, rpcBranchType);
try {
return nextHandler.invoke(invocation);
} finally {
- unbindTransactionContext(binding);
- clearServerContextAttachments();
- }
- }
-
- private RpcTransactionContext extractRpcTransactionContext() {
- RpcTransactionContext context = new RpcTransactionContext();
- context.rpcXid =
RPCContext.getServerContext().getAttachment(RootContext.KEY_XID);
- context.rpcBranchType =
RPCContext.getServerContext().getAttachment(RootContext.KEY_BRANCH_TYPE);
- return context;
- }
-
- private TransactionContextBinding
bindTransactionContext(RpcTransactionContext rpcContext) {
- TransactionContextBinding binding = new TransactionContextBinding();
-
- if (rpcContext.rpcXid != null) {
- String xidStr = rpcContext.rpcXid.toString();
- RootContext.bind(xidStr);
- binding.wasBound = true;
- binding.bindXid = xidStr;
-
- if (rpcContext.rpcBranchType != null
- && StringUtils.equals(BranchType.TCC.name(),
rpcContext.rpcBranchType.toString())) {
- RootContext.bindBranchType(BranchType.TCC);
- binding.wasBranchTypeBound = true;
- }
-
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug(
- "bind xid [{}] branchType [{}] to RootContext",
rpcContext.rpcXid, rpcContext.rpcBranchType);
- }
- }
-
- return binding;
- }
-
- private void unbindTransactionContext(TransactionContextBinding binding) {
- if (!binding.wasBound) {
- return;
- }
-
- BranchType previousBranchType = RootContext.getBranchType();
- String unbindXid = RootContext.unbind();
- binding.unbindXid = unbindXid;
- binding.unbindBranchType = previousBranchType;
-
- if (binding.wasBranchTypeBound && BranchType.TCC ==
previousBranchType) {
- RootContext.unbindBranchType();
- }
-
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("unbind xid [{}] branchType [{}] from RootContext",
unbindXid, previousBranchType);
- }
-
- handleXidChange(binding);
- }
-
- private void handleXidChange(TransactionContextBinding binding) {
- if (!binding.bindXid.equalsIgnoreCase(binding.unbindXid)) {
- LOGGER.warn(
- "xid in change during RPC from {} to {},branchType from {}
to {}",
- binding.bindXid,
- binding.unbindXid,
- binding.bindBranchType != null ? binding.bindBranchType :
"AT",
- binding.unbindBranchType);
-
- if (binding.unbindXid != null) {
- restoreTransactionContext(binding);
+ if (bound) {
+ TransactionPropagationHandler.unbindProviderContext(rpcXid);
}
+
RPCContext.getServerContext().removeAttachment(RootContext.KEY_XID);
+
RPCContext.getServerContext().removeAttachment(RootContext.KEY_BRANCH_TYPE);
}
}
- private void restoreTransactionContext(TransactionContextBinding binding) {
- RootContext.bind(binding.unbindXid);
- LOGGER.warn("bind xid [{}] back to RootContext", binding.unbindXid);
-
- if (BranchType.TCC == binding.unbindBranchType) {
- RootContext.bindBranchType(BranchType.TCC);
- LOGGER.warn("bind branchType [{}] back to RootContext",
binding.unbindBranchType);
+ private String getRpcXid() {
+ String rpcXid = getStringAttachment(RootContext.KEY_XID);
+ if (rpcXid == null) {
+ rpcXid = getStringAttachment(RootContext.KEY_XID.toLowerCase());
}
+ return rpcXid;
}
- private void clearServerContextAttachments() {
- RPCContext.getServerContext().removeAttachment(RootContext.KEY_XID);
-
RPCContext.getServerContext().removeAttachment(RootContext.KEY_BRANCH_TYPE);
+ private String getStringAttachment(String key) {
+ Object value = RPCContext.getServerContext().getAttachment(key);
+ return value == null ? null : value.toString();
}
@Override
- public void onResponse(Invocation invocation, RPCResult rpcResult) {
- // No operation needed
- }
-
- private static class RpcTransactionContext {
- /**
- * The Rpc xid.
- */
- Object rpcXid;
- /**
- * The Rpc branch type.
- */
- Object rpcBranchType;
- }
-
- private static class TransactionContextBinding {
- /**
- * The Was bound.
- */
- boolean wasBound = false;
- /**
- * The Was branch type bound.
- */
- boolean wasBranchTypeBound = false;
- /**
- * The Bind xid.
- */
- String bindXid;
- /**
- * The Bind branch type.
- */
- String bindBranchType;
- /**
- * The Unbind xid.
- */
- String unbindXid;
- /**
- * The Unbind branch type.
- */
- BranchType unbindBranchType;
- }
+ public void onResponse(Invocation invocation, RPCResult rpcResult) {}
}
diff --git
a/extensions/rpc/seata-hsf/src/test/java/org/apache/seata/integration/hsf/HsfTransactionFilterTest.java
b/extensions/rpc/seata-hsf/src/test/java/org/apache/seata/integration/hsf/HsfTransactionFilterTest.java
new file mode 100644
index 0000000000..e192086f6a
--- /dev/null
+++
b/extensions/rpc/seata-hsf/src/test/java/org/apache/seata/integration/hsf/HsfTransactionFilterTest.java
@@ -0,0 +1,190 @@
+/*
+ * 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.hsf;
+
+import com.taobao.hsf.context.RPCContext;
+import com.taobao.hsf.invocation.Invocation;
+import com.taobao.hsf.invocation.InvocationHandler;
+import com.taobao.hsf.invocation.RPCResult;
+import com.taobao.hsf.util.concurrent.ListenableFuture;
+import org.apache.seata.core.context.RootContext;
+import org.apache.seata.core.model.BranchType;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+
+class HsfTransactionFilterTest {
+
+ private static final String DEFAULT_XID = "127.0.0.1:8091:12345678";
+
+ @AfterEach
+ void cleanup() {
+ RootContext.unbind();
+ RootContext.unbindBranchType();
+ }
+
+ @Test
+ void testConsumerFilter_propagatesXid() throws Throwable {
+ RootContext.bind(DEFAULT_XID);
+ RootContext.bindBranchType(BranchType.TCC);
+
+ Map<String, Object> clientAttachments = new HashMap<>();
+ RPCContext mockClientContext = mock(RPCContext.class);
+ when(mockClientContext.putAttachment(
+ org.mockito.ArgumentMatchers.anyString(),
org.mockito.ArgumentMatchers.any()))
+ .thenAnswer(inv -> {
+ clientAttachments.put(inv.getArgument(0),
inv.getArgument(1));
+ return mockClientContext;
+ });
+
when(mockClientContext.removeAttachment(org.mockito.ArgumentMatchers.anyString()))
+ .thenAnswer(inv -> {
+ clientAttachments.remove((String) inv.getArgument(0));
+ return mockClientContext;
+ });
+
+ InvocationHandler mockHandler = mock(InvocationHandler.class);
+ @SuppressWarnings("unchecked")
+ ListenableFuture<RPCResult> mockFuture = mock(ListenableFuture.class);
+
when(mockHandler.invoke(org.mockito.ArgumentMatchers.any())).thenAnswer(inv -> {
+ assertThat(clientAttachments).containsEntry(RootContext.KEY_XID,
DEFAULT_XID);
+
assertThat(clientAttachments).containsEntry(RootContext.KEY_BRANCH_TYPE,
BranchType.TCC.name());
+ return mockFuture;
+ });
+
+ HsfTransactionConsumerFilter filter = new
HsfTransactionConsumerFilter();
+ try (MockedStatic<RPCContext> rpcContextMock =
mockStatic(RPCContext.class)) {
+
rpcContextMock.when(RPCContext::getClientContext).thenReturn(mockClientContext);
+ filter.invoke(mockHandler, new Invocation());
+ }
+
+ assertThat(clientAttachments).isEmpty();
+ }
+
+ @Test
+ void testConsumerFilter_noXid() throws Throwable {
+ Map<String, Object> clientAttachments = new HashMap<>();
+ RPCContext mockClientContext = mock(RPCContext.class);
+ when(mockClientContext.putAttachment(
+ org.mockito.ArgumentMatchers.anyString(),
org.mockito.ArgumentMatchers.any()))
+ .thenAnswer(inv -> {
+ clientAttachments.put(inv.getArgument(0),
inv.getArgument(1));
+ return mockClientContext;
+ });
+
+ InvocationHandler mockHandler = mock(InvocationHandler.class);
+ @SuppressWarnings("unchecked")
+ ListenableFuture<RPCResult> mockFuture = mock(ListenableFuture.class);
+
when(mockHandler.invoke(org.mockito.ArgumentMatchers.any())).thenReturn(mockFuture);
+
+ HsfTransactionConsumerFilter filter = new
HsfTransactionConsumerFilter();
+ try (MockedStatic<RPCContext> rpcContextMock =
mockStatic(RPCContext.class)) {
+
rpcContextMock.when(RPCContext::getClientContext).thenReturn(mockClientContext);
+ filter.invoke(mockHandler, new Invocation());
+ }
+
+ assertThat(clientAttachments).isEmpty();
+ }
+
+ @Test
+ void testProviderFilter_bindsXid() throws Throwable {
+ Map<String, Object> serverAttachments = new HashMap<>();
+ serverAttachments.put(RootContext.KEY_XID, DEFAULT_XID);
+ serverAttachments.put(RootContext.KEY_BRANCH_TYPE,
BranchType.TCC.name());
+
+ RPCContext mockServerContext = mock(RPCContext.class);
+
when(mockServerContext.getAttachment(RootContext.KEY_XID)).thenReturn(DEFAULT_XID);
+
when(mockServerContext.getAttachment(RootContext.KEY_BRANCH_TYPE)).thenReturn(BranchType.TCC.name());
+
when(mockServerContext.removeAttachment(org.mockito.ArgumentMatchers.anyString()))
+ .thenReturn(mockServerContext);
+
+ InvocationHandler mockHandler = mock(InvocationHandler.class);
+ @SuppressWarnings("unchecked")
+ ListenableFuture<RPCResult> mockFuture = mock(ListenableFuture.class);
+
when(mockHandler.invoke(org.mockito.ArgumentMatchers.any())).thenAnswer(inv -> {
+ assertThat(RootContext.getXID()).isEqualTo(DEFAULT_XID);
+ assertThat(RootContext.getBranchType()).isEqualTo(BranchType.TCC);
+ return mockFuture;
+ });
+
+ HsfTransactionProviderFilter filter = new
HsfTransactionProviderFilter();
+ try (MockedStatic<RPCContext> rpcContextMock =
mockStatic(RPCContext.class)) {
+
rpcContextMock.when(RPCContext::getServerContext).thenReturn(mockServerContext);
+ filter.invoke(mockHandler, new Invocation());
+ }
+
+ assertThat(RootContext.getXID()).isNull();
+ }
+
+ @Test
+ void testProviderFilter_noXid() throws Throwable {
+ RPCContext mockServerContext = mock(RPCContext.class);
+
when(mockServerContext.getAttachment(org.mockito.ArgumentMatchers.anyString()))
+ .thenReturn(null);
+
when(mockServerContext.removeAttachment(org.mockito.ArgumentMatchers.anyString()))
+ .thenReturn(mockServerContext);
+
+ InvocationHandler mockHandler = mock(InvocationHandler.class);
+ @SuppressWarnings("unchecked")
+ ListenableFuture<RPCResult> mockFuture = mock(ListenableFuture.class);
+
when(mockHandler.invoke(org.mockito.ArgumentMatchers.any())).thenAnswer(inv -> {
+ assertThat(RootContext.getXID()).isNull();
+ return mockFuture;
+ });
+
+ HsfTransactionProviderFilter filter = new
HsfTransactionProviderFilter();
+ try (MockedStatic<RPCContext> rpcContextMock =
mockStatic(RPCContext.class)) {
+
rpcContextMock.when(RPCContext::getServerContext).thenReturn(mockServerContext);
+ filter.invoke(mockHandler, new Invocation());
+ }
+
+ assertThat(RootContext.getXID()).isNull();
+ }
+
+ @Test
+ void testProviderFilter_xidFromLowercaseKey() throws Throwable {
+ RPCContext mockServerContext = mock(RPCContext.class);
+
when(mockServerContext.getAttachment(RootContext.KEY_XID)).thenReturn(null);
+
when(mockServerContext.getAttachment(RootContext.KEY_XID.toLowerCase())).thenReturn(DEFAULT_XID);
+
when(mockServerContext.getAttachment(RootContext.KEY_BRANCH_TYPE)).thenReturn(null);
+
when(mockServerContext.removeAttachment(org.mockito.ArgumentMatchers.anyString()))
+ .thenReturn(mockServerContext);
+
+ InvocationHandler mockHandler = mock(InvocationHandler.class);
+ @SuppressWarnings("unchecked")
+ ListenableFuture<RPCResult> mockFuture = mock(ListenableFuture.class);
+
when(mockHandler.invoke(org.mockito.ArgumentMatchers.any())).thenAnswer(inv -> {
+ assertThat(RootContext.getXID()).isEqualTo(DEFAULT_XID);
+ return mockFuture;
+ });
+
+ HsfTransactionProviderFilter filter = new
HsfTransactionProviderFilter();
+ try (MockedStatic<RPCContext> rpcContextMock =
mockStatic(RPCContext.class)) {
+
rpcContextMock.when(RPCContext::getServerContext).thenReturn(mockServerContext);
+ filter.invoke(mockHandler, new Invocation());
+ }
+
+ assertThat(RootContext.getXID()).isNull();
+ }
+}
diff --git a/extensions/rpc/seata-http-jakarta/pom.xml
b/extensions/rpc/seata-http-jakarta/pom.xml
index 1b9fb5abc3..a80da7d594 100644
--- a/extensions/rpc/seata-http-jakarta/pom.xml
+++ b/extensions/rpc/seata-http-jakarta/pom.xml
@@ -50,5 +50,11 @@
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
diff --git
a/extensions/rpc/seata-http-jakarta/src/test/java/org/apache/seata/integration/http/JakartaSeataWebMvcConfigurerTest.java
b/extensions/rpc/seata-http-jakarta/src/test/java/org/apache/seata/integration/http/JakartaSeataWebMvcConfigurerTest.java
new file mode 100644
index 0000000000..5e3f98ae3a
--- /dev/null
+++
b/extensions/rpc/seata-http-jakarta/src/test/java/org/apache/seata/integration/http/JakartaSeataWebMvcConfigurerTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.http;
+
+import
org.apache.seata.integration.http.jakarta.JakartaTransactionPropagationInterceptor;
+import org.junit.jupiter.api.Test;
+import
org.springframework.web.servlet.config.annotation.InterceptorRegistration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class JakartaSeataWebMvcConfigurerTest {
+
+ @Test
+ void testAddInterceptors() {
+ JakartaSeataWebMvcConfigurer configurer = new
JakartaSeataWebMvcConfigurer();
+ InterceptorRegistry registry = mock(InterceptorRegistry.class);
+ InterceptorRegistration registration =
mock(InterceptorRegistration.class);
+ when(registry.addInterceptor(any())).thenReturn(registration);
+
+ configurer.addInterceptors(registry);
+
+
verify(registry).addInterceptor(any(JakartaTransactionPropagationInterceptor.class));
+ }
+}
diff --git
a/extensions/rpc/seata-http-jakarta/src/test/java/org/apache/seata/integration/http/jakarta/JakartaTransactionPropagationInterceptorTest.java
b/extensions/rpc/seata-http-jakarta/src/test/java/org/apache/seata/integration/http/jakarta/JakartaTransactionPropagationInterceptorTest.java
new file mode 100644
index 0000000000..42d4125c34
--- /dev/null
+++
b/extensions/rpc/seata-http-jakarta/src/test/java/org/apache/seata/integration/http/jakarta/JakartaTransactionPropagationInterceptorTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.http.jakarta;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.seata.core.context.RootContext;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class JakartaTransactionPropagationInterceptorTest {
+
+ private static final String DEFAULT_XID = "127.0.0.1:8091:12345678";
+
+ @AfterEach
+ void cleanup() {
+ RootContext.unbind();
+ }
+
+ @Test
+ void testPreHandle_bindsXid() throws Exception {
+ JakartaTransactionPropagationInterceptor interceptor = new
JakartaTransactionPropagationInterceptor();
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ HttpServletResponse response = mock(HttpServletResponse.class);
+ when(request.getHeader(RootContext.KEY_XID)).thenReturn(DEFAULT_XID);
+
+ boolean result = interceptor.preHandle(request, response, new
Object());
+
+ assertThat(result).isTrue();
+ assertThat(RootContext.getXID()).isEqualTo(DEFAULT_XID);
+ }
+
+ @Test
+ void testPreHandle_noXid() throws Exception {
+ JakartaTransactionPropagationInterceptor interceptor = new
JakartaTransactionPropagationInterceptor();
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ HttpServletResponse response = mock(HttpServletResponse.class);
+ when(request.getHeader(RootContext.KEY_XID)).thenReturn(null);
+
+ boolean result = interceptor.preHandle(request, response, new
Object());
+
+ assertThat(result).isTrue();
+ assertThat(RootContext.getXID()).isNull();
+ }
+
+ @Test
+ void testPreHandle_doesNotOverrideExistingXid() throws Exception {
+ RootContext.bind("existing-xid");
+ JakartaTransactionPropagationInterceptor interceptor = new
JakartaTransactionPropagationInterceptor();
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ HttpServletResponse response = mock(HttpServletResponse.class);
+ when(request.getHeader(RootContext.KEY_XID)).thenReturn(DEFAULT_XID);
+
+ boolean result = interceptor.preHandle(request, response, new
Object());
+
+ assertThat(result).isTrue();
+ assertThat(RootContext.getXID()).isEqualTo("existing-xid");
+ }
+
+ @Test
+ void testAfterCompletion_unbindsXid() throws Exception {
+ RootContext.bind(DEFAULT_XID);
+ JakartaTransactionPropagationInterceptor interceptor = new
JakartaTransactionPropagationInterceptor();
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ HttpServletResponse response = mock(HttpServletResponse.class);
+ when(request.getHeader(RootContext.KEY_XID)).thenReturn(DEFAULT_XID);
+
+ interceptor.afterCompletion(request, response, new Object(), null);
+
+ assertThat(RootContext.getXID()).isNull();
+ }
+
+ @Test
+ void testAfterCompletion_noXidInContext() throws Exception {
+ JakartaTransactionPropagationInterceptor interceptor = new
JakartaTransactionPropagationInterceptor();
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ HttpServletResponse response = mock(HttpServletResponse.class);
+ when(request.getHeader(RootContext.KEY_XID)).thenReturn(DEFAULT_XID);
+
+ interceptor.afterCompletion(request, response, new Object(), null);
+
+ assertThat(RootContext.getXID()).isNull();
+ }
+
+ @Test
+ void testFullLifecycle() throws Exception {
+ JakartaTransactionPropagationInterceptor interceptor = new
JakartaTransactionPropagationInterceptor();
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ HttpServletResponse response = mock(HttpServletResponse.class);
+ when(request.getHeader(RootContext.KEY_XID)).thenReturn(DEFAULT_XID);
+
+ interceptor.preHandle(request, response, new Object());
+ assertThat(RootContext.getXID()).isEqualTo(DEFAULT_XID);
+
+ interceptor.afterCompletion(request, response, new Object(), null);
+ assertThat(RootContext.getXID()).isNull();
+ }
+}
diff --git a/extensions/rpc/seata-motan/pom.xml
b/extensions/rpc/seata-motan/pom.xml
index b9a50146c8..158624e63e 100644
--- a/extensions/rpc/seata-motan/pom.xml
+++ b/extensions/rpc/seata-motan/pom.xml
@@ -35,7 +35,7 @@
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>seata-tm</artifactId>
+ <artifactId>seata-rpc-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git
a/extensions/rpc/seata-motan/src/main/java/org/apache/seata/integration/motan/MotanTransactionConsumerFilter.java
b/extensions/rpc/seata-motan/src/main/java/org/apache/seata/integration/motan/MotanTransactionConsumerFilter.java
new file mode 100644
index 0000000000..4ac2ff9d7d
--- /dev/null
+++
b/extensions/rpc/seata-motan/src/main/java/org/apache/seata/integration/motan/MotanTransactionConsumerFilter.java
@@ -0,0 +1,51 @@
+/*
+ * 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.motan;
+
+import com.weibo.api.motan.common.MotanConstants;
+import com.weibo.api.motan.core.extension.Activation;
+import com.weibo.api.motan.core.extension.Scope;
+import com.weibo.api.motan.core.extension.Spi;
+import com.weibo.api.motan.filter.Filter;
+import com.weibo.api.motan.rpc.Caller;
+import com.weibo.api.motan.rpc.Request;
+import com.weibo.api.motan.rpc.Response;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
+
+import java.util.Map;
+
+@Spi(scope = Scope.SINGLETON)
+@Activation(
+ key = {MotanConstants.NODE_TYPE_REFERER},
+ sequence = 100)
+public class MotanTransactionConsumerFilter implements Filter {
+
+ @Override
+ public Response filter(final Caller<?> caller, final Request request) {
+ Map<String, String> context =
TransactionPropagationHandler.getTransactionPropagationContext();
+ if (!context.isEmpty()) {
+ request.getAttachments().putAll(context);
+ }
+ try {
+ return caller.call(request);
+ } finally {
+ for (String key : context.keySet()) {
+ request.getAttachments().remove(key);
+ }
+ }
+ }
+}
diff --git
a/extensions/rpc/seata-motan/src/main/java/org/apache/seata/integration/motan/MotanTransactionFilter.java
b/extensions/rpc/seata-motan/src/main/java/org/apache/seata/integration/motan/MotanTransactionFilter.java
deleted file mode 100644
index d91ded6810..0000000000
---
a/extensions/rpc/seata-motan/src/main/java/org/apache/seata/integration/motan/MotanTransactionFilter.java
+++ /dev/null
@@ -1,114 +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.motan;
-
-import com.weibo.api.motan.common.MotanConstants;
-import com.weibo.api.motan.core.extension.Activation;
-import com.weibo.api.motan.core.extension.Scope;
-import com.weibo.api.motan.core.extension.Spi;
-import com.weibo.api.motan.filter.Filter;
-import com.weibo.api.motan.rpc.Caller;
-import com.weibo.api.motan.rpc.Request;
-import com.weibo.api.motan.rpc.Response;
-import org.apache.seata.common.util.StringUtils;
-import org.apache.seata.core.context.RootContext;
-import org.apache.seata.core.model.BranchType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Spi(scope = Scope.SINGLETON)
-@Activation(
- key = {MotanConstants.NODE_TYPE_SERVICE,
MotanConstants.NODE_TYPE_REFERER},
- sequence = 100)
-public class MotanTransactionFilter implements Filter {
- private static final Logger LOGGER =
LoggerFactory.getLogger(MotanTransactionFilter.class);
-
- public MotanTransactionFilter() {}
-
- @Override
- public Response filter(final Caller<?> caller, final Request request) {
- String currentXid = RootContext.getXID();
- BranchType branchType = RootContext.getBranchType();
- String requestXid = getRpcXid(request);
- String rpcBranchType = getBranchType(request);
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug(
- "context in RootContext[{},{}], context in
RpcContext[{},{}]",
- currentXid,
- branchType,
- requestXid,
- rpcBranchType);
- }
- boolean bind = false;
- if (currentXid != null) {
- request.getAttachments().put(RootContext.KEY_XID, currentXid);
- request.getAttachments().put(RootContext.KEY_BRANCH_TYPE,
branchType.name());
-
- } else if (requestXid != null) {
- RootContext.bind(requestXid);
- if (StringUtils.equals(BranchType.TCC.name(), rpcBranchType)) {
- RootContext.bindBranchType(BranchType.TCC);
- }
- bind = true;
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("bind [{}] to RootContext", requestXid);
- }
- }
- try {
- return caller.call(request);
- } finally {
- if (bind) {
- BranchType previousBranchType = RootContext.getBranchType();
- String unbindXid = RootContext.unbind();
- if (BranchType.TCC == previousBranchType) {
- RootContext.unbindBranchType();
- }
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("unbind xid [{}] branchType [{}] from
RootContext", unbindXid, previousBranchType);
- }
- if (!requestXid.equalsIgnoreCase(unbindXid)) {
- LOGGER.warn("xid has changed, during RPC from [{}] to
[{}]", requestXid, unbindXid);
- if (unbindXid != null) {
- RootContext.bind(unbindXid);
- LOGGER.warn("bind [{}}] back to RootContext",
unbindXid);
- if (BranchType.TCC == previousBranchType) {
- RootContext.bindBranchType(BranchType.TCC);
- LOGGER.warn("bind branchType [{}] back to
RootContext", previousBranchType);
- }
- }
- }
- }
- }
- }
-
- /**
- * get rpc xid
- * @param request
- * @return
- */
- private String getRpcXid(Request request) {
- String rpcXid = request.getAttachments().get(RootContext.KEY_XID);
- if (rpcXid == null) {
- rpcXid =
request.getAttachments().get(RootContext.KEY_XID.toLowerCase());
- }
- return rpcXid;
- }
-
- private String getBranchType(Request request) {
- return request.getAttachments().get(RootContext.KEY_BRANCH_TYPE);
- }
-}
diff --git
a/extensions/rpc/seata-motan/src/main/java/org/apache/seata/integration/motan/MotanTransactionProviderFilter.java
b/extensions/rpc/seata-motan/src/main/java/org/apache/seata/integration/motan/MotanTransactionProviderFilter.java
new file mode 100644
index 0000000000..ac9e46045d
--- /dev/null
+++
b/extensions/rpc/seata-motan/src/main/java/org/apache/seata/integration/motan/MotanTransactionProviderFilter.java
@@ -0,0 +1,57 @@
+/*
+ * 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.motan;
+
+import com.weibo.api.motan.common.MotanConstants;
+import com.weibo.api.motan.core.extension.Activation;
+import com.weibo.api.motan.core.extension.Scope;
+import com.weibo.api.motan.core.extension.Spi;
+import com.weibo.api.motan.filter.Filter;
+import com.weibo.api.motan.rpc.Caller;
+import com.weibo.api.motan.rpc.Request;
+import com.weibo.api.motan.rpc.Response;
+import org.apache.seata.core.context.RootContext;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
+
+@Spi(scope = Scope.SINGLETON)
+@Activation(
+ key = {MotanConstants.NODE_TYPE_SERVICE},
+ sequence = 100)
+public class MotanTransactionProviderFilter implements Filter {
+
+ @Override
+ public Response filter(final Caller<?> caller, final Request request) {
+ String rpcXid = getRpcXid(request);
+ String rpcBranchType =
request.getAttachments().get(RootContext.KEY_BRANCH_TYPE);
+ boolean bound =
TransactionPropagationHandler.bindProviderContext(rpcXid, rpcBranchType);
+ try {
+ return caller.call(request);
+ } finally {
+ if (bound) {
+ TransactionPropagationHandler.unbindProviderContext(rpcXid);
+ }
+ }
+ }
+
+ private String getRpcXid(Request request) {
+ String rpcXid = request.getAttachments().get(RootContext.KEY_XID);
+ if (rpcXid == null) {
+ rpcXid =
request.getAttachments().get(RootContext.KEY_XID.toLowerCase());
+ }
+ return rpcXid;
+ }
+}
diff --git
a/extensions/rpc/seata-motan/src/main/resources/META-INF/services/com.weibo.api.motan.filter.Filter
b/extensions/rpc/seata-motan/src/main/resources/META-INF/services/com.weibo.api.motan.filter.Filter
index 14920bb6fa..f94ea2b3a8 100644
---
a/extensions/rpc/seata-motan/src/main/resources/META-INF/services/com.weibo.api.motan.filter.Filter
+++
b/extensions/rpc/seata-motan/src/main/resources/META-INF/services/com.weibo.api.motan.filter.Filter
@@ -14,4 +14,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-org.apache.seata.integration.motan.MotanTransactionFilter
\ No newline at end of file
+org.apache.seata.integration.motan.MotanTransactionConsumerFilter
+org.apache.seata.integration.motan.MotanTransactionProviderFilter
\ No newline at end of file
diff --git
a/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/BaseRpcFilter.java
b/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/BaseRpcFilter.java
deleted file mode 100644
index 71cc7b423e..0000000000
---
a/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/BaseRpcFilter.java
+++ /dev/null
@@ -1,59 +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.rpc.core;
-
-import org.apache.seata.common.util.CollectionUtils;
-import org.apache.seata.common.util.StringUtils;
-import org.apache.seata.core.context.RootContext;
-
-import java.util.Map;
-
-public interface BaseRpcFilter<T> {
- String[] TRX_CONTEXT_KEYS = new String[] {RootContext.KEY_XID,
RootContext.KEY_BRANCH_TYPE};
-
- default String getValueFromMap(Map<String, String> rpcContextMap, String
key) {
- return rpcContextMap.get(key);
- }
-
- default void assertNotNull(Object obj, String errMsg) {
- if (obj == null) {
- throw new IllegalStateException(errMsg);
- }
- }
-
- default String getJsonContext(Map<String, String> contextMap) {
- if (CollectionUtils.isEmpty(contextMap)) {
- return StringUtils.EMPTY;
- }
- StringBuilder sb = new StringBuilder("{");
- for (int i = 0; i < TRX_CONTEXT_KEYS.length; i++) {
- String contextValue = contextMap.get(TRX_CONTEXT_KEYS[i]);
- if (i > 0) {
- sb.append(",");
- }
- sb.append("\"").append(TRX_CONTEXT_KEYS[i]).append("\"");
- sb.append(":");
- if (null == contextValue) {
- sb.append("null");
- } else {
- sb.append("\"").append(contextValue).append("\"");
- }
- }
- sb.append("}");
- return sb.toString();
- }
-}
diff --git
a/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/ConsumerRpcFilter.java
b/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/ConsumerRpcFilter.java
deleted file mode 100644
index f5bc73a371..0000000000
---
a/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/ConsumerRpcFilter.java
+++ /dev/null
@@ -1,91 +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.rpc.core;
-
-import org.apache.seata.common.util.StringUtils;
-import org.apache.seata.core.context.RootContext;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public interface ConsumerRpcFilter<T> extends BaseRpcFilter<T> {
-
- /**
- * get contexts from RootContext
- *
- * @return
- */
- default Map<String, String> getRootContexts() {
- Map<String, String> contextMap = new HashMap<>();
- if (RootContext.inGlobalTransaction()) {
- for (int i = 0; i < TRX_CONTEXT_KEYS.length; i++) {
- switch (TRX_CONTEXT_KEYS[i]) {
- case RootContext.KEY_XID:
- assertNotNull(RootContext.getXID(), "xid is null");
- contextMap.put(RootContext.KEY_XID,
RootContext.getXID());
- break;
- case RootContext.KEY_BRANCH_TYPE:
- contextMap.put(
- RootContext.KEY_BRANCH_TYPE,
- RootContext.getBranchType().name());
- break;
- default:
- throw new IllegalArgumentException("wrong context: " +
TRX_CONTEXT_KEYS[i]);
- }
- }
- }
- return contextMap;
- }
-
- default String getXidFromRootContexts(Map<String, String> rootContextMap) {
- return getValueFromMap(rootContextMap, RootContext.KEY_XID);
- }
-
- /**
- * bind contexts to RpcRequest
- *
- * @param rpcRequest
- * @param contextMap
- */
- default void bindContextsToRequest(T rpcRequest, Map<String, String>
contextMap) {
- for (int i = 0; i < TRX_CONTEXT_KEYS.length; i++) {
- String contextValue = contextMap.get(TRX_CONTEXT_KEYS[i]);
- if (StringUtils.isNotBlank(contextValue)) {
- bindContextToRequest(rpcRequest, TRX_CONTEXT_KEYS[i],
contextValue);
- }
- }
- }
-
- void bindContextToRequest(T rpcRequest, String key, String value);
-
- /**
- * clean contexts to RpcRequest
- *
- * @param rpcRequest
- * @param contextMap
- */
- default void cleanRequestContexts(T rpcRequest, Map<String, String>
contextMap) {
- for (int i = 0; i < TRX_CONTEXT_KEYS.length; i++) {
- String contextValue = contextMap.get(TRX_CONTEXT_KEYS[i]);
- if (StringUtils.isNotBlank(contextValue)) {
- cleanRequestContext(rpcRequest, TRX_CONTEXT_KEYS[i]);
- }
- }
- }
-
- void cleanRequestContext(T rpcRequest, String key);
-}
diff --git
a/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/ProviderRpcFilter.java
b/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/ProviderRpcFilter.java
deleted file mode 100644
index 0e297c6038..0000000000
---
a/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/ProviderRpcFilter.java
+++ /dev/null
@@ -1,110 +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.rpc.core;
-
-import org.apache.seata.common.util.StringUtils;
-import org.apache.seata.core.context.RootContext;
-import org.apache.seata.core.model.BranchType;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public interface ProviderRpcFilter<T> extends BaseRpcFilter<T> {
-
- String[] TRX_CONTEXT_KEYS =
- new String[] {RootContext.KEY_XID,
RootContext.KEY_XID.toLowerCase(), RootContext.KEY_BRANCH_TYPE};
-
- String LOW_KEY_XID = "tx_xid";
-
- /**
- * get contexts from RpcRequest
- *
- * @param rpcRequest
- * @return
- */
- default Map<String, String> getRpcContexts(T rpcRequest) {
- Map<String, String> contextMap = new HashMap<>();
- for (int i = 0; i < TRX_CONTEXT_KEYS.length; i++) {
- String contextValue = getRpcContext(rpcRequest,
TRX_CONTEXT_KEYS[i]);
- if (StringUtils.isNotBlank(contextValue)) {
- contextMap.put(TRX_CONTEXT_KEYS[i], contextValue);
- }
- }
- return contextMap;
- }
-
- String getRpcContext(T rpcContext, String key);
-
- default String getXidFromContexts(Map<String, String> rpcContextMap) {
- String xid = getValueFromMap(rpcContextMap, RootContext.KEY_XID);
- if (StringUtils.isBlank(xid)) {
- return getValueFromMap(rpcContextMap,
RootContext.KEY_XID.toLowerCase());
- }
- return xid;
- }
-
- default void bindRequestToContexts(Map<String, String> contextMap) {
- for (int i = 0; i < TRX_CONTEXT_KEYS.length; i++) {
- String contextValue = contextMap.get(TRX_CONTEXT_KEYS[i]);
- if (StringUtils.isNotBlank(contextValue)) {
- switch (TRX_CONTEXT_KEYS[i]) {
- case RootContext.KEY_XID:
- case LOW_KEY_XID:
- RootContext.bind(contextValue);
- break;
- case RootContext.KEY_BRANCH_TYPE:
- if
(BranchType.TCC.name().equalsIgnoreCase(contextValue)) {
- RootContext.bindBranchType(BranchType.TCC);
- }
- break;
- default:
- throw new IllegalArgumentException("wrong context:" +
TRX_CONTEXT_KEYS[i]);
- }
- }
- }
- }
-
- default Map<String, String> cleanRootContexts() {
- Map<String, String> contextMap = new HashMap<>();
- for (int i = 0; i < TRX_CONTEXT_KEYS.length; i++) {
- switch (TRX_CONTEXT_KEYS[i]) {
- case RootContext.KEY_XID:
- String xid = RootContext.unbind();
- contextMap.put(RootContext.KEY_XID, xid);
- break;
- case LOW_KEY_XID:
- break;
- case RootContext.KEY_BRANCH_TYPE:
- BranchType contextValue = RootContext.getBranchType();
- if (BranchType.TCC == contextValue) {
- RootContext.unbindBranchType();
- }
- if (null != contextValue) {
- contextMap.put(RootContext.KEY_BRANCH_TYPE,
contextValue.name());
- }
- break;
- default:
- throw new IllegalArgumentException("wrong context:" +
TRX_CONTEXT_KEYS[i]);
- }
- }
- return contextMap;
- }
-
- default void resetRootContexts(Map<String, String> contextMap) {
- bindRequestToContexts(contextMap);
- }
-}
diff --git
a/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/TransactionPropagationHandler.java
b/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/TransactionPropagationHandler.java
new file mode 100644
index 0000000000..fa0ba68bc9
--- /dev/null
+++
b/extensions/rpc/seata-rpc-core/src/main/java/org/apache/seata/integration/rpc/core/TransactionPropagationHandler.java
@@ -0,0 +1,77 @@
+/*
+ * 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.rpc.core;
+
+import org.apache.seata.core.context.RootContext;
+import org.apache.seata.core.model.BranchType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public final class TransactionPropagationHandler {
+
+ private static final Logger LOGGER =
LoggerFactory.getLogger(TransactionPropagationHandler.class);
+
+ private TransactionPropagationHandler() {}
+
+ public static Map<String, String> getTransactionPropagationContext() {
+ Map<String, String> context = new HashMap<>();
+ String xid = RootContext.getXID();
+ if (xid != null) {
+ context.put(RootContext.KEY_XID, xid);
+ BranchType branchType = RootContext.getBranchType();
+ if (branchType != null) {
+ context.put(RootContext.KEY_BRANCH_TYPE, branchType.name());
+ }
+ }
+ return context;
+ }
+
+ public static boolean bindProviderContext(String rpcXid, String
rpcBranchType) {
+ if (rpcXid == null) {
+ return false;
+ }
+ RootContext.bind(rpcXid);
+ if (BranchType.TCC.name().equalsIgnoreCase(rpcBranchType)) {
+ RootContext.bindBranchType(BranchType.TCC);
+ }
+ return true;
+ }
+
+ public static void unbindProviderContext(String rpcXid) {
+ BranchType previousBranchType = RootContext.getBranchType();
+ String unbindXid = RootContext.unbind();
+ if (BranchType.TCC == previousBranchType) {
+ RootContext.unbindBranchType();
+ }
+ if (rpcXid != null && !rpcXid.equalsIgnoreCase(unbindXid)) {
+ LOGGER.warn("xid changed during RPC from {} to {}", rpcXid,
unbindXid);
+ if (unbindXid != null) {
+ RootContext.bind(unbindXid);
+ if (BranchType.TCC == previousBranchType) {
+ RootContext.bindBranchType(BranchType.TCC);
+ }
+ }
+ }
+ }
+
+ public static String resolveXid(String xid, String xidLowercase) {
+ return xid != null ? xid : xidLowercase;
+ }
+}
diff --git
a/extensions/rpc/seata-rpc-core/src/test/java/org/apache/seata/integration/rpc/core/TransactionPropagationHandlerTest.java
b/extensions/rpc/seata-rpc-core/src/test/java/org/apache/seata/integration/rpc/core/TransactionPropagationHandlerTest.java
new file mode 100644
index 0000000000..5470e8bd7e
--- /dev/null
+++
b/extensions/rpc/seata-rpc-core/src/test/java/org/apache/seata/integration/rpc/core/TransactionPropagationHandlerTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.rpc.core;
+
+import org.apache.seata.core.context.RootContext;
+import org.apache.seata.core.model.BranchType;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class TransactionPropagationHandlerTest {
+
+ private static final String DEFAULT_XID = "127.0.0.1:8091:12345678";
+
+ @AfterEach
+ void cleanup() {
+ RootContext.unbind();
+ RootContext.unbindBranchType();
+ }
+
+ @Test
+ void testGetTransactionPropagationContext_noTransaction() {
+ Map<String, String> context =
TransactionPropagationHandler.getTransactionPropagationContext();
+ assertThat(context).isEmpty();
+ }
+
+ @Test
+ void testGetTransactionPropagationContext_withXid() {
+ RootContext.bind(DEFAULT_XID);
+ Map<String, String> context =
TransactionPropagationHandler.getTransactionPropagationContext();
+ assertThat(context).containsEntry(RootContext.KEY_XID, DEFAULT_XID);
+ assertThat(context).containsEntry(RootContext.KEY_BRANCH_TYPE,
BranchType.AT.name());
+ }
+
+ @Test
+ void testGetTransactionPropagationContext_withXidAndBranchType() {
+ RootContext.bind(DEFAULT_XID);
+ RootContext.bindBranchType(BranchType.TCC);
+ Map<String, String> context =
TransactionPropagationHandler.getTransactionPropagationContext();
+ assertThat(context).containsEntry(RootContext.KEY_XID, DEFAULT_XID);
+ assertThat(context).containsEntry(RootContext.KEY_BRANCH_TYPE,
BranchType.TCC.name());
+ }
+
+ @Test
+ void testBindProviderContext_nullXid() {
+ boolean bound =
TransactionPropagationHandler.bindProviderContext(null, null);
+ assertThat(bound).isFalse();
+ assertThat(RootContext.getXID()).isNull();
+ }
+
+ @Test
+ void testBindProviderContext_withXid() {
+ boolean bound =
TransactionPropagationHandler.bindProviderContext(DEFAULT_XID, null);
+ assertThat(bound).isTrue();
+ assertThat(RootContext.getXID()).isEqualTo(DEFAULT_XID);
+ assertThat(RootContext.getBranchType()).isEqualTo(BranchType.AT);
+ }
+
+ @Test
+ void testBindProviderContext_withTCC() {
+ boolean bound =
TransactionPropagationHandler.bindProviderContext(DEFAULT_XID,
BranchType.TCC.name());
+ assertThat(bound).isTrue();
+ assertThat(RootContext.getXID()).isEqualTo(DEFAULT_XID);
+ assertThat(RootContext.getBranchType()).isEqualTo(BranchType.TCC);
+ }
+
+ @Test
+ void testBindProviderContext_withNonTCCBranchType() {
+ boolean bound =
TransactionPropagationHandler.bindProviderContext(DEFAULT_XID,
BranchType.AT.name());
+ assertThat(bound).isTrue();
+ assertThat(RootContext.getXID()).isEqualTo(DEFAULT_XID);
+ assertThat(RootContext.getBranchType()).isEqualTo(BranchType.AT);
+ }
+
+ @Test
+ void testUnbindProviderContext_normalFlow() {
+ RootContext.bind(DEFAULT_XID);
+ TransactionPropagationHandler.unbindProviderContext(DEFAULT_XID);
+ assertThat(RootContext.getXID()).isNull();
+ }
+
+ @Test
+ void testUnbindProviderContext_withTCCBranchType() {
+ RootContext.bind(DEFAULT_XID);
+ RootContext.bindBranchType(BranchType.TCC);
+ TransactionPropagationHandler.unbindProviderContext(DEFAULT_XID);
+ assertThat(RootContext.getXID()).isNull();
+ assertThat(RootContext.getBranchType()).isNull();
+ }
+
+ @Test
+ void testUnbindProviderContext_xidChanged() {
+ String changedXid = "127.0.0.1:8091:99999999";
+ RootContext.bind(changedXid);
+ TransactionPropagationHandler.unbindProviderContext(DEFAULT_XID);
+ assertThat(RootContext.getXID()).isEqualTo(changedXid);
+ }
+
+ @Test
+ void testUnbindProviderContext_xidChangedWithTCC() {
+ String changedXid = "127.0.0.1:8091:99999999";
+ RootContext.bind(changedXid);
+ RootContext.bindBranchType(BranchType.TCC);
+ TransactionPropagationHandler.unbindProviderContext(DEFAULT_XID);
+ assertThat(RootContext.getXID()).isEqualTo(changedXid);
+ assertThat(RootContext.getBranchType()).isEqualTo(BranchType.TCC);
+ }
+
+ @Test
+ void testResolveXid_xidNotNull() {
+ assertThat(TransactionPropagationHandler.resolveXid("xid1",
"xid2")).isEqualTo("xid1");
+ }
+
+ @Test
+ void testResolveXid_xidNull() {
+ assertThat(TransactionPropagationHandler.resolveXid(null,
"xid2")).isEqualTo("xid2");
+ }
+
+ @Test
+ void testResolveXid_bothNull() {
+ assertThat(TransactionPropagationHandler.resolveXid(null,
null)).isNull();
+ }
+}
diff --git a/extensions/rpc/seata-sofa-rpc/pom.xml
b/extensions/rpc/seata-sofa-rpc/pom.xml
index be1e9b225c..338e9a8474 100644
--- a/extensions/rpc/seata-sofa-rpc/pom.xml
+++ b/extensions/rpc/seata-sofa-rpc/pom.xml
@@ -35,7 +35,7 @@
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>seata-tm</artifactId>
+ <artifactId>seata-rpc-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git
a/extensions/rpc/seata-sofa-rpc/src/main/java/org/apache/seata/integration/sofa/rpc/TransactionContextConsumerFilter.java
b/extensions/rpc/seata-sofa-rpc/src/main/java/org/apache/seata/integration/sofa/rpc/TransactionContextConsumerFilter.java
index 95132320af..af650d0095 100644
---
a/extensions/rpc/seata-sofa-rpc/src/main/java/org/apache/seata/integration/sofa/rpc/TransactionContextConsumerFilter.java
+++
b/extensions/rpc/seata-sofa-rpc/src/main/java/org/apache/seata/integration/sofa/rpc/TransactionContextConsumerFilter.java
@@ -16,7 +16,6 @@
*/
package org.apache.seata.integration.sofa.rpc;
-import com.alipay.sofa.rpc.context.RpcInternalContext;
import com.alipay.sofa.rpc.core.exception.SofaRpcException;
import com.alipay.sofa.rpc.core.request.SofaRequest;
import com.alipay.sofa.rpc.core.response.SofaResponse;
@@ -24,100 +23,28 @@ import com.alipay.sofa.rpc.ext.Extension;
import com.alipay.sofa.rpc.filter.AutoActive;
import com.alipay.sofa.rpc.filter.Filter;
import com.alipay.sofa.rpc.filter.FilterInvoker;
-import org.apache.seata.common.util.StringUtils;
-import org.apache.seata.core.context.RootContext;
-import org.apache.seata.core.model.BranchType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
+
+import java.util.Map;
-/**
- * TransactionContext on consumer side.
- *
- * @since 0.6.0
- */
@Extension(value = "transactionContextConsumer")
@AutoActive(consumerSide = true)
public class TransactionContextConsumerFilter extends Filter {
- /**
- * Logger for this class
- */
- private static final Logger LOGGER =
LoggerFactory.getLogger(TransactionContextConsumerFilter.class);
-
@Override
public SofaResponse invoke(FilterInvoker filterInvoker, SofaRequest
sofaRequest) throws SofaRpcException {
- String xid = RootContext.getXID();
- String rpcXid = getRpcXid();
- BranchType branchType = RootContext.getBranchType();
- String rpcBranchType = getBranchType();
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug(
- "context in RootContext[{},{}], context in
RpcContext[{},{}]",
- xid,
- branchType,
- rpcXid,
- rpcBranchType);
- }
- boolean bind = false;
- if (xid != null) {
- sofaRequest.addRequestProp(RootContext.KEY_XID, xid);
- sofaRequest.addRequestProp(RootContext.KEY_BRANCH_TYPE,
branchType.name());
- } else {
- if (rpcXid != null) {
- RootContext.bind(rpcXid);
- if (StringUtils.equals(BranchType.TCC.name(), rpcBranchType)) {
- RootContext.bindBranchType(BranchType.TCC);
- }
- bind = true;
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("bind[{}] to RootContext", rpcXid);
- }
+ Map<String, String> context =
TransactionPropagationHandler.getTransactionPropagationContext();
+ if (!context.isEmpty()) {
+ for (Map.Entry<String, String> entry : context.entrySet()) {
+ sofaRequest.addRequestProp(entry.getKey(), entry.getValue());
}
}
try {
return filterInvoker.invoke(sofaRequest);
} finally {
- if (bind) {
- String unbindXid = RootContext.unbind();
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("unbind[{}] from RootContext", unbindXid);
- }
- BranchType previousBranchType = RootContext.getBranchType();
- if (BranchType.TCC == previousBranchType) {
- RootContext.unbindBranchType();
- }
- if (!rpcXid.equalsIgnoreCase(unbindXid)) {
- if (LOGGER.isWarnEnabled()) {
- LOGGER.warn("xid in change during RPC from [{}] to
[{}]", rpcXid, unbindXid);
- }
- if (unbindXid != null) {
- RootContext.bind(unbindXid);
- if (LOGGER.isWarnEnabled()) {
- LOGGER.warn("bind [{}] back to RootContext",
unbindXid);
- }
- if (BranchType.TCC == previousBranchType) {
- RootContext.bindBranchType(BranchType.TCC);
- LOGGER.warn("bind branchType [{}] back to
RootContext", previousBranchType);
- }
- }
- }
+ for (String key : context.keySet()) {
+ sofaRequest.removeRequestProp(key);
}
}
}
-
- /**
- * get rpc xid
- * @return
- */
- private String getRpcXid() {
- String rpcXid = (String)
RpcInternalContext.getContext().getAttachment(RootContext.HIDDEN_KEY_XID);
- if (rpcXid == null) {
- rpcXid = (String)
RpcInternalContext.getContext().getAttachment(RootContext.HIDDEN_KEY_XID.toLowerCase());
- }
- return rpcXid;
- }
-
- private String getBranchType() {
- return (String)
RpcInternalContext.getContext().getAttachment(RootContext.HIDDEN_KEY_BRANCH_TYPE);
- }
}
diff --git
a/extensions/rpc/seata-sofa-rpc/src/main/java/org/apache/seata/integration/sofa/rpc/TransactionContextProviderFilter.java
b/extensions/rpc/seata-sofa-rpc/src/main/java/org/apache/seata/integration/sofa/rpc/TransactionContextProviderFilter.java
index e2d0579f9e..9fa2b9a50d 100644
---
a/extensions/rpc/seata-sofa-rpc/src/main/java/org/apache/seata/integration/sofa/rpc/TransactionContextProviderFilter.java
+++
b/extensions/rpc/seata-sofa-rpc/src/main/java/org/apache/seata/integration/sofa/rpc/TransactionContextProviderFilter.java
@@ -16,7 +16,6 @@
*/
package org.apache.seata.integration.sofa.rpc;
-import com.alipay.sofa.rpc.context.RpcInternalContext;
import com.alipay.sofa.rpc.core.exception.SofaRpcException;
import com.alipay.sofa.rpc.core.request.SofaRequest;
import com.alipay.sofa.rpc.core.response.SofaResponse;
@@ -24,95 +23,27 @@ import com.alipay.sofa.rpc.ext.Extension;
import com.alipay.sofa.rpc.filter.AutoActive;
import com.alipay.sofa.rpc.filter.Filter;
import com.alipay.sofa.rpc.filter.FilterInvoker;
-import org.apache.seata.common.util.StringUtils;
import org.apache.seata.core.context.RootContext;
-import org.apache.seata.core.model.BranchType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.seata.integration.rpc.core.TransactionPropagationHandler;
-/**
- * TransactionContext on provider side.
- *
- * @since 0.6.0
- */
@Extension(value = "transactionContextProvider")
@AutoActive(providerSide = true)
public class TransactionContextProviderFilter extends Filter {
- /**
- * Logger for this class
- */
- private static final Logger LOGGER =
LoggerFactory.getLogger(TransactionContextProviderFilter.class);
-
@Override
public SofaResponse invoke(FilterInvoker filterInvoker, SofaRequest
sofaRequest) throws SofaRpcException {
- String xid = RootContext.getXID();
String rpcXid = getRpcXid(sofaRequest);
- BranchType branchType = RootContext.getBranchType();
- String rpcBranchType = getBranchType(sofaRequest);
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug(
- "context in RootContext[{},{}], context in
RpcContext[{},{}]",
- xid,
- branchType,
- rpcXid,
- rpcBranchType);
- }
- boolean bind = false;
- if (xid != null) {
-
RpcInternalContext.getContext().setAttachment(RootContext.HIDDEN_KEY_XID, xid);
-
RpcInternalContext.getContext().setAttachment(RootContext.HIDDEN_KEY_BRANCH_TYPE,
branchType.name());
- } else {
- if (null != rpcXid) {
- RootContext.bind(rpcXid);
- if (StringUtils.equals(BranchType.TCC.name(), rpcBranchType)) {
- RootContext.bindBranchType(BranchType.TCC);
- }
- bind = true;
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("bind[{}] to RootContext", rpcXid);
- }
- }
- }
+ String rpcBranchType = (String)
sofaRequest.getRequestProp(RootContext.KEY_BRANCH_TYPE);
+ boolean bound =
TransactionPropagationHandler.bindProviderContext(rpcXid, rpcBranchType);
try {
return filterInvoker.invoke(sofaRequest);
} finally {
- if (xid != null) {
-
RpcInternalContext.getContext().removeAttachment(RootContext.HIDDEN_KEY_XID);
-
RpcInternalContext.getContext().removeAttachment(RootContext.HIDDEN_KEY_BRANCH_TYPE);
- }
- if (bind) {
- String unbindXid = RootContext.unbind();
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("unbind[{}] from RootContext", unbindXid);
- }
- BranchType previousBranchType = RootContext.getBranchType();
- if (BranchType.TCC == previousBranchType) {
- RootContext.unbindBranchType();
- }
- if (!rpcXid.equalsIgnoreCase(unbindXid)) {
- if (LOGGER.isWarnEnabled()) {
- LOGGER.warn("xid in change during RPC from [{}] to
[{}]", rpcXid, unbindXid);
- }
- if (unbindXid != null) {
- RootContext.bind(unbindXid);
- if (LOGGER.isWarnEnabled()) {
- LOGGER.warn("bind [{}] back to RootContext",
unbindXid);
- }
- if (BranchType.TCC == previousBranchType) {
- RootContext.bindBranchType(BranchType.TCC);
- LOGGER.warn("bind branchType [{}] back to
RootContext", previousBranchType);
- }
- }
- }
+ if (bound) {
+ TransactionPropagationHandler.unbindProviderContext(rpcXid);
}
}
}
- /**
- * get rpc xid
- * @return
- */
private String getRpcXid(SofaRequest sofaRequest) {
String rpcXid = (String)
sofaRequest.getRequestProp(RootContext.KEY_XID);
if (rpcXid == null) {
@@ -120,8 +51,4 @@ public class TransactionContextProviderFilter extends Filter
{
}
return rpcXid;
}
-
- private String getBranchType(SofaRequest sofaRequest) {
- return (String)
sofaRequest.getRequestProp(RootContext.KEY_BRANCH_TYPE);
- }
}
diff --git
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/ConnectionProxyTest.java
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/ConnectionProxyTest.java
index 6f82a14c32..323ac00403 100644
---
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/ConnectionProxyTest.java
+++
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/ConnectionProxyTest.java
@@ -23,6 +23,7 @@ import
org.apache.seata.core.exception.TransactionExceptionCode;
import org.apache.seata.core.model.BranchStatus;
import org.apache.seata.core.model.BranchType;
import org.apache.seata.core.model.GlobalLockConfig;
+import org.apache.seata.core.model.ResourceManager;
import org.apache.seata.rm.DefaultResourceManager;
import org.apache.seata.rm.datasource.ConnectionProxy.LockRetryPolicy;
import org.apache.seata.rm.datasource.exec.LockConflictException;
@@ -57,12 +58,13 @@ public class ConnectionProxyTest {
private static final String TEST_XID = "testXid";
- private static final String lockKey = "order:123";
+ private static final String LOCK_KEY = "order:123";
private static final String DB_TYPE = "mysql";
private Field branchRollbackFlagField;
private boolean originalBranchRollbackFlag;
+ private ResourceManager originalAtResourceManager;
@BeforeEach
public void initBeforeEach() throws Exception {
@@ -85,16 +87,23 @@ public class ConnectionProxyTest {
null,
TEST_XID,
"{\"autoCommit\":false}",
- lockKey))
+ LOCK_KEY))
.thenThrow(new
TransactionException(TransactionExceptionCode.LockKeyConflict));
DefaultResourceManager defaultResourceManager =
DefaultResourceManager.get();
Assertions.assertNotNull(defaultResourceManager);
+ originalAtResourceManager =
defaultResourceManager.getResourceManager(BranchType.AT);
DefaultResourceManager.mockResourceManager(BranchType.AT, rm);
}
@org.junit.jupiter.api.AfterEach
public void cleanupAfterEach() throws Exception {
- branchRollbackFlagField.set(null, originalBranchRollbackFlag);
+ try {
+ branchRollbackFlagField.set(null, originalBranchRollbackFlag);
+ } finally {
+ if (originalAtResourceManager != null) {
+ DefaultResourceManager.mockResourceManager(BranchType.AT,
originalAtResourceManager);
+ }
+ }
}
@Test
@@ -114,7 +123,7 @@ public class ConnectionProxyTest {
sqlUndoLog.setBeforeImage(beforeImage);
connectionProxy.getContext().appendUndoItem(sqlUndoLog);
connectionProxy.appendUndoLog(new SQLUndoLog());
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
Assertions.assertThrows(LockWaitTimeoutException.class,
connectionProxy::commit);
}
}
@@ -130,7 +139,7 @@ public class ConnectionProxyTest {
ConnectionProxy connectionProxy = new ConnectionProxy(dataSourceProxy,
null);
connectionProxy.bind(TEST_XID);
connectionProxy.appendUndoLog(new SQLUndoLog());
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
SQLUndoLog sqlUndoLog = new SQLUndoLog();
TableRecords beforeImage = new TableRecords();
beforeImage.add(new Row());
@@ -246,7 +255,7 @@ public class ConnectionProxyTest {
beforeImage.add(new Row());
sqlUndoLog.setBeforeImage(beforeImage);
connectionProxy.appendUndoLog(sqlUndoLog);
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
connectionProxy.commit();
@@ -257,7 +266,7 @@ public class ConnectionProxyTest {
Mockito.isNull(),
Mockito.eq(TEST_XID),
Mockito.anyString(),
- Mockito.eq(lockKey));
+ Mockito.eq(LOCK_KEY));
}
}
@@ -273,12 +282,12 @@ public class ConnectionProxyTest {
connectionProxy.setAutoCommit(false);
connectionProxy.setGlobalLockRequire(true);
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
connectionProxy.commit();
Mockito.verify(rm)
- .lockQuery(Mockito.eq(BranchType.AT), Mockito.anyString(),
Mockito.isNull(), Mockito.eq(lockKey));
+ .lockQuery(Mockito.eq(BranchType.AT), Mockito.anyString(),
Mockito.isNull(), Mockito.eq(LOCK_KEY));
}
}
@@ -343,7 +352,7 @@ public class ConnectionProxyTest {
beforeImage.add(new Row());
sqlUndoLog.setBeforeImage(beforeImage);
connectionProxy.appendUndoLog(sqlUndoLog);
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
connectionProxy.commit();
@@ -372,7 +381,7 @@ public class ConnectionProxyTest {
Mockito.isNull(),
Mockito.eq(TEST_XID),
Mockito.anyString(),
- Mockito.eq(lockKey)))
+ Mockito.eq(LOCK_KEY)))
.thenReturn(789L);
DefaultResourceManager.mockResourceManager(BranchType.AT, rm);
@@ -383,7 +392,7 @@ public class ConnectionProxyTest {
beforeImage.add(new Row());
sqlUndoLog.setBeforeImage(beforeImage);
connectionProxy.appendUndoLog(sqlUndoLog);
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
connectionProxy.commit();
@@ -394,7 +403,7 @@ public class ConnectionProxyTest {
Mockito.isNull(),
Mockito.eq(TEST_XID),
Mockito.anyString(),
- Mockito.eq(lockKey));
+ Mockito.eq(LOCK_KEY));
}
}
@@ -407,7 +416,7 @@ public class ConnectionProxyTest {
connectionProxy.setAutoCommit(false);
connectionProxy.bind(TEST_XID);
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
connectionProxy.commit();
@@ -467,7 +476,7 @@ public class ConnectionProxyTest {
beforeImage.add(new Row());
sqlUndoLog.setBeforeImage(beforeImage);
connectionProxy.appendUndoLog(sqlUndoLog);
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
connectionProxy.commit();
@@ -509,7 +518,7 @@ public class ConnectionProxyTest {
beforeImage.add(new Row());
sqlUndoLog.setBeforeImage(beforeImage);
connectionProxy.appendUndoLog(sqlUndoLog);
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
Assertions.assertThrows(SQLException.class, connectionProxy::commit);
@@ -553,7 +562,7 @@ public class ConnectionProxyTest {
beforeImage.add(new Row());
sqlUndoLog.setBeforeImage(beforeImage);
connectionProxy.appendUndoLog(sqlUndoLog);
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
connectionProxy.commit();
@@ -591,7 +600,7 @@ public class ConnectionProxyTest {
beforeImage.add(new Row());
sqlUndoLog.setBeforeImage(beforeImage);
connectionProxy.appendUndoLog(sqlUndoLog);
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
connectionProxy.setAutoCommit(true);
@@ -602,7 +611,7 @@ public class ConnectionProxyTest {
Mockito.isNull(),
Mockito.eq(TEST_XID),
Mockito.anyString(),
- Mockito.eq(lockKey));
+ Mockito.eq(LOCK_KEY));
Assertions.assertTrue(mockConnection.getAutoCommit());
}
}
@@ -619,12 +628,12 @@ public class ConnectionProxyTest {
connectionProxy.setAutoCommit(false);
connectionProxy.setGlobalLockRequire(true);
- connectionProxy.appendLockKey(lockKey);
+ connectionProxy.appendLockKey(LOCK_KEY);
connectionProxy.setAutoCommit(true);
Mockito.verify(rm)
- .lockQuery(Mockito.eq(BranchType.AT), Mockito.anyString(),
Mockito.isNull(), Mockito.eq(lockKey));
+ .lockQuery(Mockito.eq(BranchType.AT), Mockito.anyString(),
Mockito.isNull(), Mockito.eq(LOCK_KEY));
Assertions.assertTrue(mockConnection.getAutoCommit());
}
}
@@ -638,20 +647,20 @@ public class ConnectionProxyTest {
Mockito.eq(BranchType.AT),
Mockito.eq(TEST_RESOURCE_ID),
Mockito.eq(TEST_XID),
- Mockito.eq(lockKey)))
+ Mockito.eq(LOCK_KEY)))
.thenReturn(true);
DefaultResourceManager.mockResourceManager(BranchType.AT, rm);
connectionProxy.bind(TEST_XID);
- connectionProxy.checkLock(lockKey);
+ connectionProxy.checkLock(LOCK_KEY);
Mockito.verify(rm)
.lockQuery(
Mockito.eq(BranchType.AT),
Mockito.eq(TEST_RESOURCE_ID),
Mockito.eq(TEST_XID),
- Mockito.eq(lockKey));
+ Mockito.eq(LOCK_KEY));
}
}
@@ -664,13 +673,13 @@ public class ConnectionProxyTest {
Mockito.eq(BranchType.AT),
Mockito.eq(TEST_RESOURCE_ID),
Mockito.eq(TEST_XID),
- Mockito.eq(lockKey)))
+ Mockito.eq(LOCK_KEY)))
.thenReturn(false);
DefaultResourceManager.mockResourceManager(BranchType.AT, rm);
connectionProxy.bind(TEST_XID);
- Assertions.assertThrows(LockConflictException.class, () ->
connectionProxy.checkLock(lockKey));
+ Assertions.assertThrows(LockConflictException.class, () ->
connectionProxy.checkLock(LOCK_KEY));
}
}
@@ -683,13 +692,13 @@ public class ConnectionProxyTest {
Mockito.eq(BranchType.AT),
Mockito.eq(TEST_RESOURCE_ID),
Mockito.eq(TEST_XID),
- Mockito.eq(lockKey)))
+ Mockito.eq(LOCK_KEY)))
.thenReturn(true);
DefaultResourceManager.mockResourceManager(BranchType.AT, rm);
connectionProxy.bind(TEST_XID);
- boolean result = connectionProxy.lockQuery(lockKey);
+ boolean result = connectionProxy.lockQuery(LOCK_KEY);
Assertions.assertTrue(result);
}
@@ -704,13 +713,13 @@ public class ConnectionProxyTest {
Mockito.eq(BranchType.AT),
Mockito.eq(TEST_RESOURCE_ID),
Mockito.eq(TEST_XID),
- Mockito.eq(lockKey)))
+ Mockito.eq(LOCK_KEY)))
.thenReturn(false);
DefaultResourceManager.mockResourceManager(BranchType.AT, rm);
connectionProxy.bind(TEST_XID);
- boolean result = connectionProxy.lockQuery(lockKey);
+ boolean result = connectionProxy.lockQuery(LOCK_KEY);
Assertions.assertFalse(result);
}
@@ -772,14 +781,14 @@ public class ConnectionProxyTest {
Mockito.eq(BranchType.AT),
Mockito.eq(TEST_RESOURCE_ID),
Mockito.eq(TEST_XID),
- Mockito.eq(lockKey)))
+ Mockito.eq(LOCK_KEY)))
.thenThrow(new
TransactionException(TransactionExceptionCode.LockKeyConflict, "lock
conflict"));
DefaultResourceManager.mockResourceManager(BranchType.AT, rm);
connectionProxy.bind(TEST_XID);
LockConflictException exception =
- Assertions.assertThrows(LockConflictException.class, () ->
connectionProxy.checkLock(lockKey));
+ Assertions.assertThrows(LockConflictException.class, () ->
connectionProxy.checkLock(LOCK_KEY));
Assertions.assertEquals(TransactionExceptionCode.LockKeyConflict,
exception.getCode());
}
}
@@ -793,7 +802,7 @@ public class ConnectionProxyTest {
Mockito.eq(BranchType.AT),
Mockito.eq(TEST_RESOURCE_ID),
Mockito.eq(TEST_XID),
- Mockito.eq(lockKey)))
+ Mockito.eq(LOCK_KEY)))
.thenThrow(new TransactionException(
TransactionExceptionCode.LockKeyConflictFailFast,
"lock conflict fail fast"));
DefaultResourceManager.mockResourceManager(BranchType.AT, rm);
@@ -801,7 +810,7 @@ public class ConnectionProxyTest {
connectionProxy.bind(TEST_XID);
LockConflictException exception =
- Assertions.assertThrows(LockConflictException.class, () ->
connectionProxy.checkLock(lockKey));
+ Assertions.assertThrows(LockConflictException.class, () ->
connectionProxy.checkLock(LOCK_KEY));
Assertions.assertEquals(TransactionExceptionCode.LockKeyConflictFailFast,
exception.getCode());
}
}
diff --git
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/DataSourceProxyTest.java
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/DataSourceProxyTest.java
index ae0311c145..dd362aae73 100644
---
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/DataSourceProxyTest.java
+++
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/DataSourceProxyTest.java
@@ -17,6 +17,8 @@
package org.apache.seata.rm.datasource;
import com.alibaba.druid.pool.DruidDataSource;
+import org.apache.seata.core.model.BranchType;
+import org.apache.seata.core.model.ResourceManager;
import org.apache.seata.rm.DefaultResourceManager;
import org.apache.seata.rm.datasource.mock.MockDataSource;
import org.apache.seata.rm.datasource.mock.MockDriver;
@@ -256,13 +258,14 @@ public class DataSourceProxyTest {
DataSourceProxy proxy = getDataSourceProxy(dataSource);
+ ResourceManager atManager =
DefaultResourceManager.get().getResourceManager(BranchType.AT);
+
// Ensure it's registered
- Assertions.assertNotNull(
-
DefaultResourceManager.get().getManagedResources().get(proxy.getResourceId()));
+
Assertions.assertNotNull(atManager.getManagedResources().get(proxy.getResourceId()));
proxy.close();
// Ensure it's unregistered
-
Assertions.assertNull(DefaultResourceManager.get().getManagedResources().get(proxy.getResourceId()));
+
Assertions.assertNull(atManager.getManagedResources().get(proxy.getResourceId()));
}
}
diff --git
a/test-suite/test-new-version/src/test/java/org/apache/seata/core/rpc/netty/TmNettyClientTest.java
b/test-suite/test-new-version/src/test/java/org/apache/seata/core/rpc/netty/TmNettyClientTest.java
index e1cf6e6957..434f289ea2 100644
---
a/test-suite/test-new-version/src/test/java/org/apache/seata/core/rpc/netty/TmNettyClientTest.java
+++
b/test-suite/test-new-version/src/test/java/org/apache/seata/core/rpc/netty/TmNettyClientTest.java
@@ -91,7 +91,7 @@ public class TmNettyClientTest extends BaseNettyClientTest {
@Test
public void testSendMsgWithResponse() throws Exception {
int dynamicPort = getDynamicPort();
- ServerInstance serverInstance = startServerSimple(dynamicPort);
+ ServerInstance serverInstance = startServer(dynamicPort);
try {
configureClient(dynamicPort);
@@ -111,7 +111,7 @@ public class TmNettyClientTest extends BaseNettyClientTest {
request.setXid("127.0.0.1:" + dynamicPort + ":1249853");
GlobalCommitResponse globalCommitResponse = null;
try {
- globalCommitResponse = (GlobalCommitResponse)
tmNettyRemotingClient.sendSyncRequest(request);
+ globalCommitResponse = (GlobalCommitResponse)
tmNettyRemotingClient.sendSyncRequest(channel, request);
} catch (TimeoutException e) {
throw new RuntimeException(e);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]