wujimin closed pull request #699: [SCB-532] Support recursive dependency
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/699
 
 
   

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/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/CtType.java
 
b/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/CtType.java
index d0da1e010..4c53818e1 100644
--- 
a/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/CtType.java
+++ 
b/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/CtType.java
@@ -22,6 +22,7 @@
 import javassist.CtClass;
 import javassist.CtPrimitiveType;
 import javassist.NotFoundException;
+import javassist.bytecode.SignatureAttribute.ClassType;
 
 public class CtType {
   private static final ClassPool PRIMITIVE_CLASSPOOL = 
JavassistUtils.getOrCreateClassPool(int.class.getClassLoader());
@@ -32,11 +33,22 @@
 
   private String genericSignature;
 
+  public CtType(CtClass ctClass) {
+    ClassType classType = new ClassType(ctClass.getName(), null);
+    init(ctClass, false, classType.encode());
+  }
+
   public CtType(CtClass ctClass, boolean hasGenericTypes, String 
genericSignature) {
     init(ctClass, hasGenericTypes, genericSignature);
   }
 
   public CtType(JavaType javaType) {
+    if (CtTypeJavaType.class.isInstance(javaType)) {
+      CtType ctType = ((CtTypeJavaType) javaType).getType();
+      init(ctType.ctClass, ctType.hasGenericTypes, ctType.genericSignature);
+      return;
+    }
+
     ClassLoader classLoader = javaType.getRawClass().getClassLoader();
     try {
       ClassPool classPool = JavassistUtils.getOrCreateClassPool(classLoader);
diff --git 
a/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/CtTypeJavaType.java
 
b/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/CtTypeJavaType.java
new file mode 100644
index 000000000..6e03bd94d
--- /dev/null
+++ 
b/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/CtTypeJavaType.java
@@ -0,0 +1,52 @@
+/*
+ * 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.common.javassist;
+
+import com.fasterxml.jackson.databind.type.SimpleType;
+
+/**
+ * just a wrapper for CtType
+ * pending create class from CtClass to support recursive dependency class
+ */
+public class CtTypeJavaType extends SimpleType {
+  private CtType type;
+
+  public CtTypeJavaType(CtType type) {
+    super(CtTypeJavaType.class);
+    this.type = type;
+  }
+
+  public CtType getType() {
+    return type;
+  }
+
+  @Override
+  protected String buildCanonicalName() {
+    return type.getCtClass().getName();
+  }
+
+  @Override
+  public String getGenericSignature() {
+    return type.getGenericSignature();
+  }
+
+
+  @Override
+  public StringBuilder getGenericSignature(StringBuilder sb) {
+    return sb.append(type.getGenericSignature());
+  }
+}
diff --git 
a/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/JavassistUtils.java
 
b/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/JavassistUtils.java
index 025ea9474..66bb661e1 100644
--- 
a/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/JavassistUtils.java
+++ 
b/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/JavassistUtils.java
@@ -139,7 +139,7 @@ private static void addEnumValuesMethod(CtClass ctClass, 
List<String> values) th
     return createClass(null, config);
   }
 
-  public static Class<?> createClass(ClassLoader classLoader, ClassConfig 
config) {
+  public static CtClass createCtClass(ClassLoader classLoader, ClassConfig 
config) {
     if (classLoader == null) {
       classLoader = Thread.currentThread().getContextClassLoader();
     }
@@ -185,10 +185,47 @@ private static void addEnumValuesMethod(CtClass ctClass, 
List<String> values) th
         }
       }
 
-      LOGGER.info("generate {} in classLoader {}.", config.getClassName(), 
classLoader);
-      return ctClass.toClass(classLoader, null);
+      LOGGER.info("create CtClass {} in classLoader {}.", 
config.getClassName(), classLoader);
+      return ctClass;
+    } catch (Throwable e) {
+      throw new IllegalStateException(
+          String.format("Failed to create CtClass %s in classLoader %s.", 
config.getClassName(),
+              classLoader), e);
+    }
+  }
+
+  public static Class<?> createClass(ClassLoader classLoader, ClassConfig 
config) {
+    if (classLoader == null) {
+      classLoader = Thread.currentThread().getContextClassLoader();
+    }
+
+    CtClass ctClass = createCtClass(classLoader, config);
+    return createClass(classLoader, ctClass);
+  }
+
+  public static Class<?> createClass(ClassLoader classLoader, CtClass ctClass) 
{
+    if (classLoader == null) {
+      classLoader = Thread.currentThread().getContextClassLoader();
+    }
+
+    String clsName = ctClass.getName();
+    try {
+      // must try load from classloader first
+      // because class A depend on class B
+      // when load class A, will load class B
+      // after this, if CtClass B invoke toClass again, will cause problem.
+      return classLoader.loadClass(clsName);
+    } catch (ClassNotFoundException e) {
+      // ignore it
+    }
+
+    try {
+      Class<?> cls = ctClass.toClass(classLoader, null);
+      LOGGER.info("create class {} in classLoader {}.", clsName, classLoader);
+      return cls;
     } catch (Throwable e) {
-      throw new Error(String.format("Failed to create %s in classLoader %s.", 
config.getClassName(), classLoader), e);
+      throw new IllegalStateException(
+          String.format("Failed to create %s in classLoader %s.", clsName, 
classLoader), e);
     }
   }
 
