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

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

commit 02eabd6369400fd61db29ca44492678af745bccd
Author: ken.lj <[email protected]>
AuthorDate: Sun Nov 3 13:26:07 2019 +0800

    generic codec & bootstrap api
---
 .../org/apache/dubbo/bootstrap/DubboBootstrap.java |  9 +++++
 .../org/apache/dubbo/config/ReferenceConfig.java   |  8 ++++-
 .../org/apache/dubbo/config/ServiceConfig.java     |  8 ++++-
 .../dubbo/config/utils/ReferenceConfigCache.java   |  2 ++
 .../apache/dubbo/config/spring/ReferenceBean.java  |  5 +++
 .../configcenter/DynamicConfigurationFactory.java  |  2 +-
 .../dubbo/common/constants/CommonConstants.java    |  2 ++
 .../apache/dubbo/common/utils/ReflectUtils.java    | 10 ++++++
 .../dubbo/config/service/ReferenceConfig.java      |  5 +--
 .../apache/dubbo/rpc/model/MethodDescriptor.java   |  9 ++++-
 .../store/InMemoryWritableMetadataService.java     |  5 ++-
 .../store/RemoteWritableMetadataService.java       |  5 ++-
 .../org/apache/dubbo/qos/command/impl/Offline.java | 38 +++++++++------------
 .../org/apache/dubbo/qos/command/impl/Online.java  | 39 +++++++++-------------
 .../org/apache/dubbo/rpc/ClusterInterceptor.java   | 11 +++++-
 .../src/main/java/org/apache/dubbo/rpc/Filter.java | 25 +++++++-------
 .../main/java/org/apache/dubbo/rpc/Invocation.java |  2 +-
 .../java/org/apache/dubbo/rpc/RpcInvocation.java   | 12 +++++++
 .../apache/dubbo/rpc/filter/GenericImplFilter.java | 39 ++++++++++++++++------
 .../org/apache/dubbo/rpc/support/RpcUtils.java     | 18 ++++++++++
 .../protocol/dubbo/DecodeableRpcInvocation.java    | 37 +++++++++++---------
 .../dubbo/rpc/protocol/dubbo/DubboCodec.java       |  3 +-
 22 files changed, 198 insertions(+), 96 deletions(-)

diff --git 
a/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
 
b/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
index 6281366..d537537 100644
--- 
a/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
+++ 
b/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
@@ -550,6 +550,14 @@ public class DubboBootstrap extends GenericEventListener {
         }
     }
 
+    public boolean isExported(ServiceConfig<?> serviceConfig) {
+        return CollectionUtils.isNotEmpty(exporters.get(serviceConfig));
+    }
+
+    public boolean isRefereed(ReferenceConfig<?> referenceConfig) {
+        return getCache().get(referenceConfig) != null;
+    }
+
     /**
      * refer a single ReferenceConfig
      * <p>
@@ -1257,6 +1265,7 @@ public class DubboBootstrap extends GenericEventListener {
                 }
             }
             sc.setInterface(interfaceClass);
+            sc.setInterface(interfaceName);
             sc.checkStubAndLocal(interfaceClass);
             BootstrapUtils.checkMock(interfaceClass, sc);
             sc.appendParameters();
diff --git 
a/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
 
b/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index 047f8a4..654d5e9 100644
--- 
a/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
+++ 
b/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
@@ -24,12 +24,18 @@ import org.apache.dubbo.bootstrap.DubboBootstrap;
  */
 @Deprecated
 public class ReferenceConfig<T> extends 
org.apache.dubbo.config.service.ReferenceConfig<T> {
+    DubboBootstrap bootstrap = DubboBootstrap.getInstance();
 
+    @Deprecated
     public synchronized T get() {
-        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
         // bootstrap guarantees only started once.
         bootstrap.start();
         return (T) bootstrap.refer(this);
     }
 
+    @Deprecated
+    public void destroy() {
+        bootstrap.unRefer(this);
+    }
+
 }
diff --git 
a/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
 
