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

albumenj pushed a commit to branch 3.2
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.2 by this push:
     new ee9d01a6e0 feat: split rpcContext (#10798)
ee9d01a6e0 is described below

commit ee9d01a6e0712b7024a89b4767a6ea3f7243d999
Author: aamingaa <[email protected]>
AuthorDate: Thu Nov 10 20:56:26 2022 +0800

    feat: split rpcContext (#10798)
---
 .../filter/support/ConsumerContextFilter.java      |  10 +-
 .../java/com/alibaba/dubbo/rpc/RpcContext.java     |  15 +-
 .../dubbo/rpc/PenetrateAttachmentSelector.java     |   3 +-
 .../main/java/org/apache/dubbo/rpc/RpcContext.java |  55 ++++-
 .../dubbo/rpc/RpcServerContextAttachment.java      | 236 +++++++++++++++++++++
 .../org/apache/dubbo/rpc/filter/ContextFilter.java |  29 ++-
 .../dubbo/rpc/PenetrateAttachmentSelectorTest.java |  16 +-
 .../java/org/apache/dubbo/rpc/RpcContextTest.java  | 134 ++++++++++++
 .../apache/dubbo/rpc/filter/ContextFilterTest.java |   3 +-
 .../support/PenetrateAttachmentSelectorMock.java   |  11 +-
 .../tri/call/AbstractServerCallListener.java       |   4 +-
 11 files changed, 489 insertions(+), 27 deletions(-)

diff --git 
a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ConsumerContextFilter.java
 
b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ConsumerContextFilter.java
index e793727d92..fe78983f58 100644
--- 
a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ConsumerContextFilter.java
+++ 
b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ConsumerContextFilter.java
@@ -75,7 +75,7 @@ public class ConsumerContextFilter implements ClusterFilter, 
ClusterFilter.Liste
 
             if (CollectionUtils.isNotEmpty(supportedSelectors)) {
                 for (PenetrateAttachmentSelector supportedSelector : 
supportedSelectors) {
-                    Map<String, Object> selected = supportedSelector.select();
+                    Map<String, Object> selected = 
supportedSelector.select(invocation, RpcContext.getClientAttachment(), 
RpcContext.getServerAttachment());
                     if (CollectionUtils.isNotEmptyMap(selected)) {
                         ((RpcInvocation) 
invocation).addObjectAttachments(selected);
                     }
@@ -83,7 +83,6 @@ public class ConsumerContextFilter implements ClusterFilter, 
ClusterFilter.Liste
             } else {
                 ((RpcInvocation) 
invocation).addObjectAttachments(RpcContext.getServerAttachment().getObjectAttachments());
             }
-
             Map<String, Object> contextAttachments = 
RpcContext.getClientAttachment().getObjectAttachments();
             if (CollectionUtils.isNotEmptyMap(contextAttachments)) {
                 /**
@@ -105,8 +104,7 @@ public class ConsumerContextFilter implements 
ClusterFilter, ClusterFilter.Liste
                             + invocation.getMethodName() + ", terminate 
directly."), invocation);
                 }
             }
-
-            RpcContext.removeServerContext();
+            RpcContext.removeClientResponseContext();
             return invoker.invoke(invocation);
         } finally {
             RpcContext.restoreServiceContext(originServiceContext);
@@ -116,8 +114,8 @@ public class ConsumerContextFilter implements 
ClusterFilter, ClusterFilter.Liste
     @Override
     public void onResponse(Result appResponse, Invoker<?> invoker, Invocation 
invocation) {
         // pass attachments to result
-        
RpcContext.getServerContext().setObjectAttachments(appResponse.getObjectAttachments());
-
+        Map<String, Object> map = appResponse.getObjectAttachments();
+        RpcContext.getClientResponseContext().setObjectAttachments(map);
         removeContext(invocation);
     }
 
diff --git 
a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java 
b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
index 08cc64760a..5d9d1a092d 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
+++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
@@ -47,11 +47,24 @@ public class RpcContext {
     public static RpcContext getServerContext() {
         return new 
RpcContext(org.apache.dubbo.rpc.RpcContext.getServerContext());
     }
+    public static RpcContext getClientResponseContext() {
+        return new 
RpcContext(org.apache.dubbo.rpc.RpcContext.getClientResponseContext());
+    }
+
+    public static RpcContext getServerResponseContext() {
+        return new 
RpcContext(org.apache.dubbo.rpc.RpcContext.getServerResponseContext());
+    }
+    public static void removeClientResponseContext() {
+        org.apache.dubbo.rpc.RpcContext.removeClientResponseContext();
+    }
+
+    public static void removeServerResponseContext() {
+        org.apache.dubbo.rpc.RpcContext.removeServerResponseContext();
+    }
 
     public static void removeServerContext() {
         org.apache.dubbo.rpc.RpcContext.removeServerContext();
     }
-
     public static void removeContext() {
         org.apache.dubbo.rpc.RpcContext.removeContext();
     }
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/PenetrateAttachmentSelector.java
 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/PenetrateAttachmentSelector.java
index aee89a6ad4..13bad8aa2e 100644
--- 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/PenetrateAttachmentSelector.java
+++ 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/PenetrateAttachmentSelector.java
@@ -29,6 +29,7 @@ public interface PenetrateAttachmentSelector {
      *
      * @return attachment pass to next hop
      */
-    Map<String, Object> select();
+    Map<String, Object> select(Invocation invocation, RpcContextAttachment 
clientAttachment, RpcContextAttachment serverAttachment);
+    Map<String, Object> selectReverse(Invocation invocation, 
RpcContextAttachment clientResponseContext, RpcContextAttachment 
serverResponseContext);
 
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcContext.java 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcContext.java
index cfe7f9a821..33a302e03a 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcContext.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcContext.java
@@ -56,7 +56,15 @@ public class RpcContext {
     /**
      * use internal thread local to improve performance
      */
-    private static final InternalThreadLocal<RpcContextAttachment> 
SERVER_LOCAL = new InternalThreadLocal<RpcContextAttachment>() {
+
+    private static final InternalThreadLocal<RpcContextAttachment> 
CLIENT_RESPONSE_LOCAL = new InternalThreadLocal<RpcContextAttachment>() {
+        @Override
+        protected RpcContextAttachment initialValue() {
+            return new RpcContextAttachment();
+        }
+    };
+
+    private static final InternalThreadLocal<RpcContextAttachment> 
SERVER_RESPONSE_LOCAL = new InternalThreadLocal<RpcContextAttachment>() {
         @Override
         protected RpcContextAttachment initialValue() {
             return new RpcContextAttachment();
@@ -118,7 +126,7 @@ public class RpcContext {
      * @return server context
      */
     public static RpcContextAttachment getServerContext() {
-        return SERVER_LOCAL.get();
+        return new RpcServerContextAttachment();
     }
 
     /**
@@ -126,8 +134,20 @@ public class RpcContext {
      *
      * @see org.apache.dubbo.rpc.filter.ContextFilter
      */
-    public static void removeServerContext() {
-        SERVER_LOCAL.remove();
+    public static RpcContextAttachment getClientResponseContext() {
+        return CLIENT_RESPONSE_LOCAL.get();
+    }
+
+    public static RpcContextAttachment getServerResponseContext() {
+        return SERVER_RESPONSE_LOCAL.get();
+    }
+
+    public static void removeClientResponseContext() {
+        CLIENT_RESPONSE_LOCAL.remove();
+    }
+
+    public static void removeServerResponseContext() {
+        SERVER_RESPONSE_LOCAL.remove();
     }
 
     /**
@@ -158,6 +178,13 @@ public class RpcContext {
         return SERVER_ATTACHMENT.get();
     }
 
+    public static void removeServerContext() {
+        RpcContextAttachment rpcContextAttachment = 
RpcContext.getServerContext();
+        for(String key : rpcContextAttachment.attachments.keySet()) {
+            rpcContextAttachment.remove(key);
+        }
+    }
+
     public boolean canRemove() {
         return remove;
     }
@@ -206,7 +233,8 @@ public class RpcContext {
         if (SERVER_ATTACHMENT.get().canRemove()) {
             SERVER_ATTACHMENT.remove();
         }
-        SERVER_LOCAL.remove();
+        CLIENT_RESPONSE_LOCAL.remove();
+        SERVER_RESPONSE_LOCAL.remove();
         SERVICE_CONTEXT.remove();
         CANCELLATION_CONTEXT.remove();
     }
@@ -828,13 +856,15 @@ public class RpcContext {
         private final RpcServiceContext serviceContext;
         private final RpcContextAttachment clientAttachment;
         private final RpcContextAttachment serverAttachment;
-        private final RpcContextAttachment serverLocal;
+        private final RpcContextAttachment clientResponseLocal;
+        private final RpcContextAttachment serverResponseLocal;
 
         public RestoreContext() {
             serviceContext = getServiceContext().copyOf(false);
             clientAttachment = getClientAttachment().copyOf(false);
             serverAttachment = getServerAttachment().copyOf(false);
-            serverLocal = getServerContext().copyOf(false);
+            clientResponseLocal = getClientResponseContext().copyOf(false);
+            serverResponseLocal = getServerResponseContext().copyOf(false);
         }
 
         public void restore() {
@@ -853,10 +883,15 @@ public class RpcContext {
             } else {
                 removeServerAttachment();
             }
-            if (serverLocal != null) {
-                SERVER_LOCAL.set(serverLocal);
+            if (clientResponseLocal != null) {
+                CLIENT_RESPONSE_LOCAL.set(clientResponseLocal);
+            } else {
+                removeClientResponseContext();
+            }
+            if (serverResponseLocal != null) {
+                SERVER_RESPONSE_LOCAL.set(serverResponseLocal);
             } else {
-                removeServerContext();
+                removeServerResponseContext();
             }
         }
     }
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcServerContextAttachment.java
 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcServerContextAttachment.java
new file mode 100644
index 0000000000..c1bcdd79e6
--- /dev/null
+++ 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcServerContextAttachment.java
@@ -0,0 +1,236 @@
+/*
+ * 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.dubbo.rpc;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class RpcServerContextAttachment extends RpcContextAttachment {
+    @Override
+    public RpcContextAttachment copyOf(boolean needCopy) {
+        throw new RuntimeException("copyOf internal method, should not be 
invoke");
+    }
+
+    @Override
+    protected boolean isValid() {
+        throw new RuntimeException("isValid of is internal method, should not 
be invoke");
+    }
+
+    @Override
+    public RpcContextAttachment setObjectAttachment(String key, Object value) {
+        RpcContext.getServerResponseContext().setObjectAttachment(key, value);
+        return this;
+    }
+
+    @Override
+    protected void setAsyncContext(AsyncContext asyncContext) {
+        RpcContext.getServerResponseContext().setAsyncContext(asyncContext);
+    }
+
+    @Override
+    public boolean isAsyncStarted() {
+        return RpcContext.getServerResponseContext().isAsyncStarted();
+    }
+
+    @Override
+    public boolean stopAsync() {
+        return RpcContext.getServerResponseContext().stopAsync();
+    }
+
+    @Override
+    public AsyncContext getAsyncContext() {
+        return RpcContext.getServerResponseContext().getAsyncContext();
+    }
+
+    @Override
+    public String getAttachment(String key) {
+        Object attachment = getObjectAttachment(key);
+        if (attachment instanceof String) {
+            return (String) attachment;
+        }
+        return null;
+    }
+
+    @Override
+    public Object getObjectAttachment(String key) {
+        Object fromServerResponse = 
RpcContext.getServerResponseContext().getObjectAttachment(key);
+        if (fromServerResponse == null) {
+            fromServerResponse = 
RpcContext.getClientResponseContext().getObjectAttachment(key);
+        }
+        return fromServerResponse;
+    }
+
+    @Override
+    public RpcContextAttachment setAttachment(String key, String value) {
+        return RpcContext.getServerResponseContext().setAttachment(key, value);
+    }
+
+    @Override
+    public RpcContextAttachment setAttachment(String key, Object value) {
+        return RpcContext.getServerResponseContext().setAttachment(key, value);
+    }
+
+    @Override
+    public RpcContextAttachment removeAttachment(String key) {
+        RpcContext.getServerResponseContext().removeAttachment(key);
+        RpcContext.getClientResponseContext().removeAttachment(key);
+        return this;
+    }
+
+    @Override
+    public Map<String, String> getAttachments() {
+        return new AttachmentsAdapter.ObjectToStringMap(new 
ObjectAttachmentMap(this));
+    }
+
+    @Override
+    public Map<String, Object> getObjectAttachments() {
+        return new ObjectAttachmentMap(this);
+    }
+
+    @Override
+    public RpcContextAttachment setAttachments(Map<String, String> attachment) 
{
+        RpcContext.getServerResponseContext().setAttachments(attachment);
+        RpcContext.getClientResponseContext().clearAttachments();
+        return this;
+    }
+
+    @Override
+    public RpcContextAttachment setObjectAttachments(Map<String, Object> 
attachment) {
+        RpcContext.getServerResponseContext().setObjectAttachments(attachment);
+        RpcContext.getClientResponseContext().clearAttachments();
+        return this;
+    }
+
+    @Override
+    public void clearAttachments() {
+        RpcContext.getServerResponseContext().clearAttachments();
+        RpcContext.getClientResponseContext().clearAttachments();
+    }
+
+    @Override
+    public Map<String, Object> get() {
+        return getObjectAttachments();
+    }
+
+    @Override
+    public RpcContextAttachment set(String key, Object value) {
+        return setAttachment(key, value);
+    }
+
+    @Override
+    public RpcContextAttachment remove(String key) {
+        return removeAttachment(key);
+    }
+
+    @Override
+    public Object get(String key) {
+        return getAttachment(key);
+    }
+
+    static class ObjectAttachmentMap implements Map<String, Object> {
+        private final RpcServerContextAttachment adapter;
+
+        public ObjectAttachmentMap(RpcServerContextAttachment adapter) {
+            this.adapter = adapter;
+        }
+
+        private Map<String, Object> getAttachments() {
+            Map<String, Object> clientResponse = 
RpcContext.getClientResponseContext().getObjectAttachments();
+            Map<String, Object> serverResponse = 
RpcContext.getServerResponseContext().getObjectAttachments();
+            Map<String, Object> result = new HashMap<>((int) 
(clientResponse.size() + serverResponse.size() / 0.75) + 1);
+            result.putAll(clientResponse);
+            result.putAll(serverResponse);
+            return result;
+        }
+
+        @Override
+        public int size() {
+            return getAttachments().size();
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return 
RpcContext.getClientResponseContext().getObjectAttachments().isEmpty() &&
+                
RpcContext.getServerResponseContext().getObjectAttachments().isEmpty();
+        }
+
+        @Override
+        public boolean containsKey(Object key) {
+            return 
RpcContext.getClientResponseContext().getObjectAttachments().containsKey(key) ||
+                
RpcContext.getServerResponseContext().getObjectAttachments().containsKey(key);
+        }
+
+        @Override
+        public boolean containsValue(Object value) {
+            return 
RpcContext.getClientResponseContext().getObjectAttachments().containsValue(value)
 ||
+                
RpcContext.getServerResponseContext().getObjectAttachments().containsValue(value);
+        }
+
+        @Override
+        public Object get(Object key) {
+            if (key instanceof String) {
+                return adapter.getObjectAttachment((String) key);
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        public Object put(String key, Object value) {
+            return adapter.setObjectAttachment(key, value);
+        }
+
+        @Override
+        public Object remove(Object key) {
+            if (key instanceof String) {
+                return adapter.removeAttachment((String) key);
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        public void putAll(Map<? extends String, ?> m) {
+            for (Entry<? extends String, ?> entry : m.entrySet()) {
+                adapter.setObjectAttachment(entry.getKey(), entry.getValue());
+            }
+        }
+
+        @Override
+        public void clear() {
+            adapter.clearAttachments();
+        }
+
+        @Override
+        public Set<String> keySet() {
+            return getAttachments().keySet();
+        }
+
+        @Override
+        public Collection<Object> values() {
+            return getAttachments().values();
+        }
+
+        @Override
+        public Set<Entry<String, Object>> entrySet() {
+            return getAttachments().entrySet();
+        }
+    }
+}
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
index deb7d529a8..6cfe9936a6 100644
--- 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
+++ 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
@@ -16,6 +16,11 @@
  */
 package org.apache.dubbo.rpc.filter;
 
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.support.RpcUtils;
+import org.apache.dubbo.rpc.TimeoutCountDown;
 import org.apache.dubbo.common.extension.Activate;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.rpc.Filter;
@@ -25,8 +30,7 @@ import org.apache.dubbo.rpc.Result;
 import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.TimeoutCountDown;
-import org.apache.dubbo.rpc.support.RpcUtils;
+import org.apache.dubbo.rpc.PenetrateAttachmentSelector;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -58,6 +62,12 @@ import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
  */
 @Activate(group = PROVIDER, order = Integer.MIN_VALUE)
 public class ContextFilter implements Filter, Filter.Listener {
+    private Set<PenetrateAttachmentSelector> supportedSelectors;
+
+    public ContextFilter(ApplicationModel applicationModel) {
+        ExtensionLoader<PenetrateAttachmentSelector> selectorExtensionLoader = 
applicationModel.getExtensionLoader(PenetrateAttachmentSelector.class);
+        supportedSelectors = 
selectorExtensionLoader.getSupportedExtensionInstances();
+    }
 
     private static final Set<String> UNLOADING_KEYS;
 
@@ -142,7 +152,17 @@ public class ContextFilter implements Filter, 
Filter.Listener {
     @Override
     public void onResponse(Result appResponse, Invoker<?> invoker, Invocation 
invocation) {
         // pass attachments to result
-        
appResponse.addObjectAttachments(RpcContext.getServerContext().getObjectAttachments());
+        if (CollectionUtils.isNotEmpty(supportedSelectors)) {
+            for (PenetrateAttachmentSelector supportedSelector : 
supportedSelectors) {
+                Map<String, Object> selected = 
supportedSelector.selectReverse(invocation, 
RpcContext.getClientResponseContext(), RpcContext.getServerResponseContext());
+                if (CollectionUtils.isNotEmptyMap(selected)) {
+                    appResponse.addObjectAttachments(selected);
+                }
+            }
+        } else {
+            
appResponse.addObjectAttachments(RpcContext.getClientResponseContext().getObjectAttachments());
+        }
+        
appResponse.addObjectAttachments(RpcContext.getServerResponseContext().getObjectAttachments());
         removeContext();
     }
 
@@ -155,6 +175,7 @@ public class ContextFilter implements Filter, 
Filter.Listener {
         RpcContext.removeServerAttachment();
         RpcContext.removeClientAttachment();
         RpcContext.removeServiceContext();
-        RpcContext.removeServerContext();
+        RpcContext.removeClientResponseContext();
+        RpcContext.removeServerResponseContext();
     }
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/PenetrateAttachmentSelectorTest.java
 
b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/PenetrateAttachmentSelectorTest.java
index 6cd94a298e..5490204bf4 100644
--- 
a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/PenetrateAttachmentSelectorTest.java
+++ 
b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/PenetrateAttachmentSelectorTest.java
@@ -39,10 +39,24 @@ public class PenetrateAttachmentSelectorTest {
         Map<String, Object> allSelected = new HashMap<>();
         if (CollectionUtils.isNotEmpty(supportedSelectors)) {
             for (String supportedSelector : supportedSelectors) {
-                Map<String, Object> selected = 
selectorExtensionLoader.getExtension(supportedSelector).select();
+                Map<String, Object> selected = 
selectorExtensionLoader.getExtension(supportedSelector).select(null, null, 
null);
                 allSelected.putAll(selected);
             }
         }
         Assertions.assertEquals(allSelected.get("testKey"), "testVal");
     }
+
+    @Test
+    public void testSelectReverse() {
+        ExtensionLoader<PenetrateAttachmentSelector> selectorExtensionLoader = 
ApplicationModel.defaultModel().getExtensionLoader(PenetrateAttachmentSelector.class);
+        Set<String> supportedSelectors = 
selectorExtensionLoader.getSupportedExtensions();
+        Map<String, Object> allSelected = new HashMap<>();
+        if (CollectionUtils.isNotEmpty(supportedSelectors)) {
+            for (String supportedSelector : supportedSelectors) {
+                Map<String, Object> selected = 
selectorExtensionLoader.getExtension(supportedSelector).selectReverse(null, 
null, null);
+                allSelected.putAll(selected);
+            }
+        }
+        Assertions.assertEquals(allSelected.get("reverseKey"), "reverseVal");
+    }
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/RpcContextTest.java
 
b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/RpcContextTest.java
index a7dbd8f293..0d2d22d0d0 100644
--- 
a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/RpcContextTest.java
+++ 
b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/RpcContextTest.java
@@ -18,11 +18,15 @@ package org.apache.dubbo.rpc;
 
 import org.apache.dubbo.common.URL;
 
+import org.apache.dubbo.common.url.component.URLParam;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import java.io.InputStream;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 
@@ -202,9 +206,139 @@ public class RpcContextTest {
         rpcContext.setObjectAttachments(map);
         Assertions.assertEquals(map, rpcContext.getObjectAttachments());
     }
+    @Test
+    public void say() {
+        final String key = "user-attachment";
+        final String value = "attachment-value";
+        RpcContext.getServerContext().setObjectAttachment(key, value);
+        final String returned = (String) 
RpcContext.getServerContext().getObjectAttachment(key);
+        System.out.println(returned);
+        RpcContext.getServerContext().remove(key);
+    }
 
     @Test
     public void testRestore() {
 
     }
+
+    @Test
+    public void testRpcServerContextAttachment() {
+        RpcContextAttachment attachment = RpcContext.getServerContext();
+        attachment.setAttachment("key_1","value_1");
+        attachment.setAttachment("key_2","value_2");
+        Assertions.assertEquals("value_1", attachment.getAttachment("key_1"));
+        Assertions.assertEquals(null, attachment.getAttachment("aaa"));
+        attachment.removeAttachment("key_1");
+        Assertions.assertEquals(null, attachment.getAttachment("key_1"));
+        Assertions.assertEquals("value_2", attachment.getAttachment("key_2"));
+        Object obj = new Object();
+        attachment.setObjectAttachment("key_3", obj);
+        Assertions.assertEquals(obj, attachment.getObjectAttachment("key_3"));
+        attachment.removeAttachment("key_3");
+        Assertions.assertEquals(null, attachment.getObjectAttachment("key_3"));
+
+        Assertions.assertThrows(RuntimeException.class, () -> 
attachment.copyOf(true));
+        Assertions.assertThrows(RuntimeException.class, attachment::isValid);
+
+        Map<String, String> map = new HashMap<>();
+        map.put("key_4", "value_4");
+        map.put("key_5", "value_5");
+        attachment.setAttachments(map);
+        Assertions.assertEquals(attachment.getAttachments(), 
attachment.getObjectAttachments());
+        Assertions.assertEquals(attachment.getAttachments(), attachment.get());
+        Map<String, String> map1 = attachment.getAttachments();
+        Assertions.assertEquals("value_4", map1.get("key_4"));
+        Assertions.assertEquals("value_5", map1.get("key_5"));
+        attachment.clearAttachments();
+        Assertions.assertEquals(attachment, 
attachment.removeAttachment("key_4"));
+        Assertions.assertEquals(attachment, 
attachment.removeAttachment("key_5"));
+
+        attachment.set("key_6", "value_6");
+        Assertions.assertEquals("value_6", attachment.get("key_6"));
+        attachment.clearAttachments();
+
+        Map<String, Object> objectMap = new HashMap<>();
+        objectMap.put("key_7", "value_7");
+        objectMap.put("key_8", "value_8");
+        attachment.setObjectAttachments(objectMap);
+        Map<String, String> objectMap1 = attachment.getAttachments();
+        Assertions.assertEquals("value_7", objectMap1.get("key_7"));
+        Assertions.assertEquals("value_8", objectMap1.get("key_8"));
+        attachment.clearAttachments();
+
+    }
+
+    @Test
+    public void testRpcServerContextClearAttachment() {
+        RpcServerContextAttachment attachment = new 
RpcServerContextAttachment();
+        attachment.setAttachment("key_1","value_1");
+        attachment.setAttachment("key_2","value_2");
+        attachment.setAttachment("key_3","value_3");
+        attachment.clearAttachments();
+        Assertions.assertEquals(null, attachment.getAttachment("key_1"));
+        Assertions.assertEquals(null, attachment.getAttachment("key_2"));
+        Assertions.assertEquals(null, attachment.getAttachment("key_3"));
+
+        attachment.setObjectAttachment("key_1","value_1");
+        attachment.setObjectAttachment("key_2","value_2");
+        attachment.setObjectAttachment("key_3","value_3");
+        attachment.clearAttachments();
+        Assertions.assertEquals(null, attachment.getAttachment("key_1"));
+        Assertions.assertEquals(null, attachment.getAttachment("key_2"));
+        Assertions.assertEquals(null, attachment.getAttachment("key_3"));
+    }
+
+    @Test
+    public void testAsyncContext() {
+        RpcServerContextAttachment attachment = new 
RpcServerContextAttachment();
+        AsyncContext asyncContext = new AsyncContextImpl();
+        attachment.setAsyncContext(asyncContext);
+        asyncContext.start();
+        Assertions.assertTrue(attachment.isAsyncStarted());
+        Assertions.assertEquals(asyncContext, attachment.getAsyncContext());
+        Assertions.assertTrue(attachment.stopAsync());
+    }
+
+    @Test
+    public void testObjectAttachmentMap() {
+        RpcServerContextAttachment attachment  = new 
RpcServerContextAttachment();
+        RpcServerContextAttachment.ObjectAttachmentMap objectAttachmentMap = 
new RpcServerContextAttachment.ObjectAttachmentMap(attachment);
+        objectAttachmentMap.put("key_1", "value_1");
+        Set<String> keySet = objectAttachmentMap.keySet();
+        Assertions.assertEquals(true, keySet.contains("key_1"));
+        Collection<Object> valueSet = objectAttachmentMap.values();
+        Assertions.assertEquals(true, valueSet.contains("value_1"));
+        Set<Map.Entry<String, Object>> entrySet = 
objectAttachmentMap.entrySet();
+        Map.Entry<String, Object> entry = entrySet.iterator().next();
+        Assertions.assertEquals("key_1", entry.getKey());
+        Assertions.assertEquals("value_1", entry.getValue());
+        Assertions.assertEquals(true, 
objectAttachmentMap.containsKey("key_1"));
+        Assertions.assertEquals(true, 
objectAttachmentMap.containsValue("value_1"));
+        Assertions.assertEquals("value_1", objectAttachmentMap.get("key_1"));
+        Assertions.assertEquals(null, objectAttachmentMap.get("key_2"));
+        objectAttachmentMap.remove("key_1");
+        Assertions.assertEquals(null, objectAttachmentMap.get("key_1"));
+        Map<String, String> map = new HashMap<>();
+        map.put("key_3","value_3");
+        map.put("key_4","value_4");
+        objectAttachmentMap.putAll(map);
+        Assertions.assertEquals("value_3", objectAttachmentMap.get("key_3"));
+        Assertions.assertEquals("value_4", objectAttachmentMap.get("key_4"));
+        Assertions.assertEquals(null, objectAttachmentMap.remove(new 
Object()));
+        objectAttachmentMap.clear();
+    }
+
+    @Test
+    public void testClearAttachmentMap() {
+        RpcServerContextAttachment attachment  = new 
RpcServerContextAttachment();
+        RpcServerContextAttachment.ObjectAttachmentMap objectAttachmentMap = 
new RpcServerContextAttachment.ObjectAttachmentMap(attachment);
+        objectAttachmentMap.put("key_1", "value_1");
+        objectAttachmentMap.put("key_2", "value_2");
+        objectAttachmentMap.put("key_3", "value_3");
+        Assertions.assertEquals(3, objectAttachmentMap.size());
+        objectAttachmentMap.clear();
+        Assertions.assertEquals(null, objectAttachmentMap.get(new Object()));
+        Assertions.assertEquals(0, objectAttachmentMap.size());
+        Assertions.assertEquals(true, objectAttachmentMap.isEmpty());
+    }
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java
 
b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java
index a37f87a98a..ae9549bfee 100644
--- 
a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java
+++ 
b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java
@@ -23,6 +23,7 @@ import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Result;
 import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.support.DemoService;
 import org.apache.dubbo.rpc.support.MockInvocation;
 import org.apache.dubbo.rpc.support.MyInvoker;
@@ -39,7 +40,7 @@ import static org.mockito.Mockito.mock;
  */
 public class ContextFilterTest {
 
-    Filter contextFilter = new ContextFilter();
+    Filter contextFilter = new ContextFilter(ApplicationModel.defaultModel());
     Invoker<DemoService> invoker;
     Invocation invocation;
 
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/PenetrateAttachmentSelectorMock.java
 
b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/PenetrateAttachmentSelectorMock.java
index f40eb0f078..9f74ef1cf1 100644
--- 
a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/PenetrateAttachmentSelectorMock.java
+++ 
b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/PenetrateAttachmentSelectorMock.java
@@ -16,17 +16,26 @@
  */
 package org.apache.dubbo.rpc.support;
 
+import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.PenetrateAttachmentSelector;
 import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcContextAttachment;
 
 import java.util.Map;
 
 public class PenetrateAttachmentSelectorMock implements 
PenetrateAttachmentSelector {
 
     @Override
-    public Map<String, Object> select() {
+    public Map<String, Object> select(Invocation invocation, 
RpcContextAttachment clientAttachment, RpcContextAttachment serverAttachment) {
         Map<String, Object> objectAttachments = 
RpcContext.getServerAttachment().getObjectAttachments();
         objectAttachments.put("testKey", "testVal");
         return objectAttachments;
     }
+
+    @Override
+    public Map<String, Object> selectReverse(Invocation invocation, 
RpcContextAttachment clientResponseContext, RpcContextAttachment 
serverResponseContext) {
+        Map<String, Object> objectAttachments = 
RpcContext.getServerResponseContext().getObjectAttachments();
+        objectAttachments.put("reverseKey", "reverseVal");
+        return objectAttachments;
+    }
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/AbstractServerCallListener.java
 
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/AbstractServerCallListener.java
index 2c06f35e0b..6a4f698edb 100644
--- 
a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/AbstractServerCallListener.java
+++ 
b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/AbstractServerCallListener.java
@@ -52,11 +52,11 @@ public abstract class AbstractServerCallListener implements 
AbstractServerCall.L
         RpcContext.restoreCancellationContext(cancellationContext);
         InetSocketAddress remoteAddress = (InetSocketAddress) 
invocation.getAttributes()
             .remove(AbstractServerCall.REMOTE_ADDRESS_KEY);
-        RpcContext.getServerContext().setRemoteAddress(remoteAddress);
+        RpcContext.getServiceContext().setRemoteAddress(remoteAddress);
         String remoteApp = (String) invocation.getAttributes()
             .remove(TripleHeaderEnum.CONSUMER_APP_NAME_KEY);
         if (null != remoteApp) {
-            RpcContext.getServerContext().setRemoteApplicationName(remoteApp);
+            RpcContext.getServiceContext().setRemoteApplicationName(remoteApp);
         }
         final long stInMillis = System.currentTimeMillis();
         try {


Reply via email to