diff --git 
a/common/common-javassist/src/test/java/org/apache/servicecomb/common/javassist/TestCtType.java
 
b/common/common-javassist/src/test/java/org/apache/servicecomb/common/javassist/TestCtType.java
index 40ecd7b3a..1bf190737 100644
--- 
a/common/common-javassist/src/test/java/org/apache/servicecomb/common/javassist/TestCtType.java
+++ 
b/common/common-javassist/src/test/java/org/apache/servicecomb/common/javassist/TestCtType.java
@@ -25,6 +25,7 @@
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
+import javassist.ClassPool;
 import javassist.CtClass;
 import javassist.NotFoundException;
 
@@ -33,6 +34,17 @@
 
   @Test
   public void fromCtClass() {
+    CtClass ctClass = Mockito.mock(CtClass.class);
+    Mockito.when(ctClass.getName()).thenReturn("a.b.c");
+    ctType = new CtType(ctClass);
+
+    Assert.assertSame(ctClass, ctType.getCtClass());
+    Assert.assertFalse(ctType.hasGenericTypes());
+    Assert.assertEquals("La/b/c;", ctType.getGenericSignature());
+  }
+
+  @Test
+  public void fromCtClass_fullInfo() {
     CtClass ctClass = Mockito.mock(CtClass.class);
     ctType = new CtType(ctClass, true, "Ljava/util/List<[B;>;");
 
@@ -87,4 +99,17 @@ public void fromJavaType_listBytes() throws 
NotFoundException {
     Assert.assertTrue(ctType.hasGenericTypes());
     Assert.assertEquals("Ljava/util/List<[B>;", ctType.getGenericSignature());
   }
+
+  @Test
+  public void fromCtTypeJavaType() throws NotFoundException {
+    CtClass ctClass = 
ClassPool.getDefault().get(String.class.getCanonicalName());
+    CtType otherCtType = new CtType(ctClass, false, "Ljava/lang/String;");
+    CtTypeJavaType ctTypeJavaType = new CtTypeJavaType(otherCtType);
+
+    ctType = new CtType(ctTypeJavaType);
+
+    Assert.assertSame(ctClass, ctType.getCtClass());
+    Assert.assertFalse(ctType.hasGenericTypes());
+    Assert.assertEquals("Ljava/lang/String;", ctType.getGenericSignature());
+  }
 }
diff --git 
a/common/common-javassist/src/test/java/org/apache/servicecomb/common/javassist/TestCtTypeJavaType.java
 