b/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index 29cb5a3..3921318 100644
--- 
a/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ 
b/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -25,12 +25,18 @@ import org.apache.dubbo.bootstrap.DubboBootstrap;
 @Deprecated
 public class ServiceConfig<T> extends 
org.apache.dubbo.config.service.ServiceConfig<T> {
 
+    private DubboBootstrap bootstrap = DubboBootstrap.getInstance();
+
     @Deprecated
     public void export() {
-        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
         // bootstrap guarantees only started once.
         bootstrap.start();
         bootstrap.export(this);
     }
 
+    @Deprecated
+    public void unexport() {
+        bootstrap.unExport(this);
+    }
+
 }
\ No newline at end of file
diff --git 
a/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java
 
b/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java
index 925e1e9..2e40b7b 100644
--- 
a/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java
+++ 
b/dubbo-bootstrap/dubbo-bootstrap-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java
@@ -538,6 +538,7 @@ public class ReferenceConfigCache {
                 rc.setGeneric(rc.getConsumer().getGeneric());
             }
             Class<?> interfaceClass = null;
+            String realInterfaceName = rc.getInterface();
             if (ProtocolUtils.isGeneric(rc.getGeneric())) {
                 interfaceClass = GenericService.class;
             } else {
@@ -550,6 +551,7 @@ public class ReferenceConfigCache {
                 rc.checkInterfaceAndMethods(interfaceClass, rc.getMethods());
             }
             rc.setInterface(interfaceClass);
+            rc.setInterface(realInterfaceName);
             rc.resolveFile();
             rc.checkApplication();
             rc.checkMetadataReport();
diff --git 
a/dubbo-bootstrap/dubbo-bootstrap-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
 
b/dubbo-bootstrap/dubbo-bootstrap-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
index 26ca08e..9207421 100644
--- 
a/dubbo-bootstrap/dubbo-bootstrap-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
+++ 
b/dubbo-bootstrap/dubbo-bootstrap-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
@@ -76,6 +76,11 @@ public class ReferenceBean<T> extends ReferenceConfig<T> 
implements FactoryBean,
             BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, 
ConfigCenterBean.class, false, false);
         }
 
