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 2019/08/28 00:35:46 UTC

[servicecomb-java-chassis] 01/03: [SCB-1448]support class inheritance and interface inheritance with template type(add interface inheritance scenario support)

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

commit d96a8cafbed48ff22181a51433f7fd5dbcf35dbf
Author: liubao <bi...@qq.com>
AuthorDate: Sun Aug 25 18:51:46 2019 +0800

    [SCB-1448]support class inheritance and interface inheritance with template type(add interface inheritance scenario support)
---
 .../it/schema/generic/TestMyService.java           | 18 ++++++
 ...MyService.java => MyEndpointWithInterface.java} |  7 +--
 .../servicecomb/it/schema/generic/MyService.java   |  2 +
 .../swagger/generator/core/SwaggerGenerator.java   | 37 ++----------
 .../swagger/generator/core/utils/MethodUtils.java  | 69 ++++++++++++++++++++++
 .../swagger/generator/core/utils/ParamUtils.java   | 17 +++++-
 .../swagger/generator/core/IMyServiceChild.java    | 30 +---------
 .../swagger/generator/core/IMyServiceChild2.java   | 30 +---------
 .../swagger/generator/core/MyEndpoint2.java        | 28 +++++++++
 .../swagger/generator/core/TestParamUtils.java     | 20 +++++++
 .../generator/core/utils/AbstractBaseClass.java    | 31 ++--------
 .../swagger/generator/core/utils/AbstractBean.java | 31 +++-------
 .../generator/core/utils/BaseInterface.java        | 32 ++--------
 .../generator/core/utils/Hello2Endpoint.java       | 29 +++------
 .../swagger/generator/core/utils/HelloBean.java    | 31 +++-------
 .../generator/core/utils/HelloEndpoint.java        | 30 ++--------
 .../generator/core/utils/ServiceInterface.java     | 31 +---------
 .../generator/core/utils/TestMethodUtils.java      | 35 ++++-------
 .../swagger/engine/SwaggerProducerOperation.java   | 10 ++++
 19 files changed, 225 insertions(+), 293 deletions(-)

diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/generic/TestMyService.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/generic/TestMyService.java
index 1093772..659e3a6 100644
--- a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/generic/TestMyService.java
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/generic/TestMyService.java
@@ -27,6 +27,8 @@ import org.junit.Test;
 public class TestMyService {
   private static Consumers<IMyService> myservice = new Consumers<>("MyEndpoint",
       IMyService.class);
+  private static Consumers<IMyService> myserviceWithInterface = new Consumers<>("MyEndpointWithInterface",
+      IMyService.class);
 
   @Test
   public void testServiceInoke() {
@@ -47,4 +49,20 @@ public class TestMyService {
     List<PersonBean> beanListResult = myservice.getIntf().helloList(beanList);
     Assert.assertEquals("p", beanListResult.get(0).getName());
   }
+
+  @Test
+  public void testServiceWithInterfaceInoke() {
+    PersonBean bean = new PersonBean();
+    bean.setName("p");
+    PersonBean resultBean = myserviceWithInterface.getIntf().hello(bean);
+    Assert.assertEquals("p", resultBean.getName());
+
+    resultBean = myserviceWithInterface.getIntf().actual();
+    Assert.assertEquals("p", resultBean.getName());
+
+    List<PersonBean> beanList = new ArrayList<>();
+    beanList.add(bean);
+    List<PersonBean> beanListResult = myserviceWithInterface.getIntf().helloList(beanList);
+    Assert.assertEquals("p", beanListResult.get(0).getName());
+  }
 }
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyEndpointWithInterface.java
similarity index 88%
copy from integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
copy to integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyEndpointWithInterface.java
index 51ef504..1b9a5e7 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyEndpointWithInterface.java
@@ -16,13 +16,12 @@
  */
 package org.apache.servicecomb.it.schema.generic;
 
-
 import java.util.List;
 
-import org.springframework.stereotype.Service;
+import org.apache.servicecomb.provider.pojo.RpcSchema;
 
-@Service
-public class MyService implements IMyService {
+@RpcSchema(schemaId = "MyEndpointWithInterface")
+public class MyEndpointWithInterface implements IMyService {
   @Override
   public PersonBean hello(PersonBean a) {
     return a;
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
index 51ef504..bb97c6d 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
@@ -19,9 +19,11 @@ package org.apache.servicecomb.it.schema.generic;
 
 import java.util.List;
 
+import org.springframework.context.annotation.Primary;
 import org.springframework.stereotype.Service;
 
 @Service
+@Primary
 public class MyService implements IMyService {
   @Override
   public PersonBean hello(PersonBean a) {
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 c686f8a..f4346f7 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
@@ -33,6 +33,7 @@ import java.util.concurrent.CompletableFuture;
 import javax.ws.rs.core.MediaType;
 
 import org.apache.servicecomb.foundation.common.utils.JvmUtils;
+import org.apache.servicecomb.swagger.generator.core.utils.MethodUtils;
 import org.springframework.util.StringUtils;
 
 import io.swagger.annotations.Api;
@@ -210,12 +211,6 @@ public class SwaggerGenerator {
       return;
     }
 
-    //        Class<?>[] interfaces = cls.getInterfaces();
-    //        if (interfaces.length == 1) {
-    //            info.setVendorExtension(SwaggerConst.EXT_JAVA_INTF, interfaces[0].getName());
-    //            return;
-    //        }
-
     String intfName = ensureGetPackageName() + "." + cls.getSimpleName() + "Intf";
     info.setVendorExtension(SwaggerConst.EXT_JAVA_INTF, intfName);
   }
@@ -225,7 +220,7 @@ public class SwaggerGenerator {
    * 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()) {
+    for (Method method : MethodUtils.findProducerMethods(interfaceCls)) {
       if (isSkipMethod(method)) {
         continue;
       }
@@ -236,35 +231,13 @@ public class SwaggerGenerator {
     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;
-    }
-    // skip static method
-    int modifiers = method.getModifiers();
-    if (Modifier.isStatic(modifiers)) {
-      return true;
-    }
-    // skip bridge method
-    if (method.isBridge()) {
-      return true;
-    }
-
-    ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
-    if (apiOperation != null && apiOperation.hidden()) {
-      return apiOperation.hidden();
-    }
-
-    return !context.canProcess(method);
+  protected boolean isSkipMethod(Method m) {
+    return !context.canProcess(m);
   }
 
   protected void scanMethods() {
     // 有时方法顺序不同,很不利于测试,所以先排序
-    List<Method> methods = Arrays.asList(cls.getMethods());
+    List<Method> methods = MethodUtils.findProducerMethods(cls);
     methods.sort(Comparator.comparing(Method::getName));
     for (Method method : methods) {
       if (isSkipMethod(method)) {
diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/utils/MethodUtils.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/utils/MethodUtils.java
new file mode 100644
index 0000000..196f508
--- /dev/null
+++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/utils/MethodUtils.java
@@ -0,0 +1,69 @@
+/*
+ * 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.swagger.generator.core.utils;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+import io.swagger.annotations.ApiOperation;
+
+public class MethodUtils {
+  public static List<Method> findProducerMethods(Class<?> cls) {
+    Method[] methods = cls.getMethods();
+    List<Method> producerMethods = new ArrayList<>(methods.length);
+
+    for (Method m : methods) {
+      if (!isSkipMethod(cls, m)) {
+        producerMethods.add(m);
+      }
+    }
+
+    producerMethods.sort(Comparator.comparing(Method::getName));
+    return producerMethods;
+  }
+
+  public static boolean isSkipMethod(Class<?> cls, Method method) {
+    if (method.getDeclaringClass() == Object.class) {
+      return true;
+    }
+    if (method.getDeclaringClass().isInterface()
+        && !cls.isInterface()) {
+      // inherited template methods
+      return true;
+    }
+    // skip static method
+    int modifiers = method.getModifiers();
+    if (Modifier.isStatic(modifiers)) {
+      return true;
+    }
+    // skip bridge method
+    if (method.isBridge()) {
+      return true;
+    }
+
+    ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
+    if (apiOperation != null && apiOperation.hidden()) {
+      return apiOperation.hidden();
+    }
+
+    return false;
+  }
+}
diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/utils/ParamUtils.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/utils/ParamUtils.java
index 0d1160a..33fd75f 100644
--- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/utils/ParamUtils.java
+++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/utils/ParamUtils.java
@@ -115,6 +115,12 @@ public final class ParamUtils {
           actualTypes = tempTypes;
         }
       }
+      if (typeVariables.length != actualTypes.length) {
+        throw new IllegalArgumentException(String
+            .format("not implement (%s) (%s) (%s), "
+                    + "e.g. extends multiple typed interface or too deep inheritance.",
+                mainClass.getName(), declaringClass.getName(), type.getTypeName()));
+      }
       for (int i = 0; i < typeVariables.length; i++) {
         if (typeVariables[i] == type) {
           return actualTypes[i];
@@ -134,17 +140,24 @@ public final class ParamUtils {
       return TypeUtils.parameterize((Class) parameterizedType.getRawType(), targetTypes);
     }
     throw new IllegalArgumentException(String
-        .format("not implement (%s) (%s) (%s)", mainClass.getName(), declaringClass.getName(), type.getTypeName()));
+        .format("not implement (%s) (%s) (%s)",
+            mainClass.getName(), declaringClass.getName(), type.getTypeName()));
   }
 
   private static Type[] getActualTypes(Type type) {
+    if (type instanceof Class<?>) {
+      if (((Class<?>) type).getSuperclass() != null) {
+        return getActualTypes(((Class<?>) type).getSuperclass());
+      } else {
+        return getActualTypes(((Class<?>) type).getGenericInterfaces()[0]);
+      }
+    }
     if (type instanceof ParameterizedType) {
       return ((ParameterizedType) type).getActualTypeArguments();
     }
     return new Type[0];
   }
 
-
   public static String generateBodyParameterName(Method method) {
     return method.getName() + "Body";
   }
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/IMyServiceChild.java
similarity index 59%
copy from integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
copy to swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/IMyServiceChild.java
index 51ef504..07405e2 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/IMyServiceChild.java
@@ -14,34 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.it.schema.generic;
 
+package org.apache.servicecomb.swagger.generator.core;
 
-import java.util.List;
-
-import org.springframework.stereotype.Service;
-
-@Service
-public class MyService implements IMyService {
-  @Override
-  public PersonBean hello(PersonBean a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean[] helloBody(PersonBean[] a) {
-    return a;
-  }
-
-  @Override
-  public List<PersonBean> helloList(List<PersonBean> a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean actual() {
-    PersonBean p = new PersonBean();
-    p.setName("p");
-    return p;
-  }
+public interface IMyServiceChild extends IMyService {
 }
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/IMyServiceChild2.java
similarity index 59%
copy from integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
copy to swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/IMyServiceChild2.java
index 51ef504..0828846 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/IMyServiceChild2.java
@@ -14,34 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.it.schema.generic;
 
+package org.apache.servicecomb.swagger.generator.core;
 
-import java.util.List;
-
-import org.springframework.stereotype.Service;
-
-@Service
-public class MyService implements IMyService {
-  @Override
-  public PersonBean hello(PersonBean a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean[] helloBody(PersonBean[] a) {
-    return a;
-  }
-
-  @Override
-  public List<PersonBean> helloList(List<PersonBean> a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean actual() {
-    PersonBean p = new PersonBean();
-    p.setName("p");
-    return p;
-  }
+public interface IMyServiceChild2 extends IMyService, IBaseService<PersonBean> {
 }
diff --git a/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/MyEndpoint2.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/MyEndpoint2.java
new file mode 100644
index 0000000..e5c2222
--- /dev/null
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/MyEndpoint2.java
@@ -0,0 +1,28 @@
+package org.apache.servicecomb.swagger.generator.core;
+
+import java.util.List;
+
+/**
+ * Created by Administrator on 2019/8/25.
+ */
+public class MyEndpoint2 implements IMyService {
+  @Override
+  public PersonBean hello(PersonBean a) {
+    return null;
+  }
+
+  @Override
+  public PersonBean[] helloBody(PersonBean[] a) {
+    return new PersonBean[0];
+  }
+
+  @Override
+  public List<PersonBean> helloList(List<PersonBean> a) {
+    return null;
+  }
+
+  @Override
+  public PersonBean actual() {
+    return null;
+  }
+}
diff --git a/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestParamUtils.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestParamUtils.java
index 450d8a2..6539f6b 100644
--- a/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestParamUtils.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestParamUtils.java
@@ -158,6 +158,20 @@ public class TestParamUtils {
     Method hello = IMyService.class.getMethod("hello", AbstractBean.class);
     assertEquals(PersonBean.class,
         ParamUtils.getGenericParameterType(IMyService.class, IBaseService.class, hello.getGenericReturnType()));
+    hello = IMyServiceChild.class.getMethod("hello", AbstractBean.class);
+    assertEquals(PersonBean.class,
+        ParamUtils.getGenericParameterType(IMyServiceChild.class, IBaseService.class, hello.getGenericReturnType()));
+
+    try {
+      hello = IMyServiceChild.class.getMethod("hello", AbstractBean.class);
+      assertEquals(PersonBean.class,
+          ParamUtils.getGenericParameterType(IMyServiceChild2.class, IBaseService.class, hello.getGenericReturnType()));
+      Assert.fail("");
+    } catch (IllegalArgumentException e) {
+      Assert.assertEquals("not implement (org.apache.servicecomb.swagger.generator.core.IMyServiceChild2) "
+          + "(org.apache.servicecomb.swagger.generator.core.IBaseService) (T), "
+          + "e.g. extends multiple typed interface or too deep inheritance.", e.getMessage());
+    }
 
     hello = MyEndpoint.class.getMethod("hello", AbstractBean.class);
     assertEquals(PersonBean.class,
@@ -171,6 +185,12 @@ public class TestParamUtils {
     assertEquals(PersonBean[].class, ParamUtils
         .getGenericParameterType(MyEndpoint.class, AbstractBaseService.class, helloBody.getGenericReturnType()));
 
+    helloBody = MyEndpoint2.class.getMethod("helloBody", PersonBean[].class);
+    assertEquals(PersonBean[].class, ParamUtils
+        .getGenericParameterType(MyEndpoint2.class, AbstractBaseService.class, helloBody.getGenericReturnType()));
+    assertEquals(PersonBean[].class, ParamUtils
+        .getGenericParameterType(MyEndpoint2.class, AbstractBaseService.class, helloBody.getGenericParameterTypes()[0]));
+
     Method helloList = IMyService.class.getMethod("helloList", List.class);
     assertEquals(TypeUtils.parameterize(List.class, PersonBean.class),
         ParamUtils.getGenericParameterType(IMyService.class, IBaseService.class, helloList.getGenericReturnType()));
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/AbstractBaseClass.java
similarity index 60%
copy from integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
copy to swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/AbstractBaseClass.java
index 51ef504..50c577d 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/AbstractBaseClass.java
@@ -14,34 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.it.schema.generic;
 
+package org.apache.servicecomb.swagger.generator.core.utils;
 
-import java.util.List;
+public abstract class AbstractBaseClass<T extends AbstractBean> {
+  abstract T get(T param);
 
-import org.springframework.stereotype.Service;
-
-@Service
-public class MyService implements IMyService {
-  @Override
-  public PersonBean hello(PersonBean a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean[] helloBody(PersonBean[] a) {
-    return a;
-  }
-
-  @Override
-  public List<PersonBean> helloList(List<PersonBean> a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean actual() {
-    PersonBean p = new PersonBean();
-    p.setName("p");
-    return p;
+  public T getBase(T param) {
+    return param;
   }
 }
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/AbstractBean.java
similarity index 60%
copy from integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
copy to swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/AbstractBean.java
index 51ef504..85515b5 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/AbstractBean.java
@@ -14,34 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.it.schema.generic;
 
+package org.apache.servicecomb.swagger.generator.core.utils;
 
-import java.util.List;
+public abstract class AbstractBean {
+  private String type;
 
-import org.springframework.stereotype.Service;
-
-@Service
-public class MyService implements IMyService {
-  @Override
-  public PersonBean hello(PersonBean a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean[] helloBody(PersonBean[] a) {
-    return a;
-  }
-
-  @Override
-  public List<PersonBean> helloList(List<PersonBean> a) {
-    return a;
+  public String getType() {
+    return type;
   }
 
-  @Override
-  public PersonBean actual() {
-    PersonBean p = new PersonBean();
-    p.setName("p");
-    return p;
+  public void setType(String type) {
+    this.type = type;
   }
 }
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/BaseInterface.java
similarity index 59%
copy from integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
copy to swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/BaseInterface.java
index 51ef504..1cef6c4 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/BaseInterface.java
@@ -14,34 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.it.schema.generic;
+package org.apache.servicecomb.swagger.generator.core.utils;
 
+public interface BaseInterface<T extends AbstractBean> {
+  T get(T param);
 
-import java.util.List;
-
-import org.springframework.stereotype.Service;
-
-@Service
-public class MyService implements IMyService {
-  @Override
-  public PersonBean hello(PersonBean a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean[] helloBody(PersonBean[] a) {
-    return a;
-  }
-
-  @Override
-  public List<PersonBean> helloList(List<PersonBean> a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean actual() {
-    PersonBean p = new PersonBean();
-    p.setName("p");
-    return p;
-  }
+  T[] getArray(T[] param);
 }
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/Hello2Endpoint.java
similarity index 63%
copy from integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
copy to swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/Hello2Endpoint.java
index 51ef504..4f40fe7 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/Hello2Endpoint.java
@@ -14,34 +14,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.it.schema.generic;
-
-
-import java.util.List;
-
-import org.springframework.stereotype.Service;
-
-@Service
-public class MyService implements IMyService {
-  @Override
-  public PersonBean hello(PersonBean a) {
-    return a;
-  }
+package org.apache.servicecomb.swagger.generator.core.utils;
 
+public class Hello2Endpoint implements ServiceInterface {
   @Override
-  public PersonBean[] helloBody(PersonBean[] a) {
-    return a;
+  public HelloBean get(HelloBean param) {
+    return param;
   }
 
   @Override
-  public List<PersonBean> helloList(List<PersonBean> a) {
-    return a;
+  public HelloBean[] getArray(HelloBean[] param) {
+    return new HelloBean[0];
   }
 
   @Override
-  public PersonBean actual() {
-    PersonBean p = new PersonBean();
-    p.setName("p");
-    return p;
+  public HelloBean getBase(HelloBean param) {
+    return param;
   }
 }
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/HelloBean.java
similarity index 60%
copy from integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
copy to swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/HelloBean.java
index 51ef504..a380e7e 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/HelloBean.java
@@ -14,34 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.it.schema.generic;
 
+package org.apache.servicecomb.swagger.generator.core.utils;
 
-import java.util.List;
+public class HelloBean extends AbstractBean {
+  private String hello;
 
-import org.springframework.stereotype.Service;
-
-@Service
-public class MyService implements IMyService {
-  @Override
-  public PersonBean hello(PersonBean a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean[] helloBody(PersonBean[] a) {
-    return a;
-  }
-
-  @Override
-  public List<PersonBean> helloList(List<PersonBean> a) {
-    return a;
+  public String getHello() {
+    return hello;
   }
 
-  @Override
-  public PersonBean actual() {
-    PersonBean p = new PersonBean();
-    p.setName("p");
-    return p;
+  public void setHello(String hello) {
+    this.hello = hello;
   }
 }
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/HelloEndpoint.java
similarity index 61%
copy from integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
copy to swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/HelloEndpoint.java
index 51ef504..1901250 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/HelloEndpoint.java
@@ -14,34 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.it.schema.generic;
 
+package org.apache.servicecomb.swagger.generator.core.utils;
 
-import java.util.List;
-
-import org.springframework.stereotype.Service;
-
-@Service
-public class MyService implements IMyService {
-  @Override
-  public PersonBean hello(PersonBean a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean[] helloBody(PersonBean[] a) {
-    return a;
-  }
-
-  @Override
-  public List<PersonBean> helloList(List<PersonBean> a) {
-    return a;
-  }
-
+public class HelloEndpoint extends AbstractBaseClass<HelloBean> {
   @Override
-  public PersonBean actual() {
-    PersonBean p = new PersonBean();
-    p.setName("p");
-    return p;
+  public HelloBean get(HelloBean param) {
+    return param;
   }
 }
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/ServiceInterface.java
similarity index 59%
copy from integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
copy to swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/ServiceInterface.java
index 51ef504..ef58d03 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/ServiceInterface.java
@@ -14,34 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.it.schema.generic;
 
+package org.apache.servicecomb.swagger.generator.core.utils;
 
-import java.util.List;
-
-import org.springframework.stereotype.Service;
-
-@Service
-public class MyService implements IMyService {
-  @Override
-  public PersonBean hello(PersonBean a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean[] helloBody(PersonBean[] a) {
-    return a;
-  }
-
-  @Override
-  public List<PersonBean> helloList(List<PersonBean> a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean actual() {
-    PersonBean p = new PersonBean();
-    p.setName("p");
-    return p;
-  }
+public interface ServiceInterface extends BaseInterface<HelloBean> {
+  HelloBean getBase(HelloBean param);
 }
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/TestMethodUtils.java
similarity index 58%
copy from integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
copy to swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/TestMethodUtils.java
index 51ef504..ee57577 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/generic/MyService.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/utils/TestMethodUtils.java
@@ -14,34 +14,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.it.schema.generic;
 
+package org.apache.servicecomb.swagger.generator.core.utils;
 
+import java.lang.reflect.Method;
 import java.util.List;
 
-import org.springframework.stereotype.Service;
+import org.junit.Assert;
+import org.junit.Test;
 
-@Service
-public class MyService implements IMyService {
-  @Override
-  public PersonBean hello(PersonBean a) {
-    return a;
-  }
-
-  @Override
-  public PersonBean[] helloBody(PersonBean[] a) {
-    return a;
-  }
+public class TestMethodUtils {
+  @Test
+  public void testGetClassMethods() throws Exception {
+    List<Method> methods = MethodUtils.findProducerMethods(Hello2Endpoint.class);
+    Assert.assertEquals(3, methods.size());
 
-  @Override
-  public List<PersonBean> helloList(List<PersonBean> a) {
-    return a;
-  }
+    methods = MethodUtils.findProducerMethods(HelloEndpoint.class);
+    Assert.assertEquals(2, methods.size());
 
-  @Override
-  public PersonBean actual() {
-    PersonBean p = new PersonBean();
-    p.setName("p");
-    return p;
+    methods = MethodUtils.findProducerMethods(ServiceInterface.class);
+    Assert.assertEquals(3, methods.size());
   }
 }
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
index cca21c5..5be9562 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
@@ -34,8 +34,12 @@ import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory;
 import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
 import org.apache.servicecomb.swagger.invocation.extension.ProducerInvokeExtension;
 import org.apache.servicecomb.swagger.invocation.response.producer.ProducerResponseMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class SwaggerProducerOperation {
+  private static final Logger LOGGER = LoggerFactory.getLogger(SwaggerProducerOperation.class);
+
   private String name;
 
   // 因为存在aop场景,所以,producerClass不一定等于producerInstance.getClass()
@@ -153,6 +157,9 @@ public class SwaggerProducerOperation {
       asyncResp.handle(processException(invocation,
           new InvocationException(Status.BAD_REQUEST.getStatusCode(), "",
               new CommonExceptionData("Parameters not valid or types not match."), ae)));
+      LOGGER.error("Parameters not valid or types not match {}, "
+              + "debug this line to find the actual decode errors.",
+          invocation.getInvocationQualifiedName());
     } catch (Throwable e) {
       invocation.onBusinessMethodFinish();
       invocation.onBusinessFinish();
@@ -189,6 +196,9 @@ public class SwaggerProducerOperation {
       response = processException(invocation,
           new InvocationException(Status.BAD_REQUEST.getStatusCode(), "",
               new CommonExceptionData("Parameters not valid or types not match."), ae));
+      LOGGER.error("Parameters not valid or types not match {}, "
+              + "debug this line to find the actual decode errors.",
+          invocation.getInvocationQualifiedName());
     } catch (Throwable e) {
       invocation.onBusinessMethodFinish();
       invocation.onBusinessFinish();