This is an automated email from the ASF dual-hosted git repository.

jimin 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 06ec3fe4e2 refactor: Refactor Alibaba Dubbo and HSF (#7617)
06ec3fe4e2 is described below

commit 06ec3fe4e201299b08f6d85b8de2fb8bed297141
Author: jimin <[email protected]>
AuthorDate: Thu Oct 9 11:35:48 2025 +0800

    refactor: Refactor Alibaba Dubbo and HSF (#7617)
---
 changes/en-us/2.x.md                               |   2 +-
 changes/zh-cn/2.x.md                               |   2 +-
 .../AlibabaDubboTransactionConsumerFilter.java     |  29 ++-
 .../AlibabaDubboTransactionProviderFilter.java     | 137 +++++++---
 .../AlibabaDubboTransactionProviderFilterTest.java | 277 +++++++++++++++++++++
 .../hsf/HsfTransactionConsumerFilter.java          |  61 ++++-
 .../hsf/HsfTransactionProviderFilter.java          | 173 ++++++++++---
 7 files changed, 591 insertions(+), 90 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 63aaa16183..b0400c79a5 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -81,7 +81,7 @@ Add changes here for all PR submitted to the 2.x branch.
 
 ### refactor:
 
-- [[#PR_NO](https://github.com/seata/seata/pull/PR_NO)] refactor for XXX
+- [[#7617](https://github.com/seata/seata/pull/7617)] Refactor Alibaba Dubbo 
and HSF
 
 
 ### doc:
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index f3783f8234..981153aff7 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -81,7 +81,7 @@
 
 ### refactor:
 
-- [[#PR_NO](https://github.com/seata/seata/pull/PR_NO)] 重构 XXX
+- [[#7617](https://github.com/seata/seata/pull/7617)] 重构 Alibaba Dubbo 和 HSF 模块
 
 
 ### doc:
diff --git 
a/integration/dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionConsumerFilter.java
 
b/integration/dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionConsumerFilter.java
index e3aa8244fe..4549dfd5dc 100644
--- 
a/integration/dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionConsumerFilter.java
+++ 
b/integration/dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionConsumerFilter.java
@@ -44,21 +44,38 @@ public class AlibabaDubboTransactionConsumerFilter 
implements Filter {
         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);
         }
+        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);
+            }
         }
-        try {
-            return invoker.invoke(invocation);
-        } finally {
-            RpcContext.getContext().removeAttachment(RootContext.KEY_XID);
-            
RpcContext.getContext().removeAttachment(RootContext.KEY_BRANCH_TYPE);
+    }
+
+    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/integration/dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionProviderFilter.java
 
b/integration/dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionProviderFilter.java
index f361f1c457..7c8a4fddf9 100644
--- 
a/integration/dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionProviderFilter.java
+++ 
b/integration/dubbo-alibaba/src/main/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionProviderFilter.java
@@ -45,54 +45,100 @@ public class AlibabaDubboTransactionProviderFilter 
implements Filter {
         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);
         }
-        boolean bind = false;
+
+        TransactionContextBinding binding = bindTransactionContext(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);
             }
-            bind = true;
         }
 
-        try {
-            return invoker.invoke(invocation);
-        } 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 (!rpcXid.equalsIgnoreCase(unbindXid)) {
-                    LOGGER.warn(
-                            "xid in change during RPC from {} to {},branchType 
from {} to {}",
-                            rpcXid,
-                            unbindXid,
-                            rpcBranchType != null ? rpcBranchType : 
BranchType.AT,
-                            previousBranchType);
-                    if (unbindXid != null) {
-                        RootContext.bind(unbindXid);
-                        LOGGER.warn("bind xid [{}] back to RootContext", 
unbindXid);
-                        if (BranchType.TCC == previousBranchType) {
-                            RootContext.bindBranchType(BranchType.TCC);
-                            LOGGER.warn("bind branchType [{}] back to 
RootContext", previousBranchType);
-                        }
-                    }
-                }
+        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);
             }
-            
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 void clearServerContextAttachments() {
+        RpcContext.getServerContext().removeAttachment(RootContext.KEY_XID);
+        
RpcContext.getServerContext().removeAttachment(RootContext.KEY_BRANCH_TYPE);
+    }
+
     /**
      * get rpc xid
      *
@@ -105,4 +151,31 @@ 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/integration/dubbo-alibaba/src/test/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionProviderFilterTest.java
 
b/integration/dubbo-alibaba/src/test/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionProviderFilterTest.java
new file mode 100644
index 0000000000..067f3a2649
--- /dev/null
+++ 
b/integration/dubbo-alibaba/src/test/java/org/apache/seata/integration/dubbo/alibaba/AlibabaDubboTransactionProviderFilterTest.java
@@ -0,0 +1,277 @@
+/*
+ * 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.dubbo.alibaba;
+
+import com.alibaba.dubbo.rpc.Invocation;
+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.core.constants.DubboConstants;
+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.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class AlibabaDubboTransactionProviderFilterTest {
+    private AlibabaDubboTransactionProviderFilter filter;
+    private Invoker invoker;
+    private Invocation invocation;
+    private RpcContext rpcContext;
+    private RpcContext rpcServerContext;
+    private MockedStatic<RpcContext> rpcContextMock;
+
+    @BeforeEach
+    void setUp() {
+        filter = new AlibabaDubboTransactionProviderFilter();
+        invoker = mock(Invoker.class);
+        invocation = mock(Invocation.class);
+
+        // Mock RpcContext
+        rpcContextMock = mockStatic(RpcContext.class);
+        rpcContext = mock(RpcContext.class);
+        rpcServerContext = mock(RpcContext.class);
+
+        rpcContextMock.when(RpcContext::getContext).thenReturn(rpcContext);
+        
rpcContextMock.when(RpcContext::getServerContext).thenReturn(rpcServerContext);
+    }
+
+    @AfterEach
+    void tearDown() {
+        // Clear RootContext
+        RootContext.unbind();
+        RootContext.unbindBranchType();
+
+        if (rpcContextMock != null) {
+            rpcContextMock.close();
+        }
+    }
+
+    @Test
+    void testInvokeWhenNotAlibabaDubbo() {
+        // Arrange
+        Result expectedResult = mock(Result.class);
+        when(invoker.invoke(invocation)).thenReturn(expectedResult);
+
+        // Test when DubboConstants.ALIBABADUBBO is false
+        // We need to use reflection to change the value of the static final 
field
+        try {
+            // Use a different approach - test the actual behavior by checking 
if the filter returns early
+            // Create a new filter and directly test its behavior
+            AlibabaDubboTransactionProviderFilter filterWithFalse = new 
AlibabaDubboTransactionProviderFilter() {
+                // Override the invoke method to simulate ALIBABADUBBO = false
+                @Override
+                public Result invoke(Invoker<?> invoker, Invocation 
invocation) throws RpcException {
+                    // Simulate ALIBABADUBBO = false
+                    try {
+                        java.lang.reflect.Field field = 
DubboConstants.class.getDeclaredField("ALIBABADUBBO");
+                        field.setAccessible(true);
+                        field.setBoolean(null, false);
+                    } catch (Exception e) {
+                        // Ignore
+                    }
+                    return super.invoke(invoker, invocation);
+                }
+            };
+
+            // Act
+            Result result = filterWithFalse.invoke(invoker, invocation);
+
+            // Assert
+            assertEquals(expectedResult, result);
+            verify(invoker).invoke(invocation);
+        } finally {
+            // Restore the original value
+            try {
+                java.lang.reflect.Field field = 
DubboConstants.class.getDeclaredField("ALIBABADUBBO");
+                field.setAccessible(true);
+                field.setBoolean(null, true);
+            } catch (Exception e) {
+                // Ignore
+            }
+        }
+    }
+
+    @Test
+    void testInvokeWhenXidIsNull() {
+        // Arrange
+        Result expectedResult = mock(Result.class);
+        when(invoker.invoke(invocation)).thenReturn(expectedResult);
+        when(rpcContext.getAttachment(RootContext.KEY_XID)).thenReturn(null);
+        
when(rpcContext.getAttachment(RootContext.KEY_XID.toLowerCase())).thenReturn(null);
+
+        // Act
+        Result result = filter.invoke(invoker, invocation);
+
+        // Assert
+        assertEquals(expectedResult, result);
+        verify(invoker).invoke(invocation);
+        verify(rpcContext).getAttachment(RootContext.KEY_XID);
+        verify(rpcContext).getAttachment(RootContext.KEY_XID.toLowerCase());
+        assertNull(RootContext.getXID());
+    }
+
+    @Test
+    void testInvokeWhenXidIsPresent() {
+        // Arrange
+        String xid = "test-xid-123";
+        Result expectedResult = mock(Result.class);
+        when(invoker.invoke(invocation)).thenReturn(expectedResult);
+        when(rpcContext.getAttachment(RootContext.KEY_XID)).thenReturn(xid);
+        
when(rpcServerContext.getAttachment(RootContext.KEY_BRANCH_TYPE)).thenReturn(null);
+
+        // Act
+        Result result = filter.invoke(invoker, invocation);
+
+        // Assert
+        assertEquals(expectedResult, result);
+        verify(invoker).invoke(invocation);
+        // After execution, context should be cleared
+        assertNull(RootContext.getXID());
+    }
+
+    @Test
+    void testInvokeWhenXidAndTccBranchTypeArePresent() {
+        // Arrange
+        String xid = "test-xid-123";
+        String branchType = BranchType.TCC.name();
+        Result expectedResult = mock(Result.class);
+        when(invoker.invoke(invocation)).thenReturn(expectedResult);
+        when(rpcContext.getAttachment(RootContext.KEY_XID)).thenReturn(xid);
+        
when(rpcServerContext.getAttachment(RootContext.KEY_BRANCH_TYPE)).thenReturn(branchType);
+
+        // Act
+        Result result = filter.invoke(invoker, invocation);
+
+        // Assert
+        assertEquals(expectedResult, result);
+        verify(invoker).invoke(invocation);
+        // After execution, context should be cleared
+        assertNull(RootContext.getXID());
+        assertNull(RootContext.getBranchType());
+    }
+
+    @Test
+    void testInvokeWhenXidAndAtBranchTypeArePresent() {
+        // Arrange
+        String xid = "test-xid-123";
+        String branchType = BranchType.AT.name();
+        Result expectedResult = mock(Result.class);
+        when(invoker.invoke(invocation)).thenReturn(expectedResult);
+        when(rpcContext.getAttachment(RootContext.KEY_XID)).thenReturn(xid);
+        
when(rpcServerContext.getAttachment(RootContext.KEY_BRANCH_TYPE)).thenReturn(branchType);
+
+        // Act
+        Result result = filter.invoke(invoker, invocation);
+
+        // Assert
+        assertEquals(expectedResult, result);
+        verify(invoker).invoke(invocation);
+        // After execution, context should be cleared
+        assertNull(RootContext.getXID());
+        assertNull(RootContext.getBranchType());
+    }
+
+    @Test
+    void testInvokeWhenXidChangedDuringExecution() {
+        // Arrange
+        String originalXid = "original-xid-123";
+        String changedXid = "changed-xid-456";
+        Result expectedResult = mock(Result.class);
+
+        // Mock the invocation to simulate XID change during execution
+        when(invoker.invoke(invocation)).thenAnswer(invocationOnMock -> {
+            // Simulate XID change during invocation
+            RootContext.bind(changedXid);
+            return expectedResult;
+        });
+
+        
when(rpcContext.getAttachment(RootContext.KEY_XID)).thenReturn(originalXid);
+        
when(rpcContext.getAttachment(RootContext.KEY_BRANCH_TYPE)).thenReturn(null);
+
+        // Act
+        Result result = filter.invoke(invoker, invocation);
+
+        // Assert
+        assertEquals(expectedResult, result);
+        verify(invoker).invoke(invocation);
+        // According to the source code, when XID changes during execution,
+        // the filter should restore the changed XID (not the original one)
+        assertEquals(changedXid, RootContext.getXID());
+    }
+
+    @Test
+    void testGetRpcXidWhenXidExists() {
+        // Arrange
+        String xid = "test-xid-123";
+        when(rpcContext.getAttachment(RootContext.KEY_XID)).thenReturn(xid);
+
+        // Act - Using reflection to test private method
+        String result = invokePrivateMethod("getRpcXid");
+
+        // Assert
+        assertEquals(xid, result);
+    }
+
+    @Test
+    void testGetRpcXidWhenXidIsNullButLowerCaseExists() {
+        // Arrange
+        String xid = "test-xid-123";
+        when(rpcContext.getAttachment(RootContext.KEY_XID)).thenReturn(null);
+        
when(rpcContext.getAttachment(RootContext.KEY_XID.toLowerCase())).thenReturn(xid);
+
+        // Act - Using reflection to test private method
+        String result = invokePrivateMethod("getRpcXid");
+
+        // Assert
+        assertEquals(xid, result);
+    }
+
+    @Test
+    void testGetRpcXidWhenBothXidAreNull() {
+        // Arrange
+        when(rpcContext.getAttachment(RootContext.KEY_XID)).thenReturn(null);
+        
when(rpcContext.getAttachment(RootContext.KEY_XID.toLowerCase())).thenReturn(null);
+
+        // Act - Using reflection to test private method
+        String result = invokePrivateMethod("getRpcXid");
+
+        // Assert
+        assertNull(result);
+    }
+
+    // Helper method to test private methods using reflection
+    private String invokePrivateMethod(String methodName) {
+        try {
+            java.lang.reflect.Method method = 
AlibabaDubboTransactionProviderFilter.class.getDeclaredMethod(methodName);
+            method.setAccessible(true);
+            return (String) method.invoke(filter);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to invoke private method: " + 
methodName, e);
+        }
+    }
+}
diff --git 
a/integration/hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionConsumerFilter.java
 
b/integration/hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionConsumerFilter.java
index 9e1df9837e..418b5a0865 100644
--- 
a/integration/hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionConsumerFilter.java
+++ 
b/integration/hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionConsumerFilter.java
@@ -36,24 +36,65 @@ public class HsfTransactionConsumerFilter implements 
ClientFilter {
 
     @Override
     public ListenableFuture<RPCResult> invoke(InvocationHandler nextHandler, 
Invocation invocation) throws Throwable {
-        String xid = RootContext.getXID();
-        BranchType branchType = RootContext.getBranchType();
+        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[{}]", xid, branchType);
-        }
-        if (xid != null) {
-            RPCContext.getClientContext().putAttachment(RootContext.KEY_XID, 
xid);
-            
RPCContext.getClientContext().putAttachment(RootContext.KEY_BRANCH_TYPE, 
branchType.name());
+            LOGGER.debug("xid in RootContext[{}], branchType in 
RootContext[{}]", context.xid, context.branchType);
         }
+
         try {
+            propagateTransactionContext(context);
             return nextHandler.invoke(invocation);
         } finally {
-            
RPCContext.getClientContext().removeAttachment(RootContext.KEY_XID);
-            
RPCContext.getClientContext().removeAttachment(RootContext.KEY_BRANCH_TYPE);
+            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);
+            }
+        }
+    }
+
+    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) {}
+    public void onResponse(Invocation invocation, RPCResult rpcResult) {
+        // No operation needed
+    }
+
+    private static class TransactionContext {
+        /**
+         * The Xid.
+         */
+        String xid;
+        /**
+         * The Branch type.
+         */
+        BranchType branchType;
+    }
 }
