[ 
https://issues.apache.org/jira/browse/SCB-926?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16631288#comment-16631288
 ] 

ASF GitHub Bot commented on SCB-926:
------------------------------------

liubao68 closed pull request #915: [SCB-926] support invoking 3rd party service
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/915
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git 
a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java 
b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java
index 70c66f89b..5ed1759c1 100644
--- a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java
+++ b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java
@@ -19,6 +19,7 @@
 
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.definition.loader.SchemaListenerManager;
+import org.apache.servicecomb.core.definition.schema.StaticSchemaFactory;
 import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager;
 import org.apache.servicecomb.core.provider.producer.ProducerProviderManager;
 import org.apache.servicecomb.core.transport.TransportManager;
@@ -74,6 +75,7 @@ public void onApplicationEvent(ApplicationEvent event) {
         
SCBEngine.getInstance().setTransportManager(applicationContext.getBean(TransportManager.class));
         
SCBEngine.getInstance().setSchemaListenerManager(applicationContext.getBean(SchemaListenerManager.class));
         
SCBEngine.getInstance().setBootListenerList(applicationContext.getBeansOfType(BootListener.class).values());
+        
SCBEngine.getInstance().setStaticSchemaFactory(applicationContext.getBean(StaticSchemaFactory.class));
       }
 
       SCBEngine.getInstance().init();
diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java 
b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java
index 4be7e7c7b..f364d1c6f 100644
--- a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java
+++ b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java
@@ -31,6 +31,7 @@
 import org.apache.servicecomb.core.BootListener.EventType;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.definition.loader.SchemaListenerManager;
+import org.apache.servicecomb.core.definition.schema.StaticSchemaFactory;
 import org.apache.servicecomb.core.endpoint.AbstractEndpointsCache;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.event.InvocationStartEvent;
@@ -82,6 +83,8 @@
 
   private EventBus eventBus = EventManager.getEventBus();
 
+  private StaticSchemaFactory staticSchemaFactory;
+
   private static final SCBEngine INSTANCE = new SCBEngine();
 
   public void setStatus(SCBStatus status) {
@@ -374,4 +377,12 @@ public void waitStatusUp(long msWait) throws 
InterruptedException, TimeoutExcept
       }
     }
   }
+
+  public StaticSchemaFactory getStaticSchemaFactory() {
+    return staticSchemaFactory;
+  }
+
+  public void setStaticSchemaFactory(StaticSchemaFactory staticSchemaFactory) {
+    this.staticSchemaFactory = staticSchemaFactory;
+  }
 }
diff --git 
a/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionMeta.java
 
b/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionMeta.java
index a5eff5853..e4e27632b 100644
--- 
a/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionMeta.java
+++ 
b/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionMeta.java
@@ -20,10 +20,15 @@
 import org.apache.servicecomb.core.CseContext;
 import 
org.apache.servicecomb.core.definition.classloader.MicroserviceClassLoaderFactory;
 import org.apache.servicecomb.serviceregistry.api.Const;