+        // lazy init by default.
+        if (init == null) {
+            init = false;
+        }
+
         // eager init if necessary.
         if (shouldInit()) {
             getObject();
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
index 649eec6..ae4a8ee 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
@@ -25,7 +25,7 @@ import static 
org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
 /**
  * The factory interface to create the instance of {@link DynamicConfiguration}
  */
-@SPI("file") // 2.7.4 change the default SPI implementation
+@SPI("nop")
 public interface DynamicConfigurationFactory {
 
     DynamicConfiguration getDynamicConfiguration(URL url);
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
index e859f50..a8b2037 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
@@ -288,4 +288,6 @@ public interface CommonConstants {
 
     String REGISTER_KEY = "register";
 
+    String DUBBO_INVOCATION_PREFIX = "_DUBBO_IGNORE_ATTACH_";
+
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java 
b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
index 6d92210..18201d8 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
@@ -428,6 +428,16 @@ public final class ReflectUtils {
         return ret.toString();
     }
 
+    public static String[] getDescArray(final Method m) {
+        Class<?>[] parameterTypes = m.getParameterTypes();
+        String[] arr = new String[parameterTypes.length];
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            arr[i] = getDesc(parameterTypes[i]);
+        }
+        return arr;
+    }
+
     /**
      * get constructor desc.
      * "()V", "(Ljava/lang/String;I)V"
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/config/service/ReferenceConfig.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/config/service/ReferenceConfig.java
index e624a2b..a0da2bf 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/config/service/ReferenceConfig.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/config/service/ReferenceConfig.java
@@ -131,8 +131,9 @@ public class ReferenceConfig<T> extends 
AbstractReferenceConfig {
             shouldInit = getConsumer().isInit();
         }
         if (shouldInit == null) {
-            // default is false
-            return false;
+            // default is true, spring will still init lazily by setting 
init's default value to false,
+            // the def default setting happens in {@link 
ReferenceBean#afterPropertiesSet}.
+            return true;
         }
         return shouldInit;
     }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/MethodDescriptor.java 
b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/MethodDescriptor.java
index de0f7cf..cd5bf91 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/MethodDescriptor.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/MethodDescriptor.java
@@ -32,6 +32,8 @@ public class MethodDescriptor {
     //    private final boolean isCallBack;
 //    private final boolean isFuture;
     private final String paramDesc;
+    // duplicate filed as paramDesc, but with different format.
+    private final String[] compatibleParamSignatures;
     private final Class<?>[] parameterClasses;
     private final Class<?> returnClass;
     private final Type[] returnTypes;
@@ -43,7 +45,8 @@ public class MethodDescriptor {
         this.parameterClasses = method.getParameterTypes();
         this.returnClass = method.getReturnType();
         this.returnTypes = ReflectUtils.getReturnTypes(method);
-        this.paramDesc = ReflectUtils.getDesc(method);
+        this.paramDesc = ReflectUtils.getDesc(parameterClasses);
+        this.compatibleParamSignatures = ReflectUtils.getDescArray(method);
         this.methodName = method.getName();
         this.generic = (methodName.equals($INVOKE) || 
methodName.equals($INVOKE_ASYNC)) && parameterClasses.length == 3;
     }
@@ -60,6 +63,10 @@ public class MethodDescriptor {
         return paramDesc;
     }
 
+    public String[] getCompatibleParamSignatures() {
+        return compatibleParamSignatures;
+    }
+
     public Class<?>[] getParameterClasses() {
         return parameterClasses;
     }
diff --git 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java
 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java
index 115fab8..ede7b59 100644
--- 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java
+++ 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java
@@ -24,6 +24,7 @@ import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
 import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+import org.apache.dubbo.rpc.support.ProtocolUtils;
 
 import com.google.gson.Gson;
 
@@ -44,6 +45,7 @@ import static org.apache.dubbo.common.URL.buildKey;
 import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
 import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
+import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
 
 /**
  * The {@link WritableMetadataService} implementation stores the metadata of 
Dubbo services in memory locally when they
@@ -122,7 +124,8 @@ public class InMemoryWritableMetadataService implements 
WritableMetadataService
     public void publishServiceDefinition(URL providerUrl) {
         try {
             String interfaceName = providerUrl.getParameter(INTERFACE_KEY);
-            if (StringUtils.isNotEmpty(interfaceName)) {
+            if (StringUtils.isNotEmpty(interfaceName)
+                    && 
!ProtocolUtils.isGeneric(providerUrl.getParameter(GENERIC_KEY))) {
                 Class interfaceClass = Class.forName(interfaceName);
                 ServiceDefinition serviceDefinition = 
ServiceDefinitionBuilder.build(interfaceClass);
                 Gson gson = new Gson();
diff --git 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java
 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java
index 22c028d..609d43f 100644
--- 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java
+++ 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java
@@ -32,6 +32,7 @@ import 
org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
 import 
org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.support.ProtocolUtils;
 
 import java.util.Iterator;
 import java.util.Set;
@@ -47,6 +48,7 @@ import static 
org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
 import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
+import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
 
 /**
  * The {@link WritableMetadataService} implementation stores the metadata of 
Dubbo services in metadata center when they
@@ -74,7 +76,8 @@ public class RemoteWritableMetadataService implements 
WritableMetadataService {
     public void publishServiceDefinition(URL providerUrl) {
         try {
             String interfaceName = providerUrl.getParameter(INTERFACE_KEY);
-            if (StringUtils.isNotEmpty(interfaceName)) {
+            if (StringUtils.isNotEmpty(interfaceName)
+                    && 
!ProtocolUtils.isGeneric(providerUrl.getParameter(GENERIC_KEY))) {
                 Class interfaceClass = Class.forName(interfaceName);
                 ServiceDefinition serviceDefinition = 
ServiceDefinitionBuilder.build(interfaceClass);
                 getMetadataReport().storeProviderMetadata(new 
MetadataIdentifier(providerUrl.getServiceInterface(),
diff --git 
a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
 
b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
index aa236a7..eae4aca 100644
--- 
a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
+++ 
b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
@@ -16,8 +16,6 @@
  */
 package org.apache.dubbo.qos.command.impl;
 
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.URLBuilder;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
@@ -26,8 +24,6 @@ import org.apache.dubbo.qos.command.CommandContext;
 import org.apache.dubbo.qos.command.annotation.Cmd;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.registry.RegistryFactory;
-import org.apache.dubbo.registry.RegistryService;
-import org.apache.dubbo.registry.support.AbstractRegistryFactory;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
 import org.apache.dubbo.rpc.model.ServiceRepository;
@@ -35,18 +31,14 @@ import org.apache.dubbo.rpc.model.ServiceRepository;
 import java.util.Collection;
 import java.util.List;
 
-import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
-
 @Cmd(name = "offline", summary = "offline dubbo", example = {
         "offline dubbo",
         "offline xx.xx.xxx.service"
 })
 public class Offline implements BaseCommand {
     private Logger logger = LoggerFactory.getLogger(Offline.class);
-    private RegistryFactory registryFactory = 
ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
-    private ServiceRepository serviceRepository = 
ApplicationModel.getServiceRepository();
+    private static RegistryFactory registryFactory = 
ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
+    private static ServiceRepository serviceRepository = 
ApplicationModel.getServiceRepository();
 
     @Override
     public String execute(CommandContext commandContext, String[] args) {
@@ -55,6 +47,17 @@ public class Offline implements BaseCommand {
         if (args != null && args.length > 0) {
             servicePattern = args[0];
         }
+
+        boolean hasService = offline(servicePattern);
+
+        if (hasService) {
+            return "OK";
+        } else {
+            return "service not found";
+        }
+    }
+
+    public static boolean offline(String servicePattern) {
         boolean hasService = false;
 
         Collection<ProviderModel> providerModelList = 
serviceRepository.getExportedServices();
@@ -64,25 +67,14 @@ public class Offline implements BaseCommand {
                 List<ProviderModel.RegisterStatedURL> statedUrls = 
providerModel.getStatedUrl();
                 for (ProviderModel.RegisterStatedURL statedURL : statedUrls) {
                     if (statedURL.isRegistered()) {
-                        URL url = URLBuilder.from(statedURL.getRegistryUrl())
-                                .setPath(RegistryService.class.getName())
-                                .addParameter(INTERFACE_KEY, 
RegistryService.class.getName())
-                                .removeParameters(EXPORT_KEY, REFER_KEY)
-                                .build();
-                        String key = url.toServiceStringWithoutResolving();
-                        Registry registry = 
AbstractRegistryFactory.getRegistry(key);
+                        Registry registry = 
registryFactory.getRegistry(statedURL.getRegistryUrl());
                         registry.unregister(statedURL.getProviderUrl());
                         statedURL.setRegistered(false);
                     }
                 }
-
             }
         }
 
-        if (hasService) {
-            return "OK";
-        } else {
-            return "service not found";
-        }
+        return hasService;
     }
 }
diff --git 
a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
 
b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
index 4f8598c..1f99dd5 100644
--- 
a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
+++ 
b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
@@ -16,8 +16,6 @@
  */
 package org.apache.dubbo.qos.command.impl;
 
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.URLBuilder;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
@@ -27,8 +25,6 @@ import org.apache.dubbo.qos.command.CommandContext;
 import org.apache.dubbo.qos.command.annotation.Cmd;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.registry.RegistryFactory;
-import org.apache.dubbo.registry.RegistryService;
-import org.apache.dubbo.registry.support.AbstractRegistryFactory;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
 import org.apache.dubbo.rpc.model.ServiceRepository;
@@ -36,18 +32,14 @@ import org.apache.dubbo.rpc.model.ServiceRepository;
 import java.util.Collection;
 import java.util.List;
 
-import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
-
 @Cmd(name = "online", summary = "online dubbo", example = {
         "online dubbo",
         "online xx.xx.xxx.service"
 })
 public class Online implements BaseCommand {
-    private Logger logger = LoggerFactory.getLogger(Online.class);
-    private RegistryFactory registryFactory = 
ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
-    private ServiceRepository serviceRepository = 
ApplicationModel.getServiceRepository();
+    private static final Logger logger = LoggerFactory.getLogger(Online.class);
+    private static RegistryFactory registryFactory = 
ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
+    private static ServiceRepository serviceRepository = 
ApplicationModel.getServiceRepository();
 
     @Override
     public String execute(CommandContext commandContext, String[] args) {
@@ -57,6 +49,15 @@ public class Online implements BaseCommand {
             servicePattern = args[0];
         }
 
+        boolean hasService = online(servicePattern);
+        if (hasService) {
+            return "OK";
+        } else {
+            return "service not found";
+        }
+    }
+
+    public static boolean online(String servicePattern) {
         boolean hasService = false;
 
         Collection<ProviderModel> providerModelList = 
serviceRepository.getExportedServices();
@@ -65,14 +66,8 @@ public class Online implements BaseCommand {
                 hasService = true;
                 List<ProviderModel.RegisterStatedURL> statedUrls = 
providerModel.getStatedUrl();
                 for (ProviderModel.RegisterStatedURL statedURL : statedUrls) {
-                    if (statedURL.isRegistered()) {
-                        URL url = URLBuilder.from(statedURL.getRegistryUrl())
-                                .setPath(RegistryService.class.getName())
-                                .addParameter(INTERFACE_KEY, 
RegistryService.class.getName())
-                                .removeParameters(EXPORT_KEY, REFER_KEY)
-                                .build();
-                        String key = url.toServiceStringWithoutResolving();
-                        Registry registry = 
AbstractRegistryFactory.getRegistry(key);
+                    if (!statedURL.isRegistered()) {
+                        Registry registry = 
registryFactory.getRegistry(statedURL.getRegistryUrl());
                         registry.register(statedURL.getProviderUrl());
                         statedURL.setRegistered(true);
                     }
@@ -80,10 +75,6 @@ public class Online implements BaseCommand {
             }
         }
 
-        if (hasService) {
-            return "OK";
-        } else {
-            return "service not found";
-        }
+        return hasService;
     }
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ClusterInterceptor.java
 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ClusterInterceptor.java
index a90b500..48cdcdd 100644
--- 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ClusterInterceptor.java
+++ 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ClusterInterceptor.java
@@ -19,7 +19,7 @@ package org.apache.dubbo.rpc;
 import org.apache.dubbo.common.extension.SPI;
 
 /**
- * Different from {@link Filter}, ClusterInterceptor works on the outmost 
layer, before one specific address/invoker is picked.
+ * Different from {@link Filter}, ClusterInterceptor works at the outmost 
layer, before one specific address/invoker is picked.
  */
 @SPI
 public interface ClusterInterceptor {
@@ -28,6 +28,15 @@ public interface ClusterInterceptor {
 
     void after(Invoker<?> invoker, Invocation invocation);
 
+    /**
+     * Does not need to override this method, override {@link #before(Invoker, 
Invocation)} and {@link #after(Invoker, Invocation)}
+     * methods to add your own logic expected to be executed before and after 
invoke.
+     *
+     * @param invoker
+     * @param invocation
+     * @return
+     * @throws RpcException
+     */
     default Result invoke(Invoker<?> invoker, Invocation invocation) throws 
RpcException {
         return invoker.invoke(invocation);
     }
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java
index 42158b7..72a50c7 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java
@@ -47,19 +47,20 @@ public interface Filter {
      */
     Result invoke(Invoker<?> invoker, Invocation invocation) throws 
RpcException;
 
-    interface Listener {
+    /**
+     * Please use {@link Listener#onMessage(Result, Invoker, Invocation)} 
instead.
+     * This method is kept only for compatibility and may get removed at any 
version in the future.
+     *
+     * @param appResponse
+     * @param invoker
+     * @param invocation
+     */
+    @Deprecated
+    default Result onResponse(Result appResponse, Invoker<?> invoker, 
Invocation invocation) {
+        return appResponse;
+    }
 
-        /**
-         * Please use {@link #onMessage(Result, Invoker, Invocation)} instead.
-         * This method is kept only compatibility and may get removed at any 
version in the future.
-         *
-         * @param appResponse
-         * @param invoker
-         * @param invocation
-         */
-        @Deprecated
-        default void onResponse(Result appResponse, Invoker<?> invoker, 
Invocation invocation) {
-        }
+    interface Listener {
 
         void onMessage(Result appResponse, Invoker<?> invoker, Invocation 
invocation);
 
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
index e54e115..02ba1f0 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
@@ -58,7 +58,7 @@ public interface Invocation {
      *
      * @return parameter's signature
      */
-    default String[] getParameterSignatures() {
+    default String[] getCompatibleParamSignatures() {
         return Stream.of(getParameterTypes())
                 .map(Class::getName)
                 .toArray(String[]::new);
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
index 960e091..978acbe 100644
--- 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
+++ 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
@@ -51,6 +51,7 @@ public class RpcInvocation implements Invocation, 
Serializable {
 
     private transient Class<?>[] parameterTypes;
     private String parameterTypesDesc;
+    private String[] compatibleParamSignatures;
 
     private Object[] arguments;
 
@@ -133,6 +134,7 @@ public class RpcInvocation implements Invocation, 
Serializable {
                     serviceModel.getMethod(methodName, parameterTypes)
                             .ifPresent(methodModel -> {
                                 this.parameterTypesDesc = 
methodModel.getParamDesc();
+                                this.compatibleParamSignatures = 
methodModel.getCompatibleParamSignatures();
                                 this.returnTypes = 
methodModel.getReturnTypes();
                             })
             );
@@ -205,6 +207,16 @@ public class RpcInvocation implements Invocation, 
Serializable {
         this.parameterTypesDesc = parameterTypesDesc;
     }
 
+    public String[] getCompatibleParamSignatures() {
+        return compatibleParamSignatures;
+    }
+
+    // parameter signatures can be set independently, it is useful when the 
service type is not found on caller side and
+    // the invocation is not generic invocation either.
+    public void setCompatibleParamSignatures(String[] 
compatibleParamSignatures) {
+        this.compatibleParamSignatures = compatibleParamSignatures;
+    }
+
     @Override
     public Object[] getArguments() {
         return arguments;
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericImplFilter.java
 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericImplFilter.java
index 579f21d..7b78c0c 100644
--- 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericImplFilter.java
+++ 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericImplFilter.java
@@ -42,6 +42,7 @@ import java.lang.reflect.Type;
 
 import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
 import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE_ASYNC;
+import static 
org.apache.dubbo.common.constants.CommonConstants.DUBBO_INVOCATION_PREFIX;
 import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
 
 /**
@@ -56,13 +57,21 @@ public class GenericImplFilter implements Filter, 
Filter.Listener {
 
     private static final String GENERIC_PARAMETER_DESC = 
"Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;";
 
+    private static final String GENERIC_IMPL_MARKER = DUBBO_INVOCATION_PREFIX 
+ "GENERIC_IMPL";
+
     @Override
     public Result invoke(Invoker<?> invoker, Invocation invocation) throws 
RpcException {
         String generic = invoker.getUrl().getParameter(GENERIC_KEY);
-        if (ProtocolUtils.isGeneric(generic)
-                && (!$INVOKE.equals(invocation.getMethodName()) && 
!$INVOKE_ASYNC.equals(invocation.getMethodName()))
-                && invocation instanceof RpcInvocation) {
+        // calling a generic impl service
+        if (isCallingGenericImpl(generic, invocation)) {
             RpcInvocation invocation2 = new RpcInvocation(invocation);
+
+            /**
+             * Mark this invocation as a generic impl call, this value will be 
removed automatically before passing on the wire.
+             * See {@link RpcUtils#sieveUnnecessaryAttachments(Invocation)}
+             */
+            invocation2.setAttachment(GENERIC_IMPL_MARKER, true);
+
             String methodName = invocation2.getMethodName();
             Class<?>[] parameterTypes = invocation2.getParameterTypes();
             Object[] arguments = invocation2.getArguments();
@@ -91,10 +100,9 @@ public class GenericImplFilter implements Filter, 
Filter.Listener {
             invocation2.setParameterTypesDesc(GENERIC_PARAMETER_DESC);
             invocation2.setArguments(new Object[]{methodName, types, args});
             return invoker.invoke(invocation2);
-        } else if ((invocation.getMethodName().equals($INVOKE) || 
invocation.getMethodName().equals($INVOKE_ASYNC))
-                && invocation.getArguments() != null
-                && invocation.getArguments().length == 3
-                && ProtocolUtils.isGeneric(generic)) {
+        }
+        // making a generic call to a normal service
+        else if (isMakingGenericCall(generic, invocation)) {
 
             Object[] args = (Object[]) invocation.getArguments()[2];
             if (ProtocolUtils.isJavaGenericSerialization(generic)) {
@@ -127,9 +135,7 @@ public class GenericImplFilter implements Filter, 
Filter.Listener {
         String generic = invoker.getUrl().getParameter(GENERIC_KEY);
         String methodName = invocation.getMethodName();
         Class<?>[] parameterTypes = invocation.getParameterTypes();
-        if (ProtocolUtils.isGeneric(generic)
-                && (!$INVOKE.equals(invocation.getMethodName()) && 
!$INVOKE_ASYNC.equals(invocation.getMethodName()))
-                && invocation instanceof RpcInvocation) {
+        if (invocation.getAttachment(GENERIC_IMPL_MARKER) != null) {
             if (!appResponse.hasException()) {
                 Object value = appResponse.getValue();
                 try {
@@ -195,4 +201,17 @@ public class GenericImplFilter implements Filter, 
Filter.Listener {
 
     }
 
+    private boolean isCallingGenericImpl(String generic, Invocation 
invocation) {
+        return ProtocolUtils.isGeneric(generic)
+                && (!$INVOKE.equals(invocation.getMethodName()) && 
!$INVOKE_ASYNC.equals(invocation.getMethodName()))
+                && invocation instanceof RpcInvocation;
+    }
+
+    private boolean isMakingGenericCall(String generic, Invocation invocation) 
{
+        return (invocation.getMethodName().equals($INVOKE) || 
invocation.getMethodName().equals($INVOKE_ASYNC))
+                && invocation.getArguments() != null
+                && invocation.getArguments().length == 3
+                && ProtocolUtils.isGeneric(generic);
+    }
+
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java
 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java
index b1c6d15..7415928 100644
--- 
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java
+++ 
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java
@@ -28,11 +28,14 @@ import org.apache.dubbo.rpc.service.GenericService;
 
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicLong;
 
 import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
 import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE_ASYNC;
+import static 
org.apache.dubbo.common.constants.CommonConstants.DUBBO_INVOCATION_PREFIX;
 import static org.apache.dubbo.rpc.Constants.ASYNC_KEY;
 import static org.apache.dubbo.rpc.Constants.AUTO_ATTACH_INVOCATIONID_KEY;
 import static org.apache.dubbo.rpc.Constants.ID_KEY;
@@ -184,6 +187,10 @@ public class RpcUtils {
         return $INVOKE_ASYNC.equals(inv.getMethodName());
     }
 
+    public static boolean isGenericCall(String path, String method) {
+        return $INVOKE.equals(method) || $INVOKE_ASYNC.equals(method);
+    }
+
     public static InvokeMode getInvokeMode(URL url, Invocation inv) {
         if (isReturnTypeFuture(inv)) {
             return InvokeMode.FUTURE;
@@ -203,4 +210,15 @@ public class RpcUtils {
         }
         return isOneway;
     }
+
+    public static Map<String, Object> sieveUnnecessaryAttachments(Invocation 
invocation) {
+        Map<String, Object> attachments = invocation.getAttachments();
+        Map<String, Object> attachmentsToPass = new 
HashMap<>(attachments.size());
+        for (Map.Entry<String, Object> entry : attachments.entrySet()) {
+            if (!entry.getKey().startsWith(DUBBO_INVOCATION_PREFIX)) {
+                attachmentsToPass.put(entry.getKey(), entry.getValue());
+            }
+        }
+        return attachmentsToPass;
+    }
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
 
b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
index 31c2bfc..d72a878 100644
--- 
a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
+++ 
b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.serialize.Cleanable;
 import org.apache.dubbo.common.serialize.ObjectInput;
 import org.apache.dubbo.common.utils.Assert;
+import org.apache.dubbo.common.utils.ReflectUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.Codec;
@@ -32,6 +33,7 @@ import org.apache.dubbo.rpc.RpcInvocation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.MethodDescriptor;
 import org.apache.dubbo.rpc.model.ServiceDescriptor;
+import org.apache.dubbo.rpc.support.RpcUtils;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -115,24 +117,27 @@ public class DecodeableRpcInvocation extends 
RpcInvocation implements Codec, Dec
             Object[] args = DubboCodec.EMPTY_OBJECT_ARRAY;
             Class<?>[] pts = DubboCodec.EMPTY_CLASS_ARRAY;
             if (desc.length() > 0) {
-                // TODO, lambda function requires variables to be final.
-                Optional<ServiceDescriptor> serviceModel = 
ApplicationModel.getServiceModel(path);
-                if (serviceModel.isPresent()) {
-                    Optional<MethodDescriptor> methodOptional = 
serviceModel.get().getMethod(getMethodName(), desc);
-                    if (methodOptional.isPresent()) {
-                        pts = methodOptional.get().getParameterClasses();
-                        args = new Object[pts.length];
-                        for (int i = 0; i < args.length; i++) {
-                            try {
-                                args[i] = in.readObject(pts[i]);
-                            } catch (Exception e) {
-                                if (log.isWarnEnabled()) {
-                                    log.warn("Decode argument failed: " + 
e.getMessage(), e);
-                                }
-                            }
+                if (RpcUtils.isGenericCall(path, getMethodName())) {
+                    pts = ReflectUtils.desc2classArray(desc);
+                } else {
+                    Optional<ServiceDescriptor> serviceModel = 
ApplicationModel.getServiceModel(path);
+                    if (serviceModel.isPresent()) {
+                        Optional<MethodDescriptor> methodOptional = 
serviceModel.get().getMethod(getMethodName(), desc);
+                        if (methodOptional.isPresent()) {
+                            pts = methodOptional.get().getParameterClasses();
+                            
this.setReturnTypes(methodOptional.get().getReturnTypes());
                         }
+                    }
+                }
 
-                        
this.setReturnTypes(methodOptional.get().getReturnTypes());
+                args = new Object[pts.length];
+                for (int i = 0; i < args.length; i++) {
+                    try {
+                        args[i] = in.readObject(pts[i]);
+                    } catch (Exception e) {
+                        if (log.isWarnEnabled()) {
+                            log.warn("Decode argument failed: " + 
e.getMessage(), e);
+                        }
                     }
                 }
             }
diff --git 
a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java
 
b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java
index 3716c45..ac4e53d 100644
--- 
a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java
+++ 
b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java
@@ -42,6 +42,7 @@ import static 
org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
 import static 
org.apache.dubbo.rpc.protocol.dubbo.CallbackServiceCodec.encodeInvocationArgument;
 import static 
org.apache.dubbo.rpc.protocol.dubbo.Constants.DECODE_IN_IO_THREAD_KEY;
 import static 
org.apache.dubbo.rpc.protocol.dubbo.Constants.DEFAULT_DECODE_IN_IO_THREAD;
+import static 
org.apache.dubbo.rpc.support.RpcUtils.sieveUnnecessaryAttachments;
 
 /**
  * Dubbo codec.
@@ -179,7 +180,7 @@ public class DubboCodec extends ExchangeCodec {
                 out.writeObject(encodeInvocationArgument(channel, inv, i));
             }
         }
-        out.writeAttachments(inv.getAttachments());
+        out.writeAttachments(sieveUnnecessaryAttachments(inv));
     }
 
     @Override

Reply via email to