b/common/common-javassist/src/test/java/org/apache/servicecomb/common/javassist/TestCtTypeJavaType.java
new file mode 100644
index 000000000..46213a316
--- /dev/null
+++ 
b/common/common-javassist/src/test/java/org/apache/servicecomb/common/javassist/TestCtTypeJavaType.java
@@ -0,0 +1,48 @@
+/*
+ * 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.common.javassist;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+public class TestCtTypeJavaType {
+  Class<?> cls = TestCtTypeJavaType.class;
+
+  JavaType javaType = TypeFactory.defaultInstance().constructType(cls);
+
+  CtType ctType = new CtType(javaType);
+
+  CtTypeJavaType ctTypeJavaType = new CtTypeJavaType(ctType);
+
+  @Test
+  public void construct() {
+    Assert.assertSame(ctType, ctTypeJavaType.getType());
+    Assert.assertEquals(cls.getTypeName(), 
ctTypeJavaType.buildCanonicalName());
+  }
+
+  @Test
+  public void getGenericSignature() {
+    JavaType listJavaType = 
TypeFactory.defaultInstance().constructCollectionType(List.class, 
ctTypeJavaType);
+    
Assert.assertEquals("Ljava/util/List<Lorg/apache/servicecomb/common/javassist/TestCtTypeJavaType;>;",
+        listJavaType.getGenericSignature());
+  }
+}
diff --git 
a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java
 
b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java
index e24f36ebd..dc346fa9c 100644
--- 
a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java
+++ 
b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java
@@ -28,12 +28,15 @@
 import org.apache.commons.lang.StringUtils;
 import org.apache.servicecomb.demo.edge.model.AppClientDataRsp;
 import org.apache.servicecomb.demo.edge.model.ChannelRequestBase;
+import org.apache.servicecomb.demo.edge.model.DependTypeA;
+import org.apache.servicecomb.demo.edge.model.RecursiveSelfType;
 import org.apache.servicecomb.demo.edge.model.ResultWithInstance;
 import org.apache.servicecomb.provider.rest.common.RestSchema;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
@@ -93,4 +96,14 @@ protected File createBigFile() throws IOException {
   public File bigFile() throws IOException {
     return createBigFile();
   }
+
+  @PostMapping(path = "recursiveSelf")
+  public RecursiveSelfType recursiveSelf(@RequestBody RecursiveSelfType value) 
{
+    return value;
+  }
+
+  @PostMapping(path = "dependType")
+  public DependTypeA dependType(@RequestBody DependTypeA value) {
+    return value;
+  }
 }
diff --git 
a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java
 
b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java
index 7bdbb544d..cff8d62b4 100644
--- 
a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java
+++ 
b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java
@@ -29,6 +29,9 @@
 import org.apache.servicecomb.core.endpoint.EndpointsCache;
 import org.apache.servicecomb.demo.edge.model.AppClientDataRsp;
 import org.apache.servicecomb.demo.edge.model.ChannelRequestBase;
+import org.apache.servicecomb.demo.edge.model.DependTypeA;
+import org.apache.servicecomb.demo.edge.model.DependTypeB;
+import org.apache.servicecomb.demo.edge.model.RecursiveSelfType;
 import org.apache.servicecomb.demo.edge.model.ResultWithInstance;
 import org.apache.servicecomb.foundation.common.net.URIEndpointObject;
 import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder;
@@ -78,6 +81,8 @@ public Consumer() {
   public void run() {
     prepareEdge();
 
+    testRecursiveSelf();
+    testDependType();
     testDownload();
     testDownloadBigFile();
 
@@ -106,6 +111,40 @@ public void run() {
     checkResult("v2/dec", decV2Result, "2.0.0");
   }
 
+  protected void testRecursiveSelf() {
+    String url = edgePrefix + "/v2/recursiveSelf";
+
+    HttpHeaders headers = new HttpHeaders();
+    headers.setContentType(MediaType.APPLICATION_JSON);
+
+    RecursiveSelfType recursiveSelfType = new RecursiveSelfType();
+    recursiveSelfType.setField(new RecursiveSelfType());
+    recursiveSelfType.getField().setValue(10);
+
+    HttpEntity<RecursiveSelfType> entity = new HttpEntity<>(recursiveSelfType, 
headers);
+
+    RecursiveSelfType response = template.postForObject(url, entity, 
RecursiveSelfType.class);
+    Assert.isTrue(response.getValue() == 0, "default must be 0");
+    Assert.isTrue(response.getField().getValue() == 10, "must be 10");
+    Assert.isNull(response.getField().getField(), "must be null");
+  }
+
+  protected void testDependType() {
+    String url = edgePrefix + "/v2/dependType";
+
+    HttpHeaders headers = new HttpHeaders();
+    headers.setContentType(MediaType.APPLICATION_JSON);
+
+    DependTypeA dependTypeA = new DependTypeA();
+    dependTypeA.setB(new DependTypeB());
+    dependTypeA.getB().setValue(10);
+
+    HttpEntity<DependTypeA> entity = new HttpEntity<>(dependTypeA, headers);
+
+    DependTypeA response = template.postForObject(url, entity, 
DependTypeA.class);
+    Assert.isTrue(response.getB().getValue() == 10, "must be 10");
+  }
+
   protected void testDownloadBigFile() {
     String url = edgePrefix + "/v2/bigFile";
     AtomicInteger size = new AtomicInteger();
@@ -180,7 +219,7 @@ protected void invokeBusiness(String urlPrefix, 
ChannelRequestBase request) {
     HttpHeaders headers = new HttpHeaders();
     headers.setContentType(MediaType.APPLICATION_JSON);
 
-    HttpEntity<ChannelRequestBase> entity = new 
HttpEntity<ChannelRequestBase>(request, headers);
+    HttpEntity<ChannelRequestBase> entity = new HttpEntity<>(request, headers);
 
     ResponseEntity<AppClientDataRsp> response = template.postForEntity(url, 
entity, AppClientDataRsp.class);
     System.out.println("urlPrefix: " + urlPrefix);
diff --git 
a/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/DependTypeA.java
 
b/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/DependTypeA.java
new file mode 100644
index 000000000..605cc88c3
--- /dev/null
+++ 
b/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/DependTypeA.java
@@ -0,0 +1,29 @@
+/*
+ * 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.edge.model;
+
+public class DependTypeA {
+  private DependTypeB b;
+
+  public DependTypeB getB() {
+    return b;
+  }
+
+  public void setB(DependTypeB b) {
+    this.b = b;
+  }
+}
diff --git 
a/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/DependTypeB.java
 
b/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/DependTypeB.java
new file mode 100644
index 000000000..19067900c
--- /dev/null
+++ 
b/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/DependTypeB.java
@@ -0,0 +1,39 @@
+/*
+ * 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.edge.model;
+
+public class DependTypeB {
+  private DependTypeA a;
+
+  private int value;
+
+  public DependTypeA getA() {
+    return a;
+  }
+
+  public void setA(DependTypeA a) {
+    this.a = a;
+  }
+
+  public int getValue() {
+    return value;
+  }
+
+  public void setValue(int value) {
+    this.value = value;
+  }
+}
diff --git 
a/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/RecursiveSelfType.java
 
b/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/RecursiveSelfType.java
new file mode 100644
index 000000000..2ae58adcf
--- /dev/null
+++ 
b/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/RecursiveSelfType.java
@@ -0,0 +1,39 @@
+/*
+ * 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.edge.model;
+
+public class RecursiveSelfType {
+  private RecursiveSelfType field;
+
+  private int value;
+
+  public RecursiveSelfType getField() {
+    return field;
+  }
+
+  public void setField(RecursiveSelfType field) {
+    this.field = field;
+  }
+
+  public int getValue() {
+    return value;
+  }
+
+  public void setValue(int value) {
+    this.value = value;
+  }
+}
diff --git 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/AbstractConverter.java
 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/AbstractConverter.java
index f23f8daec..fbd9e486d 100644
--- 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/AbstractConverter.java
+++ 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/AbstractConverter.java
@@ -41,9 +41,10 @@ public JavaType convert(SwaggerToClassGenerator 
swaggerToClassGenerator, Object
     Map<String, Object> vendorExtensions = findVendorExtensions(def);
     String canonical = ClassUtils.getClassName(vendorExtensions);
     if (!StringUtils.isEmpty(canonical)) {
-      Class<?> clsResult = 
ClassUtils.getClassByName(swaggerToClassGenerator.getClassLoader(), canonical);
-      if (clsResult != null) {
-        return typeFactory.constructType(clsResult);
+      try {
+        return 
swaggerToClassGenerator.getTypeFactory().constructFromCanonical(canonical);
+      } catch (Throwable e) {
+        // ignore this
       }
     }
 
diff --git 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/SwaggerToClassGenerator.java
 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/SwaggerToClassGenerator.java
index 3205c0227..1db2db309 100644
--- 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/SwaggerToClassGenerator.java
+++ 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/SwaggerToClassGenerator.java
@@ -22,6 +22,7 @@
 import java.util.Map.Entry;
 
 import org.apache.servicecomb.common.javassist.ClassConfig;
+import org.apache.servicecomb.common.javassist.CtTypeJavaType;
 import org.apache.servicecomb.common.javassist.JavassistUtils;
 import org.apache.servicecomb.common.javassist.MethodConfig;
 import org.apache.servicecomb.swagger.generator.core.SwaggerConst;
@@ -39,6 +40,8 @@
 import io.swagger.models.Swagger;
 import io.swagger.models.parameters.Parameter;
 import io.swagger.models.properties.Property;
+import javassist.ClassPool;
+import javassist.CtClass;
 
 /**
  * generate interface from swagger<br>
@@ -85,6 +88,8 @@
 
   private TypeFactory typeFactory;
 
+  private ClassPool classPool;
+
   // key is swagger model or property
   @VisibleForTesting
   protected Map<Object, JavaType> swaggerObjectMap = new IdentityHashMap<>();
@@ -101,6 +106,11 @@ public SwaggerToClassGenerator(ClassLoader classLoader, 
Swagger swagger, String
     this.packageName = packageName;
 
     this.typeFactory = 
TypeFactory.defaultInstance().withClassLoader(classLoader);
+    this.classPool = JavassistUtils.getOrCreateClassPool(classLoader);
+  }
+
+  public ClassPool getClassPool() {
+    return classPool;
   }
 
   public void setInterfaceName(String interfaceName) {
@@ -136,6 +146,7 @@ public TypeFactory getTypeFactory() {
     mapDefinitionsToExistingClasses();
     convertDefinitions();
     convertResponses();
+    convertPendingCtClasses();
     convertToInterface();
 
     return interfaceCls;
@@ -232,6 +243,19 @@ protected void convertToInterface() {
     interfaceCls = JavassistUtils.createClass(classLoader, classConfig);
   }
 
+  protected void convertPendingCtClasses() {
+    for (Entry<Object, JavaType> entry : swaggerObjectMap.entrySet()) {
+      JavaType javaType = entry.getValue();
+      if (!CtTypeJavaType.class.isInstance(javaType)) {
+        continue;
+      }
+
+      CtClass ctClass = ((CtTypeJavaType) javaType).getType().getCtClass();
+      Class<?> cls = JavassistUtils.createClass(classLoader, ctClass);
+      entry.setValue(typeFactory.constructType(cls));
+    }
+  }
+
   public JavaType convert(Object swaggerObject) {
     JavaType javaType = swaggerObjectMap.get(swaggerObject);
     if (javaType == null) {
@@ -241,6 +265,16 @@ public JavaType convert(Object swaggerObject) {
     return javaType;
   }
 
+  /**
+   * just only for invoker know that there is no recursive dependency
+   *
+   */
+  public JavaType forceConvert(Object swaggerObject) {
+    convert(swaggerObject);
+    convertPendingCtClasses();
+    return swaggerObjectMap.get(swaggerObject);
+  }
+
   protected void updateJavaClassInVendor(Map<String, Object> vendorExtensions, 
String shortClsName) {
     String clsName = ClassUtils.getClassName(vendorExtensions);
     if (StringUtils.isEmpty(clsName)) {
diff --git 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/model/ModelImplConverter.java
 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/model/ModelImplConverter.java
index 827c07bb4..fa38d7432 100644
--- 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/model/ModelImplConverter.java
+++ 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/model/ModelImplConverter.java
@@ -21,6 +21,8 @@
 import java.util.Map.Entry;
 
 import org.apache.servicecomb.common.javassist.ClassConfig;
+import org.apache.servicecomb.common.javassist.CtType;
+import org.apache.servicecomb.common.javassist.CtTypeJavaType;
 import org.apache.servicecomb.common.javassist.JavassistUtils;
 import org.apache.servicecomb.swagger.converter.ConverterMgr;
 import org.apache.servicecomb.swagger.converter.SwaggerToClassGenerator;
@@ -33,6 +35,7 @@
 import io.swagger.models.ModelImpl;
 import io.swagger.models.properties.ObjectProperty;
 import io.swagger.models.properties.Property;
+import javassist.CtClass;
 
 public class ModelImplConverter extends AbstractModelConverter {
   @Override
@@ -65,18 +68,31 @@ protected JavaType getOrCreateType(SwaggerToClassGenerator 
swaggerToClassGenerat
     String clsName = ClassUtils.getClassName(findVendorExtensions(modelImpl));
     clsName = ClassUtils.correctClassName(clsName);
 
-    Class<?> cls = getOrCreateClass(swaggerToClassGenerator, 
modelImpl.getProperties(), clsName);
-    return TypeFactory.defaultInstance().constructType(cls);
+    return getOrCreateType(swaggerToClassGenerator, modelImpl.getProperties(), 
clsName);
   }
 
-  protected Class<?> getOrCreateClass(SwaggerToClassGenerator 
swaggerToClassGenerator,
+  protected JavaType getOrCreateType(SwaggerToClassGenerator 
swaggerToClassGenerator,
       Map<String, Property> properties,
       String clsName) {
     Class<?> cls = 
ClassUtils.getClassByName(swaggerToClassGenerator.getClassLoader(), clsName);
     if (cls != null) {
-      return cls;
+      return swaggerToClassGenerator.getTypeFactory().constructType(cls);
     }
 
+    CtClass ctClass = getOrCreateCtClass(swaggerToClassGenerator, properties, 
clsName);
+    return new CtTypeJavaType(new CtType(ctClass));
+  }
+
+  private CtClass getOrCreateCtClass(SwaggerToClassGenerator 
swaggerToClassGenerator, Map<String, Property> properties,
+      String clsName) {
+    CtClass ctClass = 
swaggerToClassGenerator.getClassPool().getOrNull(clsName);
+    if (ctClass != null) {
+      return ctClass;
+    }
+
+    // must ensure already create CtClass, otherwise recursive dependency 
class will create failed.
+    swaggerToClassGenerator.getClassPool().makeClass(clsName);
+
     ClassConfig classConfig = new ClassConfig();
     classConfig.setClassName(clsName);
 
@@ -87,7 +103,6 @@ protected JavaType getOrCreateType(SwaggerToClassGenerator 
swaggerToClassGenerat
       }
     }
 
-    cls = JavassistUtils.createClass(swaggerToClassGenerator.getClassLoader(), 
classConfig);
-    return cls;
+    return 
JavassistUtils.createCtClass(swaggerToClassGenerator.getClassLoader(), 
classConfig);
   }
 }
diff --git 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/property/ArrayPropertyConverter.java
 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/property/ArrayPropertyConverter.java
index fb0631c48..e7f8d161e 100644
--- 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/property/ArrayPropertyConverter.java
+++ 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/property/ArrayPropertyConverter.java
@@ -24,7 +24,6 @@
 import org.apache.servicecomb.swagger.converter.SwaggerToClassGenerator;
 
 import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.type.TypeFactory;
 
 import io.swagger.models.properties.ArrayProperty;
 import io.swagger.models.properties.Property;
@@ -40,7 +39,7 @@ public static JavaType findJavaType(SwaggerToClassGenerator 
swaggerToClassGenera
     if (Boolean.TRUE.equals(uniqueItems)) {
       collectionClass = Set.class;
     }
-    return 
TypeFactory.defaultInstance().constructCollectionType(collectionClass, 
itemJavaType);
+    return 
swaggerToClassGenerator.getTypeFactory().constructCollectionType(collectionClass,
 itemJavaType);
   }
 
   @Override
diff --git 
a/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/converter/model/TestModelImplConverter.java
 
b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/converter/model/TestModelImplConverter.java
index 6e0e178b9..be5dbdcf4 100644
--- 
a/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/converter/model/TestModelImplConverter.java
+++ 
b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/converter/model/TestModelImplConverter.java
@@ -102,7 +102,7 @@ public void convert_empty() {
     Model model = swagger.getDefinitions().get(Empty.class.getSimpleName());
     model.getVendorExtensions().put(SwaggerConst.EXT_JAVA_CLASS, "pkg.Empty");
 
-    JavaType javaType = swaggerToClassGenerator.convert(model);
+    JavaType javaType = swaggerToClassGenerator.forceConvert(model);
 
     Assert.assertEquals("pkg.Empty", javaType.getRawClass().getName());
   }
@@ -125,7 +125,7 @@ public void convert_createClass() throws 
NoSuchFieldException {
 
     swagger.addDefinition("cls", model);
 
-    JavaType javaType = swaggerToClassGenerator.convert(model);
+    JavaType javaType = swaggerToClassGenerator.forceConvert(model);
 
     Class<?> cls = javaType.getRawClass();
     Assert.assertEquals("pkg.Model", cls.getName());
diff --git 
a/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/TestSwaggerToClassGenerator_base.java
 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/TestSwaggerToClassGenerator_base.java
new file mode 100644
index 000000000..3ef0189d2
--- /dev/null
+++ 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/TestSwaggerToClassGenerator_base.java
@@ -0,0 +1,55 @@
+/*
+ * 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.converter.swaggerToClassGenerator;
+
+import org.apache.servicecomb.common.javassist.JavassistUtils;
+import org.apache.servicecomb.swagger.converter.SwaggerToClassGenerator;
+import org.apache.servicecomb.swagger.generator.core.SwaggerConst;
+import org.apache.servicecomb.swagger.generator.core.SwaggerGenerator;
+import org.apache.servicecomb.swagger.generator.core.SwaggerGeneratorContext;
+import 
org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGeneratorContext;
+
+import io.swagger.models.Model;
+import io.swagger.models.Swagger;
+
+public class TestSwaggerToClassGenerator_base {
+  ClassLoader classLoader = new ClassLoader() {
+  };
+
+  SwaggerGeneratorContext context = new SpringmvcSwaggerGeneratorContext();
+
+  SwaggerGenerator swaggerGenerator = new SwaggerGenerator(context, 
ToClassSchema.class);
+
+  Swagger swagger = swaggerGenerator.generate();
+
+  SwaggerToClassGenerator swaggerToClassGenerator = new 
SwaggerToClassGenerator(classLoader, swagger, "gen");
+
+  Class<?> swaggerIntf;
+
+  public TestSwaggerToClassGenerator_base(boolean clearXJavaClass) {
+    if (clearXJavaClass) {
+      for (Model model : swagger.getDefinitions().values()) {
+        model.getVendorExtensions().remove(SwaggerConst.EXT_JAVA_CLASS);
+      }
+    }
+    swaggerIntf = swaggerToClassGenerator.convert();
+  }
+
+  public void tearDown() {
+    JavassistUtils.clearByClassLoader(classLoader);
+  }
+}
diff --git 
a/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/TestSwaggerToClassGenerator_create.java
 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/TestSwaggerToClassGenerator_create.java
new file mode 100644
index 000000000..bfd713812
--- /dev/null
+++ 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/TestSwaggerToClassGenerator_create.java
@@ -0,0 +1,61 @@
+/*
+ * 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.converter.swaggerToClassGenerator;
+
+import java.lang.reflect.Method;
+
+import org.apache.servicecomb.foundation.common.utils.ReflectUtils;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestSwaggerToClassGenerator_create {
+  static TestSwaggerToClassGenerator_base base = new 
TestSwaggerToClassGenerator_base(true);
+
+  @AfterClass
+  public static void tearDown() {
+    base.tearDown();
+  }
+
+  @Test
+  public void recursiveSelf() throws NoSuchFieldException {
+    Method method = ReflectUtils.findMethod(base.swaggerIntf, "recursiveSelf");
+    Class<?> returnType = method.getReturnType();
+
+    Assert.assertEquals("gen.RecursiveSelfType", returnType.getName());
+    Assert.assertEquals("gen.RecursiveSelfType", 
returnType.getField("field").getType().getName());
+  }
+
+  @Test
+  public void dependType() throws NoSuchFieldException {
+    Method method = ReflectUtils.findMethod(base.swaggerIntf, "dependType");
+    Class<?> returnType = method.getReturnType();
+
+    Assert.assertEquals("gen.DependTypeA", returnType.getName());
+    Assert.assertEquals("gen.DependTypeB", 
returnType.getField("b").getType().getName());
+  }
+
+  @Test
+  public void generic() throws NoSuchFieldException {
+    Method method = ReflectUtils.findMethod(base.swaggerIntf, "generic");
+    Class<?> returnType = method.getReturnType();
+
+    Assert.assertEquals("gen.GenericRecursiveSelfTypeDependTypeA", 
returnType.getName());
+    Assert.assertEquals("gen.RecursiveSelfType", 
returnType.getField("v1").getType().getName());
+    Assert.assertEquals("gen.DependTypeA", 
returnType.getField("v2").getType().getName());
+  }
+}
diff --git 
a/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/TestSwaggerToClassGenerator_reuse.java
 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/TestSwaggerToClassGenerator_reuse.java
new file mode 100644
index 000000000..e4a067117
--- /dev/null
+++ 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/TestSwaggerToClassGenerator_reuse.java
@@ -0,0 +1,63 @@
+/*
+ * 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.converter.swaggerToClassGenerator;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+
+import org.apache.servicecomb.foundation.common.utils.ReflectUtils;
+import 
org.apache.servicecomb.swagger.converter.swaggerToClassGenerator.model.DependTypeA;
+import 
org.apache.servicecomb.swagger.converter.swaggerToClassGenerator.model.Generic;
+import 
org.apache.servicecomb.swagger.converter.swaggerToClassGenerator.model.RecursiveSelfType;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestSwaggerToClassGenerator_reuse {
+  static TestSwaggerToClassGenerator_base base = new 
TestSwaggerToClassGenerator_base(false);
+
+  @AfterClass
+  public static void tearDown() {
+    base.tearDown();
+  }
+
+  @Test
+  public void recursiveSelf() {
+    Method method = ReflectUtils.findMethod(base.swaggerIntf, "recursiveSelf");
+    Class<?> returnType = method.getReturnType();
+
+    Assert.assertSame(RecursiveSelfType.class, returnType);
+  }
+
+  @Test
+  public void dependType() {
+    Method method = ReflectUtils.findMethod(base.swaggerIntf, "dependType");
+    Class<?> returnType = method.getReturnType();
+
+    Assert.assertSame(DependTypeA.class, returnType);
+  }
+
+  @Test
+  public void generic() {
+    Method method = ReflectUtils.findMethod(base.swaggerIntf, "generic");
+    ParameterizedType returnType = (ParameterizedType) 
method.getGenericReturnType();
+
+    Assert.assertSame(Generic.class, returnType.getRawType());
+    Assert.assertSame(RecursiveSelfType.class, 
returnType.getActualTypeArguments()[0]);
+    Assert.assertSame(DependTypeA.class, 
returnType.getActualTypeArguments()[1]);
+  }
+}
diff --git 
a/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/ToClassSchema.java
 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/ToClassSchema.java
new file mode 100644
index 000000000..e0f6cacdd
--- /dev/null
+++ 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/ToClassSchema.java
@@ -0,0 +1,42 @@
+/*
+ * 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.converter.swaggerToClassGenerator;
+
+
+import 
org.apache.servicecomb.swagger.converter.swaggerToClassGenerator.model.DependTypeA;
+import 
org.apache.servicecomb.swagger.converter.swaggerToClassGenerator.model.Generic;
+import 
org.apache.servicecomb.swagger.converter.swaggerToClassGenerator.model.RecursiveSelfType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@RequestMapping(path = "/")
+public class ToClassSchema {
+  @GetMapping(path = "recursiveSelf")
+  public RecursiveSelfType recursiveSelf() {
+    return null;
+  }
+
+  @GetMapping(path = "dependType")
+  public DependTypeA dependType() {
+    return null;
+  }
+
+  @GetMapping(path = "generic")
+  public Generic<RecursiveSelfType, DependTypeA> generic() {
+    return null;
+  }
+}
diff --git 
a/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/DependTypeA.java
 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/DependTypeA.java
new file mode 100644
index 000000000..3fc8a96d1
--- /dev/null
+++ 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/DependTypeA.java
@@ -0,0 +1,29 @@
+/*
+ * 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.converter.swaggerToClassGenerator.model;
+
+public class DependTypeA {
+  private DependTypeB b;
+
+  public DependTypeB getB() {
+    return b;
+  }
+
+  public void setB(DependTypeB b) {
+    this.b = b;
+  }
+}
diff --git 
a/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/DependTypeB.java
 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/DependTypeB.java
new file mode 100644
index 000000000..5957ca32f
--- /dev/null
+++ 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/DependTypeB.java
@@ -0,0 +1,29 @@
+/*
+ * 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.converter.swaggerToClassGenerator.model;
+
+public class DependTypeB {
+  private DependTypeA a;
+
+  public DependTypeA getA() {
+    return a;
+  }
+
+  public void setA(DependTypeA a) {
+    this.a = a;
+  }
+}
diff --git 
a/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/Generic.java
 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/Generic.java
new file mode 100644
index 000000000..69aec3d6b
--- /dev/null
+++ 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/Generic.java
@@ -0,0 +1,39 @@
+/*
+ * 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.converter.swaggerToClassGenerator.model;
+
+public class Generic<T1, T2> {
+  private T1 v1;
+
+  private T2 v2;
+
+  public T1 getV1() {
+    return v1;
+  }
+
+  public void setV1(T1 v1) {
+    this.v1 = v1;
+  }
+
+  public T2 getV2() {
+    return v2;
+  }
+
+  public void setV2(T2 v2) {
+    this.v2 = v2;
+  }
+}
diff --git 
a/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/RecursiveSelfType.java
 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/RecursiveSelfType.java
new file mode 100644
index 000000000..9b8b663d4
--- /dev/null
+++ 
b/swagger/swagger-generator/generator-springmvc/src/test/java/org/apache/servicecomb/swagger/converter/swaggerToClassGenerator/model/RecursiveSelfType.java
@@ -0,0 +1,29 @@
+/*
+ * 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.converter.swaggerToClassGenerator.model;
+
+public class RecursiveSelfType {
+  private RecursiveSelfType field;
+
+  public RecursiveSelfType getField() {
+    return field;
+  }
+
+  public void setField(RecursiveSelfType field) {
+    this.field = field;
+  }
+}


 

----------------------------------------------------------------
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


With regards,
Apache Git Services

Reply via email to