diff --git 
a/integration/hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionProviderFilter.java
 
b/integration/hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionProviderFilter.java
index e60460877e..b87d59a475 100644
--- 
a/integration/hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionProviderFilter.java
+++ 
b/integration/hsf/src/main/java/org/apache/seata/integration/hsf/HsfTransactionProviderFilter.java
@@ -37,57 +37,150 @@ public class HsfTransactionProviderFilter implements 
ServerFilter {
 
     @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();
 
-        Object rpcXid = 
RPCContext.getServerContext().getAttachment(RootContext.KEY_XID);
-        Object rpcBranchType = 
RPCContext.getServerContext().getAttachment(RootContext.KEY_BRANCH_TYPE);
         if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug("xid in RpcContext[{}], branchType in 
RpcContext[{}]", rpcXid, rpcBranchType);
+            LOGGER.debug(
+                    "xid in RpcContext[{}], branchType in RpcContext[{}]", 
rpcContext.rpcXid, rpcContext.rpcBranchType);
         }
-        boolean bind = false;
-        if (rpcXid != null) {
-            RootContext.bind(rpcXid.toString());
-            if (StringUtils.equals(BranchType.TCC.name(), 
rpcBranchType.toString())) {
+
+        TransactionContextBinding binding = bindTransactionContext(rpcContext);
+
+        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;
             }
-            bind = true;
+
             if (LOGGER.isDebugEnabled()) {
-                LOGGER.debug("bind xid [{}] branchType [{}] to RootContext", 
rpcXid, rpcBranchType);
+                LOGGER.debug(
+                        "bind xid [{}] branchType [{}] to RootContext", 
rpcContext.rpcXid, rpcContext.rpcBranchType);
             }
         }
-        try {
-            return nextHandler.invoke(invocation);
-        } 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 (!rpcXid.toString().equalsIgnoreCase(unbindXid)) {
-                    LOGGER.warn(
-                            "xid in change during RPC from {} to {},branchType 
from {} to {}",
-                            rpcXid,
-                            unbindXid,
-                            rpcBranchType != null ? rpcBranchType : "AT",
-                            previousBranchType);
-                    if (unbindXid != null) {
-                        RootContext.bind(unbindXid);
-                        LOGGER.warn("bind xid [{}] back to RootContext", 
unbindXid);
-                        if (BranchType.TCC == previousBranchType) {
-                            RootContext.bindBranchType(BranchType.TCC);
-                            LOGGER.warn("bind branchType [{}] back to 
RootContext", previousBranchType);
-                        }
-                    }
-                }
+
+        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);
             }
-            
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 void clearServerContextAttachments() {
+        RPCContext.getServerContext().removeAttachment(RootContext.KEY_XID);
+        
RPCContext.getServerContext().removeAttachment(RootContext.KEY_BRANCH_TYPE);
+    }
+
     @Override
-    public void onResponse(Invocation invocation, RPCResult rpcResult) {}
+    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;
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to