You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2020/07/29 07:14:51 UTC

[servicecomb-java-chassis] branch master updated: [SCB-2045]support add service interface to tell which methods can publish as service

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

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new 845d763  [SCB-2045]support add service interface to tell which methods can publish as service
845d763 is described below

commit 845d763e5bab180285116ab5a0d6f4ea5f528728
Author: liubao <bi...@qq.com>
AuthorDate: Wed Jul 29 10:07:16 2020 +0800

    [SCB-2045]support add service interface to tell which methods can publish as service
---
 .../core/provider/producer/ProducerMeta.java       | 10 +++++
 .../provider/producer/ProducerProviderManager.java |  8 +++-
 .../demo/jaxrs/client/SchemeInterfaceJaxrs.java    | 21 ++--------
 .../jaxrs/client/TestSchemeInterfaceJaxrs.java     | 44 +++++++++++++++++++++
 .../demo/jaxrs/server/SchemeInterfaceJaxrs.java    | 29 +++++++-------
 .../jaxrs/server/SchemeInterfaceJaxrsImpl.java     | 27 ++++++-------
 .../demo/pojo/client/SchemeInterfacePojo.java      | 21 ++--------
 .../demo/pojo/client/TestSchemeInterfacePojo.java  | 45 ++++++++++++++++++++++
 .../demo/pojo/server/SchemeInterfacePojo.java      | 21 ++--------
 .../demo/pojo/server/SchemeInterfacePojoImpl.java  | 27 ++++++-------
 .../springmvc/client/SchemeInterfaceSpringmvc.java | 21 ++--------
 .../client/TestSchemeInterfaceSpringmvc.java       | 44 +++++++++++++++++++++
 .../springmvc/server/SchemeInterfaceSpringmvc.java | 26 +++++--------
 .../server/SchemeInterfaceSpringmvcImpl.java       | 27 ++++++-------
 .../provider/pojo/PojoProducerProvider.java        | 10 -----
 .../servicecomb/provider/pojo/RpcSchema.java       |  2 +
 .../provider/pojo/schema/PojoProducers.java        |  1 +
 .../provider/rest/common/RestProducers.java        |  1 +
 .../provider/rest/common/RestSchema.java           |  2 +
 .../swagger/engine/SwaggerEnvironment.java         | 25 +++++++++---
 .../arguments/consumer/TestPojoV1V1.java           | 13 ++++++-
 21 files changed, 258 insertions(+), 167 deletions(-)

diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerMeta.java b/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerMeta.java
index b110dc5..87a1481 100644
--- a/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerMeta.java
+++ b/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerMeta.java
@@ -22,6 +22,8 @@ public class ProducerMeta {
 
   private Object instance;
 
+  private Class<?> schemaInterface;
+
   public ProducerMeta() {
   }
 
@@ -45,4 +47,12 @@ public class ProducerMeta {
   public void setInstance(Object instance) {
     this.instance = instance;
   }
+
+  public Class<?> getSchemaInterface() {
+    return schemaInterface;
+  }
+
+  public void setSchemaInterface(Class<?> schemaInterface) {
+    this.schemaInterface = schemaInterface;
+  }
 }
diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerProviderManager.java b/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerProviderManager.java
index 9c02c67..854a4c2 100644
--- a/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerProviderManager.java
+++ b/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerProviderManager.java
@@ -84,18 +84,22 @@ public class ProducerProviderManager {
 
   private void regsiterProducerMetas(List<ProducerMeta> producerMetas) {
     for (ProducerMeta producerMeta : producerMetas) {
-      registerSchema(producerMeta.getSchemaId(), producerMeta.getInstance());
+      registerSchema(producerMeta.getSchemaId(), producerMeta.getSchemaInterface(), producerMeta.getInstance());
     }
   }
 
   public SchemaMeta registerSchema(String schemaId, Object instance) {
+    return registerSchema(schemaId, null, instance);
+  }
+
+  public SchemaMeta registerSchema(String schemaId, Class<?> schemaInterface, Object instance) {
     MicroserviceMeta producerMicroserviceMeta = scbEngine.getProducerMicroserviceMeta();
     Swagger swagger = scbEngine.getSwaggerLoader().loadLocalSwagger(
         producerMicroserviceMeta.getAppId(),
         producerMicroserviceMeta.getShortName(),
         schemaId);
     SwaggerProducer swaggerProducer = scbEngine.getSwaggerEnvironment()
-        .createProducer(instance, swagger);
+        .createProducer(instance, schemaInterface, swagger);
     swagger = swaggerProducer.getSwagger();
     registerUrlPrefixToSwagger(swagger);
 
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/SchemeInterfaceJaxrs.java
similarity index 62%
copy from providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
copy to demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/SchemeInterfaceJaxrs.java
index 97f4460..53f4c07 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
+++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/SchemeInterfaceJaxrs.java
@@ -15,23 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.provider.rest.common;
+package org.apache.servicecomb.demo.jaxrs.client;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+public interface SchemeInterfaceJaxrs {
+  int add(int a, int b);
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import org.springframework.stereotype.Component;
-
-@Inherited
-@Documented
-@Retention(RUNTIME)
-@Target(TYPE)
-@Component
-public @interface RestSchema {
-  String schemaId();
+  int reduce(int a, int b);
 }
diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestSchemeInterfaceJaxrs.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestSchemeInterfaceJaxrs.java
new file mode 100644
index 0000000..6ebc4ef
--- /dev/null
+++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestSchemeInterfaceJaxrs.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.demo.jaxrs.client;
+
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TestSchemeInterfaceJaxrs implements CategorizedTestCase {
+  @RpcReference(schemaId = "SchemeInterfaceJaxrs", microserviceName = "jaxrs")
+  private SchemeInterfaceJaxrs jaxrs;
+
+  public void testAllTransport() throws Exception {
+    TestMgr.check(3, jaxrs.add(1, 2));
+
+    try {
+      jaxrs.reduce(1, 3);
+      TestMgr.failed("should throw exception", new Exception());
+    } catch (Exception e) {
+      TestMgr.check(
+          "Consumer method org.apache.servicecomb.demo.jaxrs.client.SchemeInterfaceJaxrs:reduce "
+              + "not exist in contract, microserviceName=jaxrs, schemaId=SchemeInterfaceJaxrs; "
+              + "new producer not running or not deployed.",
+          e.getMessage());
+    }
+  }
+}
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrs.java
similarity index 62%
copy from providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
copy to demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrs.java
index 97f4460..e0de028 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
+++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrs.java
@@ -15,23 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.provider.rest.common;
+package org.apache.servicecomb.demo.jaxrs.server;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import javax.validation.constraints.Min;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
+import org.springframework.web.bind.annotation.RequestParam;
 
-import org.springframework.stereotype.Component;
-
-@Inherited
-@Documented
-@Retention(RUNTIME)
-@Target(TYPE)
-@Component
-public @interface RestSchema {
-  String schemaId();
+@Path("/jaxrs/schemaInterface")
+@Produces(MediaType.APPLICATION_JSON)
+public interface SchemeInterfaceJaxrs {
+  @Path("/add")
+  @GET
+  public int add(@Min(1) @RequestParam("a") int a, @Min(1) @RequestParam("b") int b);
 }
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrsImpl.java
similarity index 62%
copy from providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
copy to demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrsImpl.java
index 97f4460..edf68e3 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
+++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrsImpl.java
@@ -15,23 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.provider.rest.common;
+package org.apache.servicecomb.demo.jaxrs.server;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import javax.validation.constraints.Min;
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
 
-import org.springframework.stereotype.Component;
+@RestSchema(schemaId = "SchemeInterfaceJaxrs", schemaInterface = SchemeInterfaceJaxrs.class)
+public class SchemeInterfaceJaxrsImpl implements SchemeInterfaceJaxrs {
+  @Override
+  public int add(@Min(1) int a, @Min(1) int b) {
+    return a + b;
+  }
 
-@Inherited
-@Documented
-@Retention(RUNTIME)
-@Target(TYPE)
-@Component
-public @interface RestSchema {
-  String schemaId();
+  public int reduce(int a, int b) {
+    return a - b;
+  }
 }
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/SchemeInterfacePojo.java
similarity index 62%
copy from providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
copy to demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/SchemeInterfacePojo.java
index 97f4460..f701c9f 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
+++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/SchemeInterfacePojo.java
@@ -15,23 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.provider.rest.common;
+package org.apache.servicecomb.demo.pojo.client;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+public interface SchemeInterfacePojo {
+  int reduce(int a, int b);
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import org.springframework.stereotype.Component;
-
-@Inherited
-@Documented
-@Retention(RUNTIME)
-@Target(TYPE)
-@Component
-public @interface RestSchema {
-  String schemaId();
+  int add(int a, int b);
 }
diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSchemeInterfacePojo.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSchemeInterfacePojo.java
new file mode 100644
index 0000000..cd51640
--- /dev/null
+++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSchemeInterfacePojo.java
@@ -0,0 +1,45 @@
+/*
+ * 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.demo.pojo.client;
+
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TestSchemeInterfacePojo implements CategorizedTestCase {
+  @RpcReference(microserviceName = "pojo", schemaId = "SchemeInterfacePojoImpl")
+  private SchemeInterfacePojo pojo;
+
+  @Override
+  public void testAllTransport() throws Exception {
+    TestMgr.check(-1, pojo.reduce(1, 2));
+
+    try {
+      pojo.add(1, 2);
+      TestMgr.failed("should throw exception", new Exception());
+    } catch (Exception e) {
+      TestMgr.check(
+          "Consumer method org.apache.servicecomb.demo.pojo.client.SchemeInterfacePojo:"
+              + "add not exist in contract, microserviceName=pojo, "
+              + "schemaId=SchemeInterfacePojoImpl; new producer not running or not deployed.",
+          e.getMessage());
+    }
+  }
+}
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/SchemeInterfacePojo.java
similarity index 62%
copy from providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
copy to demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/SchemeInterfacePojo.java
index 97f4460..7a50394 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
+++ b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/SchemeInterfacePojo.java
@@ -15,23 +15,8 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.provider.rest.common;
+package org.apache.servicecomb.demo.pojo.server;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import org.springframework.stereotype.Component;
-
-@Inherited
-@Documented
-@Retention(RUNTIME)
-@Target(TYPE)
-@Component
-public @interface RestSchema {
-  String schemaId();
+public interface SchemeInterfacePojo {
+  int reduce(int a, int b);
 }
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/SchemeInterfacePojoImpl.java
similarity index 62%
copy from providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
copy to demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/SchemeInterfacePojoImpl.java
index 97f4460..0e54440 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
+++ b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/SchemeInterfacePojoImpl.java
@@ -15,23 +15,18 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.provider.rest.common;
+package org.apache.servicecomb.demo.pojo.server;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import org.apache.servicecomb.provider.pojo.RpcSchema;
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
+@RpcSchema(schemaId = "SchemeInterfacePojoImpl", schemaInterface = SchemeInterfacePojo.class)
+public class SchemeInterfacePojoImpl implements SchemeInterfacePojo {
+  @Override
+  public int reduce(int a, int b) {
+    return a - b;
+  }
 
-import org.springframework.stereotype.Component;
-
-@Inherited
-@Documented
-@Retention(RUNTIME)
-@Target(TYPE)
-@Component
-public @interface RestSchema {
-  String schemaId();
+  public int add(int a, int b) {
+    return a + b;
+  }
 }
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SchemeInterfaceSpringmvc.java
similarity index 62%
copy from providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
copy to demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SchemeInterfaceSpringmvc.java
index 97f4460..863f9b8 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SchemeInterfaceSpringmvc.java
@@ -15,23 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.provider.rest.common;
+package org.apache.servicecomb.demo.springmvc.client;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+public interface SchemeInterfaceSpringmvc {
+  int add(int a, int b);
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import org.springframework.stereotype.Component;
-
-@Inherited
-@Documented
-@Retention(RUNTIME)
-@Target(TYPE)
-@Component
-public @interface RestSchema {
-  String schemaId();
+  int reduce(int a, int b);
 }
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSchemeInterfaceSpringmvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSchemeInterfaceSpringmvc.java
new file mode 100644
index 0000000..c29fda9
--- /dev/null
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSchemeInterfaceSpringmvc.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.demo.springmvc.client;
+
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TestSchemeInterfaceSpringmvc implements CategorizedTestCase {
+  @RpcReference(schemaId = "SchemeInterfaceSpringmvc", microserviceName = "springmvc")
+  private SchemeInterfaceSpringmvc springmvc;
+
+  public void testAllTransport() throws Exception {
+    TestMgr.check(3, springmvc.add(1, 2));
+
+    try {
+      springmvc.reduce(1, 3);
+      TestMgr.failed("should throw exception", new Exception());
+    } catch (Exception e) {
+      TestMgr.check(
+          "Consumer method org.apache.servicecomb.demo.springmvc.client.SchemeInterfaceSpringmvc:reduce not "
+              + "exist in contract, microserviceName=springmvc, "
+              + "schemaId=SchemeInterfaceSpringmvc; new producer not running or not deployed.",
+          e.getMessage());
+    }
+  }
+}
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvc.java
similarity index 58%
copy from providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
copy to demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvc.java
index 97f4460..68aba03 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvc.java
@@ -15,23 +15,17 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.provider.rest.common;
+package org.apache.servicecomb.demo.springmvc.server;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import javax.validation.constraints.Min;
+import javax.ws.rs.core.MediaType;
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 
-import org.springframework.stereotype.Component;
-
-@Inherited
-@Documented
-@Retention(RUNTIME)
-@Target(TYPE)
-@Component
-public @interface RestSchema {
-  String schemaId();
+@RequestMapping(path = "/springmvc/schemaInterface", produces = MediaType.APPLICATION_JSON)
+public interface SchemeInterfaceSpringmvc {
+  @GetMapping(path = "/add")
+  public int add(@Min(1) @RequestParam("a") int a, @Min(1) @RequestParam("b") int b);
 }
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvcImpl.java
similarity index 62%
copy from providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
copy to demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvcImpl.java
index 97f4460..548e591 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvcImpl.java
@@ -15,23 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.provider.rest.common;
+package org.apache.servicecomb.demo.springmvc.server;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import javax.validation.constraints.Min;
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
 
-import org.springframework.stereotype.Component;
+@RestSchema(schemaId = "SchemeInterfaceSpringmvc", schemaInterface = SchemeInterfaceSpringmvc.class)
+public class SchemeInterfaceSpringmvcImpl implements SchemeInterfaceSpringmvc {
+  @Override
+  public int add(@Min(1) int a, @Min(1) int b) {
+    return a + b;
+  }
 
-@Inherited
-@Documented
-@Retention(RUNTIME)
-@Target(TYPE)
-@Component
-public @interface RestSchema {
-  String schemaId();
+  public int reduce(int a, int b) {
+    return a - b;
+  }
 }
diff --git a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/PojoProducerProvider.java b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/PojoProducerProvider.java
index 4ba6507..637e82d 100644
--- a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/PojoProducerProvider.java
+++ b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/PojoProducerProvider.java
@@ -53,16 +53,6 @@ public class PojoProducerProvider extends AbstractProducerProvider {
     for (ProducerMeta producerMeta : pojoProducers.getProducerMetas()) {
       PojoProducerMeta pojoProducerMeta = (PojoProducerMeta) producerMeta;
       initPojoProducerMeta(pojoProducerMeta);
-
-//      try {
-//        producerSchemaFactory.getOrCreateProducerSchema(
-//            pojoProducerMeta.getSchemaId(),
-//            pojoProducerMeta.getInstanceClass(),
-//            pojoProducerMeta.getInstance());
-//      } catch (Throwable e) {
-//        throw new IllegalArgumentException(
-//            "create producer schema failed, class=" + pojoProducerMeta.getInstanceClass().getName(), e);
-//      }
     }
 
     return pojoProducers.getProducerMetas();
diff --git a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/RpcSchema.java b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/RpcSchema.java
index 80e1c82..5302f29 100644
--- a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/RpcSchema.java
+++ b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/RpcSchema.java
@@ -34,4 +34,6 @@ import org.springframework.stereotype.Component;
 @Component
 public @interface RpcSchema {
   String schemaId() default "";
+
+  Class<?> schemaInterface() default Object.class;
 }
diff --git a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/schema/PojoProducers.java b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/schema/PojoProducers.java
index 1c4ac88..9c1a7e0 100644
--- a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/schema/PojoProducers.java
+++ b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/schema/PojoProducers.java
@@ -75,6 +75,7 @@ public class PojoProducers implements BeanPostProcessor {
 
     PojoProducerMeta pojoProducerMeta = new PojoProducerMeta();
     pojoProducerMeta.setSchemaId(schemaId);
+    pojoProducerMeta.setSchemaInterface(rpcSchema.schemaInterface());
     pojoProducerMeta.setInstance(bean);
 
     registerPojoProducer(pojoProducerMeta);
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestProducers.java b/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestProducers.java
index 16d2cf9..59a6018 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestProducers.java
+++ b/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestProducers.java
@@ -67,6 +67,7 @@ public class RestProducers implements BeanPostProcessor {
     RestSchema restSchema = beanCls.getAnnotation(RestSchema.class);
     if (restSchema != null) {
       ProducerMeta producerMeta = new ProducerMeta(restSchema.schemaId(), bean);
+      producerMeta.setSchemaInterface(restSchema.schemaInterface());
       producerMetaList.add(producerMeta);
       return;
     }
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java b/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
index 97f4460..f031c3d 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
+++ b/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/RestSchema.java
@@ -34,4 +34,6 @@ import org.springframework.stereotype.Component;
 @Component
 public @interface RestSchema {
   String schemaId();
+
+  Class<?> schemaInterface() default Object.class;
 }
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java
index 5e34eaa..49618a0 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java
@@ -100,12 +100,13 @@ public class SwaggerEnvironment {
   }
 
   public SwaggerProducer createProducer(Object producerInstance, Swagger swagger) {
-    if (swagger == null) {
-      Class<?> producerCls = BeanUtils.getImplClassFromBean(producerInstance);
-      swagger = SwaggerGenerator.generate(producerCls);
-    }
+    return createProducer(producerInstance, null, swagger);
+  }
 
-    Map<Class<?>, ContextArgumentMapperFactory> contextFactorys = SPIServiceUtils
+  public SwaggerProducer createProducer(Object producerInstance, Class<?> schemaInterface, Swagger swagger) {
+    swagger = checkAndGenerateSwagger(producerInstance, schemaInterface, swagger);
+
+    Map<Class<?>, ContextArgumentMapperFactory> contextFactories = SPIServiceUtils
         .getOrLoadSortedService(ProducerContextArgumentMapperFactory.class)
         .stream()
         .collect(Collectors.toMap(ProducerContextArgumentMapperFactory::getContextClass, Function.identity()));
@@ -135,7 +136,7 @@ public class SwaggerEnvironment {
 
       ProducerArgumentsMapperCreator creator = new ProducerArgumentsMapperCreator(
           Json.mapper().getSerializationConfig(),
-          contextFactorys,
+          contextFactories,
           producerCls,
           producerMethod,
           swaggerOperation);
@@ -157,4 +158,16 @@ public class SwaggerEnvironment {
 
     return producer;
   }
+
+  private Swagger checkAndGenerateSwagger(Object producerInstance, Class<?> schemaInterface, Swagger swagger) {
+    if (swagger == null) {
+      if (schemaInterface != null && !Object.class.equals(schemaInterface)) {
+        swagger = SwaggerGenerator.generate(schemaInterface);
+      } else {
+        Class<?> producerCls = BeanUtils.getImplClassFromBean(producerInstance);
+        swagger = SwaggerGenerator.generate(producerCls);
+      }
+    }
+    return swagger;
+  }
 }
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/consumer/TestPojoV1V1.java b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/consumer/TestPojoV1V1.java
index 223a092..0372acc 100644
--- a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/consumer/TestPojoV1V1.java
+++ b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/consumer/TestPojoV1V1.java
@@ -39,9 +39,18 @@ import io.swagger.models.Swagger;
 @SuppressWarnings("unchecked")
 public class TestPojoV1V1 {
   @Test
-  public void add_add() {
+  public void add_add_class() {
+    add_add(PojoAddV1.class);
+  }
+
+  @Test
+  public void add_add_interface() {
+    add_add(ConsumerAddV1.class);
+  }
+
+  public void add_add(Class<?> clazz) {
     SwaggerEnvironment environment = new SwaggerEnvironment();
-    Swagger swagger = SwaggerGenerator.generate(PojoAddV1.class);
+    Swagger swagger = SwaggerGenerator.generate(clazz);
 
     SwaggerConsumer swaggerConsumer = environment.createConsumer(ConsumerAddV1.class, swagger);
     ArgumentsMapper mapper = swaggerConsumer.findOperation("add").getArgumentsMapper();