+import org.apache.servicecomb.serviceregistry.api.registry.Microservice;
 import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersion;
 
 public class MicroserviceVersionMeta extends MicroserviceVersion {
-  private MicroserviceMeta microserviceMeta;
+  MicroserviceMeta microserviceMeta;
+
+  MicroserviceVersionMeta(Microservice microservice) {
+    super(microservice);
+  }
 
   public MicroserviceVersionMeta(String microserviceName, String 
microserviceId,
       MicroserviceClassLoaderFactory classLoaderFactory) {
diff --git 
a/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMeta.java
 
b/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMeta.java
new file mode 100644
index 000000000..0fd866bc0
--- /dev/null
+++ 
b/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMeta.java
@@ -0,0 +1,44 @@
+/*
+ * 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.servicecomb.core.definition;
+
+import org.apache.servicecomb.core.CseContext;
+import org.apache.servicecomb.core.SCBEngine;
+import 
org.apache.servicecomb.core.definition.classloader.MicroserviceClassLoaderFactory;
+import org.apache.servicecomb.serviceregistry.api.Const;
+import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice;
+
+public class StaticMicroserviceVersionMeta extends MicroserviceVersionMeta {
+
+  public StaticMicroserviceVersionMeta(StaticMicroservice microservice,
+      MicroserviceClassLoaderFactory classLoaderFactory) {
+    super(microservice);
+
+    this.microserviceMeta = new 
MicroserviceMeta(microservice.getServiceName());
+    this.microserviceMeta.setClassLoader(
+        classLoaderFactory.create(microservice.getAppId(), 
microservice.getServiceName(), microservice.getVersion()));
+    if (Const.REGISTRY_APP_ID.equals(microservice.getAppId())
+        && Const.REGISTRY_SERVICE_NAME.equals(microservice.getServiceName())) {
+      // do not load service center schemas
+      return;
+    }
+
+    
SCBEngine.getInstance().getStaticSchemaFactory().loadSchema(microserviceMeta, 
microservice);
+    
CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(microserviceMeta);
+  }
+}
diff --git 
a/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaFactory.java
 
b/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaFactory.java
new file mode 100644
index 000000000..e10dc9b2e
--- /dev/null
+++ 
b/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.servicecomb.core.definition;
+
+import 
org.apache.servicecomb.core.definition.classloader.MicroserviceClassLoaderFactory;
+import 
org.apache.servicecomb.core.definition.classloader.PrivateMicroserviceClassLoaderFactory;
+import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice;
+import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersion;
+import 
org.apache.servicecomb.serviceregistry.consumer.StaticMicroserviceVersionFactory;
+
+public class StaticMicroserviceVersionMetaFactory implements 
StaticMicroserviceVersionFactory {
+  private final MicroserviceClassLoaderFactory classLoaderFactory = 
PrivateMicroserviceClassLoaderFactory.INSTANCE;
+
+  @Override
+  public MicroserviceVersion create(StaticMicroservice microservice) {
+    return new StaticMicroserviceVersionMeta(microservice, classLoaderFactory);
+  }
+}
diff --git 
a/core/src/main/java/org/apache/servicecomb/core/definition/schema/ProducerSchemaFactory.java
 
b/core/src/main/java/org/apache/servicecomb/core/definition/schema/ProducerSchemaFactory.java
index 5b1d0c885..59888d4c6 100644
--- 
a/core/src/main/java/org/apache/servicecomb/core/definition/schema/ProducerSchemaFactory.java
+++ 
b/core/src/main/java/org/apache/servicecomb/core/definition/schema/ProducerSchemaFactory.java
@@ -36,6 +36,7 @@
 import org.apache.servicecomb.core.executor.ExecutorManager;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.swagger.SwaggerUtils;
 import org.apache.servicecomb.swagger.engine.SwaggerEnvironment;
 import org.apache.servicecomb.swagger.engine.SwaggerProducer;
 import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation;
@@ -45,13 +46,10 @@
 import org.springframework.stereotype.Component;
 import org.springframework.util.StringUtils;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectWriter;
 import com.netflix.config.DynamicPropertyFactory;
 
 import io.swagger.models.Operation;
 import io.swagger.models.Swagger;
-import io.swagger.util.Yaml;
 
 @Component
 public class ProducerSchemaFactory extends 
AbstractSchemaFactory<ProducerSchemaContext> {
@@ -60,22 +58,12 @@
   @Inject
   private SwaggerEnvironment swaggerEnv;
 
-  private ObjectWriter writer = Yaml.pretty();
-
-  private String getSwaggerContent(Swagger swagger) {
-    try {
-      return writer.writeValueAsString(swagger);
-    } catch (JsonProcessingException e) {
-      throw new Error(e);
-    }
-  }
-
   public void setSwaggerEnv(SwaggerEnvironment swaggerEnv) {
     this.swaggerEnv = swaggerEnv;
   }
 
   // 只会在启动流程中调用
-  public SchemaMeta getOrCreateProducerSchema( String schemaId,
+  public SchemaMeta getOrCreateProducerSchema(String schemaId,
       Class<?> producerClass,
       Object producerInstance) {
     MicroserviceMeta microserviceMeta = 
SCBEngine.getInstance().getProducerMicroserviceMeta();
@@ -126,7 +114,7 @@ protected SchemaMeta createSchema(ProducerSchemaContext 
context) {
     if (swagger == null) {
       SwaggerGenerator generator = generateSwagger(context);
       swagger = generator.getSwagger();
-      String swaggerContent = getSwaggerContent(swagger);
+      String swaggerContent = SwaggerUtils.swaggerToString(swagger);
       LOGGER.info("generate swagger for {}/{}/{}, swagger: {}",
           context.getMicroserviceMeta().getAppId(),
           context.getMicroserviceName(),
diff --git 
a/core/src/main/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactory.java
 
b/core/src/main/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactory.java
new file mode 100644
index 000000000..0606e46d8
--- /dev/null
+++ 
b/core/src/main/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactory.java
@@ -0,0 +1,62 @@
+/*
+ * 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.servicecomb.core.definition.schema;
+
+import org.apache.servicecomb.core.definition.MicroserviceMeta;
+import org.apache.servicecomb.core.definition.SchemaMeta;
+import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice;
+import org.apache.servicecomb.swagger.SwaggerUtils;
+import org.apache.servicecomb.swagger.generator.core.SwaggerGenerator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import io.swagger.models.Swagger;
+
+@Component
+public class StaticSchemaFactory extends AbstractSchemaFactory<SchemaContext> {
+
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(StaticSchemaFactory.class);
+
+  public void loadSchema(MicroserviceMeta microserviceMeta, StaticMicroservice 
microservice) {
+    SchemaContext context = new SchemaContext();
+    context.setMicroserviceMeta(microserviceMeta);
+    // use microservice name as schemaId, since currently we only allow one 
schema per 3rd party microservice
+    context.setSchemaId(microserviceMeta.getShortName());
+    context.setProviderClass(microservice.getSchemaIntfCls());
+
+    getOrCreateSchema(context);
+  }
+
+  @Override
+  protected SchemaMeta createSchema(SchemaContext context) {
+    // generate schema according to producer interface
+    Swagger swagger;
+    SwaggerGenerator generator = generateSwagger(context);
+    swagger = generator.getSwagger();
+    String swaggerContent = SwaggerUtils.swaggerToString(swagger);
+    LOGGER.info("generate swagger for {}/{}/{}, swagger: {}",
+        context.getMicroserviceMeta().getAppId(),
+        context.getMicroserviceName(),
+        context.getSchemaId(),
+        swaggerContent);
+
+    // register swagger schema
+    return schemaLoader.registerSchema(context.getMicroserviceMeta(), 
context.getSchemaId(), swagger);
+  }
+}
diff --git 
a/core/src/test/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaTest.java
 
b/core/src/test/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaTest.java
new file mode 100644
index 000000000..a06f08701
--- /dev/null
+++ 
b/core/src/test/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.servicecomb.core.definition;
+
+import javax.xml.ws.Holder;
+
+import org.apache.servicecomb.core.CseContext;
+import org.apache.servicecomb.core.SCBEngine;
+import 
org.apache.servicecomb.core.definition.classloader.MicroserviceClassLoaderFactory;
+import org.apache.servicecomb.core.definition.loader.SchemaListenerManager;
+import org.apache.servicecomb.core.definition.schema.StaticSchemaFactory;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import mockit.Mock;
+import mockit.MockUp;
+
+public class StaticMicroserviceVersionMetaTest {
+
+  private static final String APP_ID_FROM_REGISTRY_UTIL = 
"appIdFromRegistryUtil";
+
+  @BeforeClass
+  public static void beforeClass() {
+    new MockUp<RegistryUtils>() {
+      @Mock
+      String getAppId() {
+        return APP_ID_FROM_REGISTRY_UTIL;
+      }
+    };
+  }
+
+  @Test
+  public void testConstruct() {
+    StaticMicroservice staticMicroservice = new StaticMicroservice();
+    String appId = "testAppId";
+    String serviceName = "testServiceName";
+    String version = "1.2.1";
+    staticMicroservice.setAppId(appId);
+    staticMicroservice.setServiceName(serviceName);
+    staticMicroservice.setVersion(version);
+
+    MicroserviceClassLoaderFactory classLoaderFactory = 
Mockito.mock(MicroserviceClassLoaderFactory.class);
+    ClassLoader classLoader = Mockito.mock(ClassLoader.class);
+    Mockito.when(classLoaderFactory.create(appId, serviceName, 
version)).thenReturn(classLoader);
+
+    Holder<Boolean> schemaLoaded = new Holder<>(false);
+    SCBEngine.getInstance().setStaticSchemaFactory(new 
MockUp<StaticSchemaFactory>() {
+      @Mock
+      void loadSchema(MicroserviceMeta microserviceMeta, StaticMicroservice 
microservice) {
+        Assert.assertSame(classLoader, microserviceMeta.getClassLoader());
+        Assert.assertSame(APP_ID_FROM_REGISTRY_UTIL, 
microserviceMeta.getAppId());
+        Assert.assertSame(serviceName, microserviceMeta.getName());
+        Assert.assertSame(serviceName, microserviceMeta.getShortName());
+        Assert.assertSame(staticMicroservice, microservice);
+        schemaLoaded.value = true;
+      }
+    }.getMockInstance());
+    Holder<Boolean> listenerNotified = new Holder<>(false);
+    CseContext.getInstance().setSchemaListenerManager(new 
MockUp<SchemaListenerManager>() {
+      @Mock
+      void notifySchemaListener(MicroserviceMeta... microserviceMetas) {
+        Assert.assertEquals(1, microserviceMetas.length);
+        MicroserviceMeta microserviceMeta = microserviceMetas[0];
+        Assert.assertEquals(serviceName, microserviceMeta.getShortName());
+        listenerNotified.value = true;
+      }
+    }.getMockInstance());
+
+    StaticMicroserviceVersionMeta staticMicroserviceVersionMeta = new 
StaticMicroserviceVersionMeta(staticMicroservice,
+        classLoaderFactory);
+
+    Assert.assertTrue(schemaLoaded.value);
+    Assert.assertTrue(listenerNotified.value);
+    Assert.assertSame(staticMicroservice, 
staticMicroserviceVersionMeta.getMicroservice());
+    Assert.assertEquals(serviceName, 
staticMicroserviceVersionMeta.getMicroserviceMeta().getName());
+  }
+}
\ No newline at end of file
diff --git 
a/core/src/test/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactoryTest.java
 
b/core/src/test/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactoryTest.java
new file mode 100644
index 000000000..2f254ae7c
--- /dev/null
+++ 
b/core/src/test/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactoryTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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.servicecomb.core.definition.schema;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.CompletableFuture;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import org.apache.servicecomb.core.definition.MicroserviceMeta;
+import org.apache.servicecomb.core.definition.OperationMeta;
+import org.apache.servicecomb.core.definition.SchemaMeta;
+import org.apache.servicecomb.core.definition.loader.SchemaLoader;
+import org.apache.servicecomb.core.unittest.UnitTestMeta;
+import org.apache.servicecomb.foundation.common.utils.ReflectUtils;
+import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice;
+import org.apache.servicecomb.swagger.SwaggerUtils;
+import 
org.apache.servicecomb.swagger.generator.core.CompositeSwaggerGeneratorContext;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class StaticSchemaFactoryTest {
+
+  private static final StaticSchemaFactory staticSchemaFactory = new 
StaticSchemaFactory();
+
+  private static final String APPLICATION_ID_KEY = "APPLICATION_ID";
+
+  private static final String APP_ID_VALUE = "appIdTest";
+
+  @BeforeClass
+  public static void beforeClass() {
+    System.setProperty(APPLICATION_ID_KEY, APP_ID_VALUE);
+    new UnitTestMeta();
+
+    CompositeSwaggerGeneratorContext compositeSwaggerGeneratorContext = new 
CompositeSwaggerGeneratorContext();
+    ReflectUtils.setField(staticSchemaFactory, 
"compositeSwaggerGeneratorContext", compositeSwaggerGeneratorContext);
+
+    SchemaLoader schemaLoader = new SchemaLoader();
+    ReflectUtils.setField(staticSchemaFactory, "schemaLoader", schemaLoader);
+  }
+
+  @AfterClass
+  public static void afterClass() {
+    TestProducerSchemaFactory.teardown();
+    System.clearProperty(APPLICATION_ID_KEY);
+  }
+
+  @Test
+  public void testLoadSchema() {
+    String serviceAndSchemaName = "3rdPartyService";
+    StaticMicroservice staticMicroservice = new StaticMicroservice();
+    staticMicroservice.setSchemaIntfCls(Test3rdPartyServiceIntf.class);
+    MicroserviceMeta microserviceMeta = new 
MicroserviceMeta(serviceAndSchemaName);
+    staticSchemaFactory.loadSchema(microserviceMeta, staticMicroservice);
+
+    SchemaMeta schemaMeta = 
microserviceMeta.findSchemaMeta(serviceAndSchemaName);
+    Assert.assertEquals(EXPECTED_SCHEMA_CONTENT,
+        SwaggerUtils.swaggerToString(schemaMeta.getSwagger()));
+
+    Assert.assertEquals(2, schemaMeta.getOperations().size());
+    OperationMeta operationMeta = schemaMeta.ensureFindOperation("add");
+    Assert.assertEquals("add", operationMeta.getOperationId());
+    Method swaggerProducerMethod = operationMeta.getMethod();
+    Class<?>[] parameterTypes = swaggerProducerMethod.getParameterTypes();
+    Assert.assertEquals(2, parameterTypes.length);
+    Assert.assertEquals(Integer.class, parameterTypes[0]);
+    Assert.assertEquals(Integer.class, parameterTypes[1]);
+    Assert.assertEquals(Integer.class, 
swaggerProducerMethod.getGenericReturnType());
+
+    operationMeta = schemaMeta.ensureFindOperation("addAsync");
+    Assert.assertEquals("addAsync", operationMeta.getOperationId());
+    swaggerProducerMethod = operationMeta.getMethod();
+    parameterTypes = swaggerProducerMethod.getParameterTypes();
+    Assert.assertEquals(2, parameterTypes.length);
+    Assert.assertEquals(Integer.class, parameterTypes[0]);
+    Assert.assertEquals(Integer.class, parameterTypes[1]);
+    // ensure reactive operation's return type is set correctly, not 
CompletableFuture<T>
+    Assert.assertEquals(Integer.class, 
swaggerProducerMethod.getGenericReturnType());
+  }
+
+  @Path("/3rdParty")
+  interface Test3rdPartyServiceIntf {
+
+    @Path("/add")
+    @GET
+    int add(@QueryParam("x") int x, @QueryParam("y") int y);
+
+    @Path("/addAsync")
+    @GET
+    CompletableFuture<Integer> addAsync(@QueryParam("x") int x, 
@QueryParam("y") int y);
+  }
+
+  private static final String EXPECTED_SCHEMA_CONTENT = "---\n"
+      + "swagger: \"2.0\"\n"
+      + "info:\n"
+      + "  version: \"1.0.0\"\n"
+      + "  title: \"swagger definition for 
org.apache.servicecomb.core.definition.schema.StaticSchemaFactoryTest$Test3rdPartyServiceIntf\"\n"
+      + "  x-java-interface: 
\"cse.gen.appIdTest._3rdPartyService._3rdPartyService.Test3rdPartyServiceIntfIntf\"\n"
+      + "basePath: \"/3rdParty\"\n"
+      + "consumes:\n"
+      + "- \"application/json\"\n"
+      + "produces:\n"
+      + "- \"application/json\"\n"
+      + "paths:\n"
+      + "  /add:\n"
+      + "    get:\n"
+      + "      operationId: \"add\"\n"
+      + "      parameters:\n"
+      + "      - name: \"x\"\n"
+      + "        in: \"query\"\n"
+      + "        required: false\n"
+      + "        type: \"integer\"\n"
+      + "        default: 0\n"
+      + "        format: \"int32\"\n"
+      + "      - name: \"y\"\n"
+      + "        in: \"query\"\n"
+      + "        required: false\n"
+      + "        type: \"integer\"\n"
+      + "        default: 0\n"
+      + "        format: \"int32\"\n"
+      + "      responses:\n"
+      + "        200:\n"
+      + "          description: \"response of 200\"\n"
+      + "          schema:\n"
+      + "            type: \"integer\"\n"
+      + "            format: \"int32\"\n"
+      + "  /addAsync:\n"
+      + "    get:\n"
+      + "      operationId: \"addAsync\"\n"
+      + "      parameters:\n"
+      + "      - name: \"x\"\n"
+      + "        in: \"query\"\n"
+      + "        required: false\n"
+      + "        type: \"integer\"\n"
+      + "        default: 0\n"
+      + "        format: \"int32\"\n"
+      + "      - name: \"y\"\n"
+      + "        in: \"query\"\n"
+      + "        required: false\n"
+      + "        type: \"integer\"\n"
+      + "        default: 0\n"
+      + "        format: \"int32\"\n"
+      + "      responses:\n"
+      + "        200:\n"
+      + "          description: \"response of 200\"\n"
+      + "          schema:\n"
+      + "            type: \"integer\"\n"
+      + "            format: \"int32\"\n";
+}
\ No newline at end of file
diff --git a/demo/demo-schema/src/main/resources/config/log4j.properties 
b/demo/demo-schema/src/main/resources/config/log4j.properties
index cad696acc..940109425 100644
--- a/demo/demo-schema/src/main/resources/config/log4j.properties
+++ b/demo/demo-schema/src/main/resources/config/log4j.properties
@@ -19,3 +19,5 @@ paas.logs.dir=../target/logs/
 paas.logs.file=cse.log
 
 log4j.rootLogger=INFO,paas,stdout
+log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF
+log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF
diff --git 
a/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-client/src/test/resources/logback-test.xml
 
b/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-client/src/test/resources/logback-test.xml
index 3f394068d..52d292541 100644
--- 
a/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-client/src/test/resources/logback-test.xml
+++ 
b/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-client/src/test/resources/logback-test.xml
@@ -18,4 +18,6 @@
 <configuration>
   <include resource="org/springframework/boot/logging/logback/base.xml"/>
   <logger name="org.springframework" level="ERROR"/>
+  <logger 
name="org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory" 
level="OFF"/>
+  <logger 
name="org.apache.servicecomb.core.definition.schema.StaticSchemaFactory" 
level="OFF"/>
 </configuration>
\ No newline at end of file
diff --git 
a/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-server/src/main/resources/logback-test.xml
 
b/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-server/src/main/resources/logback-test.xml
index 3f394068d..52d292541 100644
--- 
a/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-server/src/main/resources/logback-test.xml
+++ 
b/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-server/src/main/resources/logback-test.xml
@@ -18,4 +18,6 @@
 <configuration>
   <include resource="org/springframework/boot/logging/logback/base.xml"/>
   <logger name="org.springframework" level="ERROR"/>
+  <logger 
name="org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory" 
level="OFF"/>
+  <logger 
name="org.apache.servicecomb.core.definition.schema.StaticSchemaFactory" 
level="OFF"/>
 </configuration>
\ No newline at end of file
diff --git 
a/demo/demo-spring-boot-discovery/demo-spring-boot-zuul-proxy/src/test/resources/logback-test.xml
 
b/demo/demo-spring-boot-discovery/demo-spring-boot-zuul-proxy/src/test/resources/logback-test.xml
index 3f394068d..52d292541 100644
--- 
a/demo/demo-spring-boot-discovery/demo-spring-boot-zuul-proxy/src/test/resources/logback-test.xml
+++ 
b/demo/demo-spring-boot-discovery/demo-spring-boot-zuul-proxy/src/test/resources/logback-test.xml
@@ -18,4 +18,6 @@
 <configuration>
   <include resource="org/springframework/boot/logging/logback/base.xml"/>
   <logger name="org.springframework" level="ERROR"/>
+  <logger 
name="org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory" 
level="OFF"/>
+  <logger 
name="org.apache.servicecomb.core.definition.schema.StaticSchemaFactory" 
level="OFF"/>
 </configuration>
\ No newline at end of file
diff --git 
a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/resources/config/log4j.properties
 
b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/resources/config/log4j.properties
new file mode 100644
index 000000000..ff989feda
--- /dev/null
+++ 
b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/resources/config/log4j.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF
+log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF
diff --git 
a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/resources/config/log4j.properties
 
b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/resources/config/log4j.properties
new file mode 100644
index 000000000..ff989feda
--- /dev/null
+++ 
b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/resources/config/log4j.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF
+log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF
diff --git 
a/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-client/src/main/resources/config/log4j.properties
 
b/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-client/src/main/resources/config/log4j.properties
new file mode 100644
index 000000000..ff989feda
--- /dev/null
+++ 
b/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-client/src/main/resources/config/log4j.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF
+log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF
diff --git 
a/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-server/src/main/resources/config/log4j.properties
 
b/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-server/src/main/resources/config/log4j.properties
new file mode 100644
index 000000000..ff989feda
--- /dev/null
+++ 
b/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-server/src/main/resources/config/log4j.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF
+log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF
diff --git 
a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/config/log4j.properties
 
b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/config/log4j.properties
new file mode 100644
index 000000000..ff989feda
--- /dev/null
+++ 
b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/config/log4j.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF
+log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF
diff --git 
a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/config/log4j.properties
 
b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/config/log4j.properties
new file mode 100644
index 000000000..ff989feda
--- /dev/null
+++ 
b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/config/log4j.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF
+log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF
diff --git 
a/demo/demo-springmvc/springmvc-client/src/main/resources/config/log4j.properties
 
b/demo/demo-springmvc/springmvc-client/src/main/resources/config/log4j.properties
new file mode 100644
index 000000000..ff989feda
--- /dev/null
+++ 
b/demo/demo-springmvc/springmvc-client/src/main/resources/config/log4j.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF
+log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF
diff --git 
a/demo/demo-springmvc/springmvc-server/src/main/resources/config/log4j.properties
 
b/demo/demo-springmvc/springmvc-server/src/main/resources/config/log4j.properties
new file mode 100644
index 000000000..ff989feda
--- /dev/null
+++ 
b/demo/demo-springmvc/springmvc-server/src/main/resources/config/log4j.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF
+log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF
diff --git 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
index 12a59f061..32dc0c698 100644
--- 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
+++ 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
@@ -34,6 +34,7 @@
 import org.apache.servicecomb.it.testcase.TestRestServerConfigEdge;
 import org.apache.servicecomb.it.testcase.TestTrace;
 import org.apache.servicecomb.it.testcase.TestTraceEdge;
+import org.apache.servicecomb.it.testcase.thirdparty.Test3rdPartyInvocation;
 
 public class ConsumerMain {
   private static ResultPrinter resultPrinter = new ResultPrinter();
@@ -132,6 +133,7 @@ private static void testStandalone() throws Throwable {
     ITJUnitUtils.run(TestRestServerConfigEdge.class);
 
     ITJUnitUtils.run(TestRequestBodySpringMvcSchema.class);
+    ITJUnitUtils.run(Test3rdPartyInvocation.class);
 
     ITJUnitUtils.getParents().pop();
     deploys.getBaseProducer().stop();
diff --git 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java
 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java
index b291692bf..8cd6e5463 100644
--- 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java
+++ 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java
@@ -47,7 +47,7 @@ public void query(@ApiParam(value = "desc of query param",
       readOnly = true,
       allowEmptyValue = true,
       name = "inputEx",
-      example = "example",
+      example = "10",
       collectionFormat = "fmt") int input) {
 
   }
diff --git 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java
 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java
index 317874246..f3e120cd6 100644
--- 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java
+++ 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java
@@ -97,7 +97,7 @@ public void springmvcQuery() {
     Assert.assertTrue(parameter.isReadOnly());
     Assert.assertTrue(parameter.getAllowEmptyValue());
     Assert.assertEquals("inputEx", parameter.getName());
-    Assert.assertEquals("example", ((QueryParameter) parameter).getExample());
+    Assert.assertEquals(10L, ((QueryParameter) parameter).getExample());
     Assert.assertEquals("fmt", ((QueryParameter) 
parameter).getCollectionFormat());
   }
 
diff --git 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/thirdparty/Test3rdPartyInvocation.java
 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/thirdparty/Test3rdPartyInvocation.java
new file mode 100644
index 000000000..370910621
--- /dev/null
+++ 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/thirdparty/Test3rdPartyInvocation.java
@@ -0,0 +1,246 @@
+/*
+ * 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.servicecomb.it.testcase.thirdparty;
+
+import java.util.Collections;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.xml.ws.Holder;
+
+import org.apache.servicecomb.it.extend.engine.GateRestTemplate;
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder;
+import 
org.apache.servicecomb.provider.springmvc.reference.async.CseAsyncRestTemplate;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.concurrent.ListenableFuture;
+import org.springframework.web.client.RestTemplate;
+
+public class Test3rdPartyInvocation {
+
+  private static final String THIRD_PARTY_MICROSERVICE_NAME = 
"3rdPartyDataTypeJaxrs";
+
+  private static final String ASYNC_THIRD_PARTY_MICROSERVICE_NAME = 
THIRD_PARTY_MICROSERVICE_NAME + "Async";
+
+  // to get endpoint from urlPrefix
+  static GateRestTemplate rt = new GateRestTemplate("it-edge", "it-producer", 
"dataTypeJaxrs");
+
+  private static DataTypeJaxrsSchemaIntf dataTypeJaxrsSchema;
+
+  private static DataTypeJaxrsSchemaAsyncIntf dataTypeJaxrsSchemaAsync;
+
+  @BeforeClass
+  public static void beforeClass() {
+    String urlPrefix = rt.getUrlPrefix();
+    int beginIndex = urlPrefix.indexOf("//");
+    int endIndex = urlPrefix.indexOf("/", beginIndex + 3);
+    String endpoint = "rest:" + urlPrefix.substring(beginIndex, endIndex);
+    RegistryUtils.getServiceRegistry()
+        .registerMicroserviceMappingByEndpoints(
+            THIRD_PARTY_MICROSERVICE_NAME, "1.2.1",
+            Collections.singletonList(endpoint),
+            DataTypeJaxrsSchemaIntf.class);
+
+    MicroserviceInstance instance = new MicroserviceInstance();
+    instance.setEndpoints(Collections.singletonList(endpoint));
+    RegistryUtils.getServiceRegistry()
+        .registerMicroserviceMapping(
+            ASYNC_THIRD_PARTY_MICROSERVICE_NAME, "1.1.1",
+            Collections.singletonList(instance),
+            DataTypeJaxrsSchemaAsyncIntf.class
+        );
+
+    dataTypeJaxrsSchema = Invoker.createProxy(
+        THIRD_PARTY_MICROSERVICE_NAME, THIRD_PARTY_MICROSERVICE_NAME, 
DataTypeJaxrsSchemaIntf.class);
+    dataTypeJaxrsSchemaAsync = Invoker.createProxy(
+        ASYNC_THIRD_PARTY_MICROSERVICE_NAME, 
ASYNC_THIRD_PARTY_MICROSERVICE_NAME, DataTypeJaxrsSchemaAsyncIntf.class);
+  }
+
+  @Test
+  public void testSyncInvoke_RPC() {
+    Assert.assertEquals(1, dataTypeJaxrsSchema.intPath(1));
+    Assert.assertEquals(2, dataTypeJaxrsSchema.intQuery(2));
+    Assert.assertEquals(3, dataTypeJaxrsSchema.intHeader(3));
+    Assert.assertEquals(4, dataTypeJaxrsSchema.intCookie(4));
+    Assert.assertEquals(5, dataTypeJaxrsSchema.intForm(5));
+    Assert.assertEquals(6, dataTypeJaxrsSchema.intBody(6));
+    Assert.assertEquals(7, dataTypeJaxrsSchema.add(3, 4));
+    Assert.assertEquals("abc", dataTypeJaxrsSchema.stringPath("abc"));
+    Assert.assertEquals("def", dataTypeJaxrsSchema.stringQuery("def"));
+    Assert.assertEquals("ghi", dataTypeJaxrsSchema.stringHeader("ghi"));
+    Assert.assertEquals("jkl", dataTypeJaxrsSchema.stringCookie("jkl"));
+    Assert.assertEquals("mn", dataTypeJaxrsSchema.stringForm("mn"));
+    Assert.assertEquals("opq", dataTypeJaxrsSchema.stringBody("opq"));
+    Assert.assertEquals("uvwxyz", dataTypeJaxrsSchema.stringConcat("uvw", 
"xyz"));
+  }
+
+  @Test
+  public void testAsyncInvoke_RPC() throws ExecutionException, 
InterruptedException {
+    Holder<Boolean> addChecked = new Holder<>(false);
+    dataTypeJaxrsSchemaAsync.add(5, 6).whenComplete((result, t) -> {
+      Assert.assertEquals(11, result.intValue());
+      Assert.assertNull(t);
+      addChecked.value = true;
+    }).get();
+    Assert.assertTrue(addChecked.value);
+
+    Holder<Boolean> postStringChecked = new Holder<>(false);
+    dataTypeJaxrsSchemaAsync.stringBody("abc").whenComplete((result, t) -> {
+      Assert.assertEquals("abc", result);
+      Assert.assertNull(t);
+      postStringChecked.value = true;
+    }).get();
+    Assert.assertTrue(postStringChecked.value);
+
+    Holder<Boolean> concatChecked = new Holder<>(false);
+    dataTypeJaxrsSchemaAsync.stringConcat("uvw", "xyz").whenComplete((result, 
t) -> {
+      Assert.assertEquals("uvwxyz", result);
+      Assert.assertNull(t);
+      concatChecked.value = true;
+    }).get();
+    Assert.assertTrue(concatChecked.value);
+  }
+
+  @Test
+  public void testSyncInvoke_RestTemplate() {
+    RestTemplate restTemplate = RestTemplateBuilder.create();
+    ResponseEntity<Integer> responseEntity = restTemplate
+        .getForEntity(
+            "cse://" + THIRD_PARTY_MICROSERVICE_NAME + 
"/rest/it-producer/v1/dataTypeJaxrs/add?num1=11&num2=22",
+            int.class);
+    Assert.assertEquals(200, responseEntity.getStatusCodeValue());
+    Assert.assertEquals(33, responseEntity.getBody().intValue());
+
+    ResponseEntity<String> stringBodyResponse = restTemplate
+        .exchange("cse://" + THIRD_PARTY_MICROSERVICE_NAME + 
"/rest/it-producer/v1/dataTypeJaxrs/stringBody",
+            HttpMethod.POST,
+            new HttpEntity<>("abc"), String.class);
+    Assert.assertEquals(200, stringBodyResponse.getStatusCodeValue());
+    Assert.assertEquals("abc", stringBodyResponse.getBody());
+  }
+
+  @Test
+  public void testAsyncInvoke_RestTemplate() throws ExecutionException, 
InterruptedException {
+    CseAsyncRestTemplate cseAsyncRestTemplate = new CseAsyncRestTemplate();
+    ListenableFuture<ResponseEntity<Integer>> responseFuture = 
cseAsyncRestTemplate
+        .getForEntity(
+            "cse://" + ASYNC_THIRD_PARTY_MICROSERVICE_NAME + 
"/rest/it-producer/v1/dataTypeJaxrs/add?num1=11&num2=22",
+            Integer.class);
+    ResponseEntity<Integer> responseEntity = responseFuture.get();
+    Assert.assertEquals(200, responseEntity.getStatusCodeValue());
+    Assert.assertEquals(33, responseEntity.getBody().intValue());
+
+    ListenableFuture<ResponseEntity<String>> stringBodyFuture = 
cseAsyncRestTemplate
+        .exchange("cse://" + ASYNC_THIRD_PARTY_MICROSERVICE_NAME + 
"/rest/it-producer/v1/dataTypeJaxrs/stringBody",
+            HttpMethod.POST,
+            new HttpEntity<>("abc"), String.class);
+    ResponseEntity<String> stringBodyResponse = stringBodyFuture.get();
+    Assert.assertEquals(200, stringBodyResponse.getStatusCodeValue());
+    Assert.assertEquals("abc", stringBodyResponse.getBody());
+  }
+
+  @Path("/rest/it-producer/v1/dataTypeJaxrs")
+  interface DataTypeJaxrsSchemaIntf {
+    @Path("intPath/{input}")
+    @GET
+    int intPath(@PathParam("input") int input);
+
+    @Path("intQuery")
+    @GET
+    int intQuery(@QueryParam("input") int input);
+
+    @Path("intHeader")
+    @GET
+    int intHeader(@HeaderParam("input") int input);
+
+    @Path("intCookie")
+    @GET
+    int intCookie(@CookieParam("input") int input);
+
+    @Path("intForm")
+    @POST
+    int intForm(@FormParam("input") int input);
+
+    @Path("intBody")
+    @POST
+    int intBody(int input);
+
+    @Path("add")
+    @GET
+    int add(@QueryParam("num1") int num1, @QueryParam("num2") int num2);
+
+    //strinnum1
+    @Path("stringPath/{input}")
+    @GET
+    String stringPath(@PathParam("input") String input);
+
+    @Path("stringQuery")
+    @GET
+    String stringQuery(@QueryParam("input") String input);
+
+    @Path("stringHeader")
+    @GET
+    String stringHeader(@HeaderParam("input") String input);
+
+    @Path("stringCookie")
+    @GET
+    String stringCookie(@CookieParam("input") String input);
+
+    @Path("stringForm")
+    @POST
+    String stringForm(@FormParam("input") String input);
+
+    @Path("stringBody")
+    @POST
+    String stringBody(String input);
+
+    @Path("stringConcat")
+    @GET
+    String stringConcat(@QueryParam("str1") String str1, @QueryParam("str2") 
String str2);
+  }
+
+  @Path("/rest/it-producer/v1/dataTypeJaxrs")
+  interface DataTypeJaxrsSchemaAsyncIntf {
+    @Path("add")
+    @GET
+    CompletableFuture<Integer> add(@QueryParam("num1") int num1, 
@QueryParam("num2") int num2);
+
+    @Path("stringBody")
+    @POST
+    CompletableFuture<String> stringBody(String input);
+
+    @Path("stringConcat")
+    @GET
+    CompletableFuture<String> stringConcat(@QueryParam("str1") String str1, 
@QueryParam("str2") String str2);
+  }
+}
diff --git 
a/integration-tests/spring-zuul-tracing-tests/src/test/resources/log4j.properties
 
b/integration-tests/spring-zuul-tracing-tests/src/test/resources/log4j.properties
index e5addd943..a25e46fe6 100644
--- 
a/integration-tests/spring-zuul-tracing-tests/src/test/resources/log4j.properties
+++ 
b/integration-tests/spring-zuul-tracing-tests/src/test/resources/log4j.properties
@@ -21,3 +21,5 @@ log4j.rootLogger=WARN, stdout
 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
 log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} 
- %m%n
+log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF
+log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF
diff --git 
a/integration-tests/tracing-tests/src/test/resources/log4j.properties 
b/integration-tests/tracing-tests/src/test/resources/log4j.properties
new file mode 100644
index 000000000..ff989feda
--- /dev/null
+++ b/integration-tests/tracing-tests/src/test/resources/log4j.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF
+log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/ServiceRegistry.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/ServiceRegistry.java
index a8cf7854b..ead2ccc31 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/ServiceRegistry.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/ServiceRegistry.java
@@ -59,4 +59,38 @@ MicroserviceInstances findServiceInstances(String appId, 
String microserviceName
   Microservice getRemoteMicroservice(String microserviceId);
 
   Features getFeatures();
+
+  /**
+   * <p>
+   * Register a third party service if not registered before, and set it's 
instances into
+   * {@linkplain 
org.apache.servicecomb.serviceregistry.consumer.StaticMicroserviceVersions 
StaticMicroserviceVersions}.
+   * </p>
+   * <p>
+   * The registered third party service has the same {@code appId} and {@code 
environment} as this microservice instance has,
+   * and there is only one schema represented by {@code schemaIntfCls}, whose 
name is the same as {@code microserviceName}.
+   * </p>
+   * <em>
+   *   This method is for initializing 3rd party service endpoint config.
+   *   i.e. If this service has not been registered before, this service will 
be registered and the instances will be set;
+   *   otherwise, NOTHING will happen.
+   * </em>
+   *
+   * @param microserviceName name of the 3rd party service, and this param 
also specifies the schemaId
+   * @param version version of this 3rd party service
+   * @param instances the instances of this 3rd party service. Users only need 
to specify the endpoint information, other
+   * necessary information will be generate and set in the implementation of 
this method.
+   * @param schemaIntfCls the producer interface of the service. This 
interface is used to generate swagger schema and
+   * can also be used for the proxy interface of RPC style invocation.
+   */
+  void registerMicroserviceMapping(String microserviceName, String version, 
List<MicroserviceInstance> instances,
+      Class<?> schemaIntfCls);
+
+  /**
+   * @see #registerMicroserviceMapping(String, String, List, Class)
+   * @param endpoints the endpoints of 3rd party service. Each of endpoints 
will be treated as a separated instance.
+   * Format of the endpoints is the same as the endpoints that ServiceComb 
microservices register in service-center,
+   * like {@code rest://127.0.0.1:8080}
+   */
+  void registerMicroserviceMappingByEndpoints(String microserviceName, String 
version,
+      List<String> endpoints, Class<?> schemaIntfCls);
 }
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/api/registry/StaticMicroservice.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/api/registry/StaticMicroservice.java
new file mode 100644
index 000000000..60d5900df
--- /dev/null
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/api/registry/StaticMicroservice.java
@@ -0,0 +1,30 @@
+/*
+ * 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.servicecomb.serviceregistry.api.registry;
+
+public class StaticMicroservice extends Microservice {
+  private Class<?> schemaIntfCls;
+
+  public Class<?> getSchemaIntfCls() {
+    return schemaIntfCls;
+  }
+
+  public void setSchemaIntfCls(Class<?> schemaIntfCls) {
+    this.schemaIntfCls = schemaIntfCls;
+  }
+}
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/config/ServiceRegistryConfig.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/config/ServiceRegistryConfig.java
index 23824a800..9832735b9 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/config/ServiceRegistryConfig.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/config/ServiceRegistryConfig.java
@@ -86,16 +86,21 @@
 
   public static final String PROXY_PASSWD = PROXY_PRE_NAME + "passwd";
 
-
   private ServiceRegistryConfig() {
 
   }
 
-
   public String getMicroserviceVersionFactory() {
     return 
DynamicPropertyFactory.getInstance().getStringProperty(MICROSERVICE_VERSION_FACTORY,
 null).get();
   }
 
+  /**
+   * Currently we don't provide configuration about {@link 
org.apache.servicecomb.serviceregistry.consumer.StaticMicroserviceVersionFactory}
+   */
+  public String getStaticMicroserviceVersionFactory() {
+    return 
"org.apache.servicecomb.core.definition.StaticMicroserviceVersionMetaFactory";
+  }
+
   public HttpVersion getHttpVersion() {
     DynamicStringProperty property =
         DynamicPropertyFactory.getInstance()
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java
index 7cc45e221..4eef10f6d 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java
@@ -20,10 +20,16 @@
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
+import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.eventbus.EventBus;
 
 public class AppManager {
+
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(AppManager.class);
+
   private EventBus eventBus;
 
   private MicroserviceVersionFactory microserviceVersionFactory = new 
DefaultMicroserviceVersionFactory();
@@ -31,6 +37,8 @@
   // key: appId
   private Map<String, MicroserviceManager> apps = new ConcurrentHashMapEx<>();
 
+  private volatile StaticMicroserviceVersionFactory 
staticMicroserviceVersionFactory;
+
   public AppManager(EventBus eventBus) {
     this.eventBus = eventBus;
   }
@@ -67,4 +75,33 @@ public MicroserviceVersions 
getOrCreateMicroserviceVersions(String appId, String
     MicroserviceManager microserviceManager = 
getOrCreateMicroserviceManager(appId);
     return 
microserviceManager.getOrCreateMicroserviceVersions(microserviceName);
   }
+
+  public StaticMicroserviceVersionFactory 
getStaticMicroserviceVersionFactory() {
+    if (null == staticMicroserviceVersionFactory) {
+      synchronized (this) {
+        if (null == staticMicroserviceVersionFactory) {
+          loadStaticMicroserviceVersionFactory();
+        }
+      }
+    }
+    return staticMicroserviceVersionFactory;
+  }
+
+  public void 
setStaticMicroserviceVersionFactory(StaticMicroserviceVersionFactory 
staticMicroserviceVersionFactory) {
+    this.staticMicroserviceVersionFactory = staticMicroserviceVersionFactory;
+  }
+
+  private void loadStaticMicroserviceVersionFactory() {
+    String staticMicroserviceVersionFactoryClass = 
ServiceRegistryConfig.INSTANCE
+        .getStaticMicroserviceVersionFactory();
+    try {
+      staticMicroserviceVersionFactory = (StaticMicroserviceVersionFactory) 
Class
+          .forName(staticMicroserviceVersionFactoryClass).newInstance();
+    } catch (InstantiationException | IllegalAccessException | 
ClassNotFoundException e) {
+      LOGGER.info("unable to load StaticMicroserviceVersionFactory", e);
+      // interrupt this loading process because this error cannot be covered 
by us.
+      throw new IllegalStateException("unable to load 
StaticMicroserviceVersionFactory", e);
+    }
+    LOGGER.info("staticMicroserviceVersionFactory is {}.", 
staticMicroserviceVersionFactoryClass);
+  }
 }
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersion.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersion.java
index 68ce8c8eb..b956a664e 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersion.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersion.java
@@ -35,6 +35,11 @@ public MicroserviceVersion(String microserviceId) {
     this.version = new Version(microservice.getVersion());
   }
 
+  public MicroserviceVersion(Microservice microservice) {
+    this.microservice = microservice;
+    this.version = new Version(microservice.getVersion());
+  }
+
   public Microservice getMicroservice() {
     return microservice;
   }
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
index ab4f479d0..e85c51311 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
@@ -43,7 +43,7 @@
 public class MicroserviceVersions {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(MicroserviceVersions.class);
 
-  private AppManager appManager;
+  AppManager appManager;
 
   private String appId;
 
@@ -58,13 +58,13 @@
   // in the future:
   //  pulledInstances means all instance
   //  instances means available instance
-  private List<MicroserviceInstance> instances;
+  List<MicroserviceInstance> instances;
 
   // key is service id
-  private Map<String, MicroserviceVersion> versions = new 
ConcurrentHashMapEx<>();
+  Map<String, MicroserviceVersion> versions = new ConcurrentHashMapEx<>();
 
   // key is version rule
-  private Map<String, MicroserviceVersionRule> versionRules = new 
ConcurrentHashMapEx<>();
+  Map<String, MicroserviceVersionRule> versionRules = new 
ConcurrentHashMapEx<>();
 
   // process pulled instances and create versionRule must be protected by lock
   // otherwise maybe lost instance or version in versionRule
@@ -74,7 +74,7 @@
   // only pendingPullCount is 0, then do a real pull 
   private AtomicInteger pendingPullCount = new AtomicInteger();
 
-  private boolean validated = false;
+  boolean validated = false;
 
   public MicroserviceVersions(AppManager appManager, String appId, String 
microserviceName) {
     this.appManager = appManager;
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionFactory.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionFactory.java
new file mode 100644
index 000000000..d2fb60d69
--- /dev/null
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionFactory.java
@@ -0,0 +1,24 @@
+/*
+ * 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.servicecomb.serviceregistry.consumer;
+
+import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice;
+
+public interface StaticMicroserviceVersionFactory {
+  MicroserviceVersion create(StaticMicroservice microservice);
+}
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersions.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersions.java
new file mode 100644
index 000000000..286ff95bb
--- /dev/null
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersions.java
@@ -0,0 +1,99 @@
+/*
+ * 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.servicecomb.serviceregistry.consumer;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice;
+import org.apache.servicecomb.serviceregistry.version.Version;
+
+public class StaticMicroserviceVersions extends MicroserviceVersions {
+
+  private Class<?> schemaIntfCls;
+
+  private String environment;
+
+  public StaticMicroserviceVersions(AppManager appManager, String appId, 
String microserviceName,
+      Class<?> schemaIntfCls) {
+    super(appManager, appId, microserviceName);
+
+    validated = true;
+    this.schemaIntfCls = schemaIntfCls;
+    this.environment = RegistryUtils.getMicroservice().getEnvironment();
+  }
+
+  @Override
+  public void pullInstances() {
+    // instance information is stored locally, do not pull from sc
+  }
+
+  public void addInstances(String version, List<MicroserviceInstance> 
addedInstances) {
+    Version parsedVersion = new Version(version);
+    String serviceId = computeServiceId(parsedVersion);
+
+    for (MicroserviceInstance instance : addedInstances) {
+      instance.setServiceId(serviceId);
+      instance.setInstanceId(serviceId + "-" + UUID.randomUUID());
+    }
+
+    mergeInstances(addedInstances);
+
+    // ensure microserviceVersion exists
+    versions.computeIfAbsent(serviceId, microserviceId -> {
+      StaticMicroservice microservice = createMicroservice(parsedVersion, 
serviceId);
+      MicroserviceVersion microserviceVersion = 
appManager.getStaticMicroserviceVersionFactory().create(microservice);
+      for (MicroserviceVersionRule microserviceVersionRule : 
versionRules.values()) {
+        microserviceVersionRule.addMicroserviceVersion(microserviceVersion);
+      }
+      return microserviceVersion;
+    });
+
+    for (MicroserviceVersionRule microserviceVersionRule : 
versionRules.values()) {
+      microserviceVersionRule.setInstances(this.instances);
+    }
+  }
+
+  private void mergeInstances(List<MicroserviceInstance> instances) {
+    if (null == this.instances) {
+      this.instances = new ArrayList<>(instances.size());
+    }
+    this.instances.addAll(instances);
+  }
+
+  private StaticMicroservice createMicroservice(Version parsedVersion, String 
serviceId) {
+    StaticMicroservice microservice = new StaticMicroservice();
+    microservice.setAppId(this.getAppId());
+    microservice.setServiceId(serviceId);
+    microservice.setServiceName(this.getMicroserviceName());
+    microservice.setVersion(parsedVersion.getVersion());
+    
microservice.setEnvironment(RegistryUtils.getMicroservice().getEnvironment());
+    microservice.setSchemaIntfCls(this.schemaIntfCls);
+    return microservice;
+  }
+
+  private String computeServiceId(Version parsedVersion) {
+    return this.getAppId() + "-"
+        + this.environment + "-"
+        + this.getMicroserviceName() + "-"
+        + parsedVersion.getVersion();
+  }
+}
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java
index 6e880faa2..d266b71da 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java
@@ -19,12 +19,15 @@
 import static 
org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_DEFAULT_REGISTER_BY;
 import static 
org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_FRAMEWORK_DEFAULT_NAME;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import org.apache.servicecomb.serviceregistry.Features;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
 import org.apache.servicecomb.serviceregistry.ServiceRegistry;
 import org.apache.servicecomb.serviceregistry.api.Const;
 import org.apache.servicecomb.serviceregistry.api.registry.BasePath;
@@ -40,7 +43,9 @@
 import 
org.apache.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig;
 import org.apache.servicecomb.serviceregistry.consumer.AppManager;
+import org.apache.servicecomb.serviceregistry.consumer.MicroserviceManager;
 import 
org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersionFactory;
+import 
org.apache.servicecomb.serviceregistry.consumer.StaticMicroserviceVersions;
 import 
org.apache.servicecomb.serviceregistry.definition.MicroserviceDefinition;
 import 
org.apache.servicecomb.serviceregistry.task.MicroserviceServiceCenterTask;
 import org.apache.servicecomb.serviceregistry.task.ServiceCenterTask;
@@ -181,7 +186,6 @@ private void loadFrameworkVersions() {
     microservice.setRegisterBy(CONFIG_DEFAULT_REGISTER_BY);
   }
 
-
   private void loadStaticConfiguration() {
     // TODO 如果yaml定义了paths规则属性,替换默认值,现需要DynamicPropertyFactory支持数组获取
     List<BasePath> paths = microservice.getPaths();
@@ -303,4 +307,32 @@ public void destroy() {
     eventBus.post(new ShutdownEvent());
     unregisterInstance();
   }
+
+  @Override
+  public void registerMicroserviceMapping(String microserviceName, String 
version,
+      List<MicroserviceInstance> instances, Class<?> schemaIntfCls) {
+    String app = RegistryUtils.getAppId();
+    MicroserviceManager microserviceManager = 
appManager.getOrCreateMicroserviceManager(app);
+    microserviceManager.getVersionsByName()
+        .computeIfAbsent(microserviceName,
+            svcName -> {
+              StaticMicroserviceVersions microserviceVersions = new 
StaticMicroserviceVersions(this.appManager,
+                  app, microserviceName, schemaIntfCls);
+              microserviceVersions.addInstances(version, instances);
+              return microserviceVersions;
+            });
+  }
+
+  @Override
+  public void registerMicroserviceMappingByEndpoints(String microserviceName, 
String version,
+      List<String> endpoints, Class<?> schemaIntfCls) {
+    ArrayList<MicroserviceInstance> microserviceInstances = new ArrayList<>();
+    for (String endpoint : endpoints) {
+      MicroserviceInstance instance = new MicroserviceInstance();
+      instance.setEndpoints(Collections.singletonList(endpoint));
+      microserviceInstances.add(instance);
+    }
+
+    registerMicroserviceMapping(microserviceName, version, 
microserviceInstances, schemaIntfCls);
+  }
 }
diff --git 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionsTest.java
 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionsTest.java
new file mode 100644
index 000000000..ca3c3b3a5
--- /dev/null
+++ 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionsTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.servicecomb.serviceregistry.consumer;
+
+import java.util.Collections;
+
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.serviceregistry.api.registry.Microservice;
+import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice;
+import org.apache.servicecomb.serviceregistry.client.ServiceRegistryClient;
+import 
org.apache.servicecomb.serviceregistry.definition.MicroserviceDefinition;
+import org.apache.servicecomb.serviceregistry.registry.AbstractServiceRegistry;
+import org.apache.servicecomb.serviceregistry.version.Version;
+import org.apache.servicecomb.serviceregistry.version.VersionUtils;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.google.common.eventbus.EventBus;
+
+import mockit.Mock;
+import mockit.MockUp;
+
+public class StaticMicroserviceVersionsTest {
+
+  private static final String APP_ID = "testAppId";
+
+  private static final String THIS_SERVICE = "thisService";
+
+  private static final String MICROSERVICE_NAME = "3rdPartyService";
+
+  private static final String ENVIRONMENT = "production";
+
+  private static final String SERVICE_ID_PREFIX = APP_ID + "-" + ENVIRONMENT + 
"-" + MICROSERVICE_NAME + "-";
+
+  @BeforeClass
+  public static void beforeClass() {
+    RegistryUtils.setServiceRegistry(new AbstractServiceRegistry(null, null,
+        MicroserviceDefinition.create(APP_ID, THIS_SERVICE)) {
+      @Override
+      protected ServiceRegistryClient createServiceRegistryClient() {
+        return null;
+      }
+    });
+    RegistryUtils.getMicroservice().setEnvironment(ENVIRONMENT);
+  }
+
+  @Test
+  public void addInstanceBasic() {
+    StaticMicroserviceVersions staticMicroserviceVersions = 
createStaticMicroserviceVersions();
+
+    MicroserviceInstance instance = new MicroserviceInstance();
+    String serviceVersion = "1.2.1";
+    staticMicroserviceVersions.addInstances(serviceVersion, 
Collections.singletonList(instance));
+
+    MicroserviceVersionRule versionRule = 
staticMicroserviceVersions.getOrCreateMicroserviceVersionRule(serviceVersion);
+    MicroserviceVersion latestMicroserviceVersion = 
versionRule.getLatestMicroserviceVersion();
+    Assert.assertEquals(new Version(serviceVersion), 
latestMicroserviceVersion.getVersion());
+    Microservice latestMicroservice = 
latestMicroserviceVersion.getMicroservice();
+    Assert.assertEquals(APP_ID, latestMicroservice.getAppId());
+    Assert.assertEquals(SERVICE_ID_PREFIX + serviceVersion, 
latestMicroservice.getServiceId());
+    Assert.assertEquals(MICROSERVICE_NAME, 
latestMicroservice.getServiceName());
+    Assert.assertEquals(serviceVersion, latestMicroservice.getVersion());
+    Assert.assertEquals(ENVIRONMENT, latestMicroservice.getEnvironment());
+    Assert.assertEquals(TestServiceIntf.class, ((StaticMicroservice) 
latestMicroservice).getSchemaIntfCls());
+    Assert.assertEquals(1, versionRule.getInstances().size());
+    Assert.assertSame(instance, 
versionRule.getInstances().get(instance.getInstanceId()));
+    Assert.assertEquals(SERVICE_ID_PREFIX + serviceVersion, 
instance.getServiceId());
+    Assert.assertTrue(instance.getInstanceId().startsWith(SERVICE_ID_PREFIX + 
serviceVersion + "-"));
+  }
+
+  @Test
+  public void addInstancesAndGetVersionRuleMultiTimes() {
+    StaticMicroserviceVersions staticMicroserviceVersions = 
createStaticMicroserviceVersions();
+
+    // add instance1 with version 1.1.0
+    MicroserviceInstance instance1 = new MicroserviceInstance();
+    staticMicroserviceVersions.addInstances("1.1.0", 
Collections.singletonList(instance1));
+
+    MicroserviceVersionRule versionRule = 
staticMicroserviceVersions.getOrCreateMicroserviceVersionRule("0.0.0+");
+    MicroserviceVersion latestMicroserviceVersion = 
versionRule.getLatestMicroserviceVersion();
+    Assert.assertEquals(new Version("1.1.0"), 
latestMicroserviceVersion.getVersion());
+    Assert.assertEquals(1, versionRule.getInstances().size());
+    Assert.assertSame(instance1, 
versionRule.getInstances().get(instance1.getInstanceId()));
+
+    // add instance2 with version 1.1.1
+    MicroserviceInstance instance2 = new MicroserviceInstance();
+    staticMicroserviceVersions.addInstances("1.1.1", 
Collections.singletonList(instance2));
+
+    versionRule = 
staticMicroserviceVersions.getOrCreateMicroserviceVersionRule("0.0.0+");
+    latestMicroserviceVersion = versionRule.getLatestMicroserviceVersion();
+    Assert.assertEquals(new Version("1.1.1"), 
latestMicroserviceVersion.getVersion());
+    Assert.assertEquals(2, versionRule.getInstances().size());
+    Assert.assertSame(instance1, 
versionRule.getInstances().get(instance1.getInstanceId()));
+    Assert.assertSame(instance2, 
versionRule.getInstances().get(instance2.getInstanceId()));
+
+    // add instance3 with version 0.1.0
+    MicroserviceInstance instance3 = new MicroserviceInstance();
+    staticMicroserviceVersions.addInstances("0.1.0", 
Collections.singletonList(instance3));
+
+    versionRule = 
staticMicroserviceVersions.getOrCreateMicroserviceVersionRule("0.0.0+");
+    latestMicroserviceVersion = versionRule.getLatestMicroserviceVersion();
+    Assert.assertEquals(new Version("1.1.1"), 
latestMicroserviceVersion.getVersion());
+    Assert.assertEquals(3, versionRule.getInstances().size());
+    Assert.assertSame(instance1, 
versionRule.getInstances().get(instance1.getInstanceId()));
+    Assert.assertSame(instance2, 
versionRule.getInstances().get(instance2.getInstanceId()));
+    Assert.assertSame(instance3, 
versionRule.getInstances().get(instance3.getInstanceId()));
+
+    // instance3 should be filtered out
+    versionRule = 
staticMicroserviceVersions.getOrCreateMicroserviceVersionRule("1.0.0+");
+    latestMicroserviceVersion = versionRule.getLatestMicroserviceVersion();
+    Assert.assertEquals(new Version("1.1.1"), 
latestMicroserviceVersion.getVersion());
+    Assert.assertEquals(2, versionRule.getInstances().size());
+    Assert.assertSame(instance1, 
versionRule.getInstances().get(instance1.getInstanceId()));
+    Assert.assertSame(instance2, 
versionRule.getInstances().get(instance2.getInstanceId()));
+    
Assert.assertNull(versionRule.getInstances().get(instance3.getInstanceId()));
+  }
+
+  private StaticMicroserviceVersions createStaticMicroserviceVersions() {
+    EventBus eventBus = new EventBus();
+    AppManager appManager = new AppManager(eventBus);
+    appManager.setStaticMicroserviceVersionFactory(microservice -> new 
MockUp<MicroserviceVersion>() {
+      @Mock
+      public Version getVersion() {
+        return VersionUtils.getOrCreate(microservice.getVersion());
+      }
+
+      @Mock
+      public Microservice getMicroservice() {
+        return microservice;
+      }
+    }.getMockInstance());
+    return new StaticMicroserviceVersions(
+        appManager, APP_ID, MICROSERVICE_NAME, TestServiceIntf.class);
+  }
+
+  private interface TestServiceIntf {
+  }
+}
\ No newline at end of file
diff --git 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestAppManager.java
 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestAppManager.java
index 33616899e..e76d23bbe 100644
--- 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestAppManager.java
+++ 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestAppManager.java
@@ -20,8 +20,10 @@
 import java.util.Collections;
 
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice;
 import 
org.apache.servicecomb.serviceregistry.api.response.FindInstancesResponse;
 import 
org.apache.servicecomb.serviceregistry.client.http.MicroserviceInstances;
+import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig;
 import org.apache.servicecomb.serviceregistry.definition.DefinitionConst;
 import org.junit.After;
 import org.junit.Assert;
@@ -30,7 +32,10 @@
 
 import com.google.common.eventbus.EventBus;
 
+import mockit.Deencapsulation;
 import mockit.Expectations;
+import mockit.Mock;
+import mockit.MockUp;
 import mockit.Mocked;
 
 public class TestAppManager {
@@ -97,4 +102,26 @@ public void setMicroserviceVersionFactory(@Mocked 
MicroserviceVersionFactory mic
 
     Assert.assertSame(microserviceVersionFactory, 
appManager.getMicroserviceVersionFactory());
   }
+
+  @Test
+  public void getStaticMicroserviceVersionFactory() {
+    new MockUp<ServiceRegistryConfig>() {
+      @Mock
+      String getStaticMicroserviceVersionFactory() {
+        return TestStaticMicroserviceVersionFactory.class.getName();
+      }
+    };
+
+    Assert.assertNull(Deencapsulation.getField(appManager, 
"staticMicroserviceVersionFactory"));
+
+    Assert.assertEquals(TestStaticMicroserviceVersionFactory.class,
+        appManager.getStaticMicroserviceVersionFactory().getClass());
+  }
+
+  static class TestStaticMicroserviceVersionFactory implements 
StaticMicroserviceVersionFactory {
+    @Override
+    public MicroserviceVersion create(StaticMicroservice microservice) {
+      return null;
+    }
+  }
 }
diff --git 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersion.java
 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersion.java
index 5b5f23aca..02b7ff54c 100644
--- 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersion.java
+++ 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersion.java
@@ -17,8 +17,9 @@
 
 package org.apache.servicecomb.serviceregistry.consumer;
 
-
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.serviceregistry.api.registry.Microservice;
+import org.apache.servicecomb.serviceregistry.version.Version;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Rule;
@@ -51,4 +52,15 @@ public void constructNormal() {
     Assert.assertEquals("1", 
microserviceVersion.getMicroservice().getServiceId());
     Assert.assertEquals("1.0.0", 
microserviceVersion.getVersion().getVersion());
   }
+
+  @Test
+  public void constructByMicroservice() {
+    Microservice microservice = new Microservice();
+    String version = "1.2.1";
+    microservice.setVersion(version);
+    MicroserviceVersion microserviceVersion = new 
MicroserviceVersion(microservice);
+
+    Assert.assertSame(microservice, microserviceVersion.getMicroservice());
+    Assert.assertEquals(new Version(version), 
microserviceVersion.getVersion());
+  }
 }
diff --git 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestAbstractServiceRegistry.java
 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestAbstractServiceRegistry.java
index b223c3d5d..e11a05808 100644
--- 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestAbstractServiceRegistry.java
+++ 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestAbstractServiceRegistry.java
@@ -17,19 +17,35 @@
 
 package org.apache.servicecomb.serviceregistry.registry;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import org.apache.servicecomb.serviceregistry.client.ServiceRegistryClient;
 import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig;
+import org.apache.servicecomb.serviceregistry.consumer.AppManager;
 import 
org.apache.servicecomb.serviceregistry.consumer.DefaultMicroserviceVersionFactory;
+import org.apache.servicecomb.serviceregistry.consumer.MicroserviceManager;
+import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersion;
+import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersions;
+import 
org.apache.servicecomb.serviceregistry.consumer.StaticMicroserviceVersionFactory;
 import 
org.apache.servicecomb.serviceregistry.definition.MicroserviceDefinition;
 import org.hamcrest.Matchers;
+import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.mockito.Mockito;
 
 import com.google.common.eventbus.EventBus;
 
+import mockit.Deencapsulation;
 import mockit.Expectations;
 import mockit.Mocked;
 
@@ -70,6 +86,17 @@ protected ServiceRegistryClient 
createServiceRegistryClient() {
   public void setup() {
     registry =
         new AbstractServiceRegistryForTest(eventBus, serviceRegistryConfig, 
microserviceDefinition);
+    RegistryUtils.setServiceRegistry(registry);
+  }
+
+  @After
+  public void tearDown() {
+    registry.appManager = null;
+  }
+
+  @AfterClass
+  public static void afterClass() {
+    RegistryUtils.setServiceRegistry(null);
   }
 
   @Test
@@ -96,8 +123,7 @@ public void 
initAppManagerSpecialMicroserviceVersionFactoryNormal()
   }
 
   @Test
-  public void initAppManagerSpecialMicroserviceVersionFactoryFailed()
-      throws InstantiationException, IllegalAccessException, 
ClassNotFoundException {
+  public void initAppManagerSpecialMicroserviceVersionFactoryFailed() {
     new Expectations() {
       {
         serviceRegistryConfig.getMicroserviceVersionFactory();
@@ -109,4 +135,70 @@ public void 
initAppManagerSpecialMicroserviceVersionFactoryFailed()
 
     registry.init();
   }
+
+  @Test
+  public void registryMicroserviceMapping() {
+    String testServiceName = "testService";
+    final String testVersion = "1.0.1";
+
+    HashMap<String, MicroserviceVersions> versionsByName = 
prepareForMicroserviceMappingRegistry();
+
+    ArrayList<MicroserviceInstance> instancesParam = new ArrayList<>();
+    instancesParam.add(new MicroserviceInstance());
+    registry.registerMicroserviceMapping(testServiceName, testVersion, 
instancesParam, Test3rdPartyServiceIntf.class);
+
+    MicroserviceVersions microserviceVersions = 
versionsByName.get(testServiceName);
+    List<MicroserviceInstance> instances = 
Deencapsulation.getField(microserviceVersions, "instances");
+    Assert.assertEquals(1, instances.size());
+    Assert.assertSame(instancesParam.get(0), instances.get(0));
+
+    // nothing will happen if register repeatedly
+    List<MicroserviceInstance> newInstancesParam = new ArrayList<>();
+    newInstancesParam.add(new MicroserviceInstance());
+    registry.registerMicroserviceMapping(
+        testServiceName, testVersion, newInstancesParam, 
Test3rdPartyServiceIntf.class);
+
+    microserviceVersions = versionsByName.get(testServiceName);
+    instances = Deencapsulation.getField(microserviceVersions, "instances");
+    Assert.assertEquals(1, instances.size());
+    Assert.assertSame(instancesParam.get(0), instances.get(0));
+  }
+
+  @Test
+  public void registryMicroserviceMappingByEndpoints() {
+    String testServiceName = "testService";
+    final String testVersion = "1.0.1";
+
+    HashMap<String, MicroserviceVersions> versionByName = 
prepareForMicroserviceMappingRegistry();
+
+    registry.registerMicroserviceMappingByEndpoints(testServiceName, 
testVersion,
+        Arrays.asList("cse://127.0.0.1:8080", "cse://127.0.0.1:8081"), 
Test3rdPartyServiceIntf.class);
+
+    MicroserviceVersions microserviceVersions = 
versionByName.get(testServiceName);
+    List<MicroserviceInstance> instances = 
Deencapsulation.getField(microserviceVersions, "instances");
+    Assert.assertEquals(2, instances.size());
+    Assert.assertEquals("cse://127.0.0.1:8080", 
instances.get(0).getEndpoints().get(0));
+    Assert.assertEquals("cse://127.0.0.1:8081", 
instances.get(1).getEndpoints().get(0));
+  }
+
+  private HashMap<String, MicroserviceVersions> 
prepareForMicroserviceMappingRegistry() {
+    registry.appManager = Mockito.mock(AppManager.class);
+    MicroserviceManager microserviceManager = 
Mockito.mock(MicroserviceManager.class);
+    StaticMicroserviceVersionFactory staticMicroserviceVersionFactory =
+        Mockito.mock(StaticMicroserviceVersionFactory.class);
+    HashMap<String, MicroserviceVersions> versionsByName = new HashMap<>();
+
+    
Mockito.when(registry.appManager.getOrCreateMicroserviceManager(this.appId)).thenReturn(microserviceManager);
+    
Mockito.when(registry.appManager.getEventBus()).thenReturn(Mockito.mock(EventBus.class));
+    Mockito.when(registry.appManager.getStaticMicroserviceVersionFactory())
+        .thenReturn(staticMicroserviceVersionFactory);
+    Mockito.when(staticMicroserviceVersionFactory.create(Mockito.any()))
+        .thenReturn(Mockito.mock(MicroserviceVersion.class));
+
+    
Mockito.when(microserviceManager.getVersionsByName()).thenReturn(versionsByName);
+    return versionsByName;
+  }
+
+  private interface Test3rdPartyServiceIntf {
+  }
 }
diff --git 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/SwaggerGenerator.java
 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/SwaggerGenerator.java
index aa472fd25..8b51b9b34 100644
--- 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/SwaggerGenerator.java
+++ 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/SwaggerGenerator.java
@@ -27,6 +27,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.CompletableFuture;
 
 import javax.ws.rs.core.MediaType;
 
@@ -203,7 +204,7 @@ private void correctInfo() {
   }
 
   protected void setJavaInterface(Info info, Class<?> cls) {
-    if (cls.isInterface()) {
+    if (cls.isInterface() && !isInterfaceReactive(cls)) {
       info.setVendorExtension(SwaggerConst.EXT_JAVA_INTF, cls.getName());
       return;
     }
@@ -218,6 +219,26 @@ protected void setJavaInterface(Info info, Class<?> cls) {
     info.setVendorExtension(SwaggerConst.EXT_JAVA_INTF, intfName);
   }
 
+  /**
+   * Whether this interface class is reactive.
+   * This is used for the situation that the {@code interfaceCls} may be used 
as swagger interface directly
+   */
+  private boolean isInterfaceReactive(Class<?> interfaceCls) {
+    for (Method method : interfaceCls.getDeclaredMethods()) {
+      if (isSkipMethod(method)) {
+        continue;
+      }
+      if (CompletableFuture.class.isAssignableFrom(method.getReturnType())) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Whether this method should be processed as a swagger operation
+   * @return true if this isn't a swagger operation; otherwise, false.
+   */
   protected boolean isSkipMethod(Method method) {
     if (method.getDeclaringClass().getName().equals(Object.class.getName())) {
       return true;
diff --git 
a/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/accesslog/impl/AccessLogHandlerTest.java
 
b/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/accesslog/impl/AccessLogHandlerTest.java
index efd4ee2b7..0ef62e508 100644
--- 
a/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/accesslog/impl/AccessLogHandlerTest.java
+++ 
b/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/accesslog/impl/AccessLogHandlerTest.java
@@ -18,6 +18,7 @@
 package org.apache.servicecomb.transport.rest.vertx.accesslog.impl;
 
 import java.util.HashSet;
+import java.util.concurrent.TimeUnit;
 
 import javax.xml.ws.Holder;
 
@@ -78,9 +79,13 @@ public int getStatusCode() {
 
     Holder<Integer> counter = new Holder<>();
     counter.value = 0;
+    String testThreadName = Thread.currentThread().getName();
     new MockUp<System>() {
       @Mock
       long currentTimeMillis() {
+        if (!testThreadName.equals(Thread.currentThread().getName())) {
+          return TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
+        }
         if (counter.value < 1) {
           ++counter.value;
           return 1L;


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


> Invoke 3rd party service
> ------------------------
>
>                 Key: SCB-926
>                 URL: https://issues.apache.org/jira/browse/SCB-926
>             Project: Apache ServiceComb
>          Issue Type: New Feature
>    Affects Versions: java-chassis-1.1.0
>            Reporter: YaoHaishi
>            Assignee: YaoHaishi
>            Priority: Major
>
> Provide a interface to let users specify 3rd party services' endpoints and 
> let users can invoke 3rd party service like invoking the ServiceComb 
> microservice.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to