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 2018/01/18 03:43:26 UTC

[incubator-servicecomb-java-chassis] 05/05: SCB-251 add Object demo

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/incubator-servicecomb-java-chassis.git

commit 7ad8ce25d0462dcabac3bc4a8f7f3044cb8572a7
Author: wujimin <wu...@huawei.com>
AuthorDate: Thu Jan 18 00:23:19 2018 +0800

    SCB-251 add Object demo
---
 .../jaxrs/client/CodeFirstRestTemplateJaxrs.java   |   6 +-
 .../servicecomb/demo/CodeFirstRestTemplate.java    |  84 +++++----
 .../org/apache/servicecomb/demo/EmptyObject.java}  |  14 +-
 .../java/org/apache/servicecomb/demo/TestMgr.java  |   4 +
 .../client/CodeFirstRestTemplateSpringmvc.java     |  44 ++---
 .../springmvc/client/CodeFirstSprigmvcIntf.java    |  18 ++
 .../demo/springmvc/client/TestObject.java          | 196 +++++++++++++++++++++
 .../demo/springmvc/client/TestResponse.java        |  65 +++++++
 .../demo/springmvc/server/CodeFirstSpringmvc.java  |  39 +++-
 9 files changed, 386 insertions(+), 84 deletions(-)

diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java
index d58b91e..935ad52 100644
--- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java
+++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java
@@ -23,10 +23,10 @@ import org.springframework.web.client.RestTemplate;
 
 public class CodeFirstRestTemplateJaxrs extends CodeFirstRestTemplate {
   @Override
-  protected void testExtend(RestTemplate template, String cseUrlPrefix) {
-    super.testExtend(template, cseUrlPrefix);
-
+  protected void testAllTransport(String microserviceName, RestTemplate template, String cseUrlPrefix) {
     testDefaultPath(template, cseUrlPrefix);
+
+    super.testAllTransport(microserviceName, template, cseUrlPrefix);
   }
 
   private void testDefaultPath(RestTemplate template, String cseUrlPrefix) {
diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java
index ac8d82c..4512e59 100644
--- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java
@@ -40,46 +40,58 @@ import org.springframework.web.client.RestTemplate;
 import io.vertx.core.json.JsonObject;
 
 public class CodeFirstRestTemplate {
+  protected void changeTransport(String microserviceName, String transport) {
+    CseContext.getInstance().getConsumerProviderManager().setTransport(microserviceName, transport);
+    TestMgr.setMsg(microserviceName, transport);
+  }
+
   public void testCodeFirst(RestTemplate template, String microserviceName, String basePath) {
+    String cseUrlPrefix = "cse://" + microserviceName + basePath;
+    changeTransport(microserviceName, "highway");
+    testOnlyHighway(template, cseUrlPrefix);
+
+    changeTransport(microserviceName, Const.RESTFUL);
+    testOnlyRest(template, cseUrlPrefix);
+
     for (String transport : DemoConst.transports) {
-      CseContext.getInstance().getConsumerProviderManager().setTransport(microserviceName, transport);
-      TestMgr.setMsg(microserviceName, transport);
-
-      String cseUrlPrefix = "cse://" + microserviceName + basePath;
-
-      testExtend(template, cseUrlPrefix);
-
-      testCodeFirstUserMap(template, cseUrlPrefix);
-      testCodeFirstTextPlain(template, cseUrlPrefix);
-      testCodeFirstBytes(template, cseUrlPrefix);
-      testCseResponse(microserviceName, template, cseUrlPrefix);
-      testCodeFirstAddDate(template, cseUrlPrefix);
-
-      testCodeFirstAdd(template, cseUrlPrefix);
-      testCodeFirstAddString(template, cseUrlPrefix);
-      testCodeFirstIsTrue(template, cseUrlPrefix);
-      testCodeFirstSayHi2(template, cseUrlPrefix);
-      testCodeFirstSayHi(template, cseUrlPrefix);
-      testCodeFirstSaySomething(template, cseUrlPrefix);
-      //            testCodeFirstRawJsonString(template, cseUrlPrefix);
-      testCodeFirstSayHello(template, cseUrlPrefix);
-      testCodeFirstReduce(template, cseUrlPrefix);
-
-      // TODO: highway unsupported until JAV-394 completed
-      if (transport.equals("rest")) {
-        testOnlyRest(template, cseUrlPrefix);
-        // only rest transport will set trace id
-        testTraceIdOnNotSetBefore(template, cseUrlPrefix);
-      }
-
-      testTraceIdOnContextContainsTraceId(template, cseUrlPrefix);
-
-      testRawJson(template, cseUrlPrefix);
+      changeTransport(microserviceName, transport);
+      testAllTransport(microserviceName, template, cseUrlPrefix);
     }
   }
 
+  protected void testAllTransport(String microserviceName, RestTemplate template, String cseUrlPrefix) {
+    testCodeFirstUserMap(template, cseUrlPrefix);
+    testCodeFirstTextPlain(template, cseUrlPrefix);
+    testCodeFirstBytes(template, cseUrlPrefix);
+    testCseResponse(microserviceName, template, cseUrlPrefix);
+    testCodeFirstAddDate(template, cseUrlPrefix);
+
+    testCodeFirstAdd(template, cseUrlPrefix);
+    testCodeFirstAddString(template, cseUrlPrefix);
+    testCodeFirstIsTrue(template, cseUrlPrefix);
+    testCodeFirstSayHi2(template, cseUrlPrefix);
+    testCodeFirstSayHi(template, cseUrlPrefix);
+    testCodeFirstSaySomething(template, cseUrlPrefix);
+    //            testCodeFirstRawJsonString(template, cseUrlPrefix);
+    testCodeFirstSayHello(template, cseUrlPrefix);
+    testCodeFirstReduce(template, cseUrlPrefix);
+
+    testTraceIdOnContextContainsTraceId(template, cseUrlPrefix);
+
+    testRawJson(template, cseUrlPrefix);
+  }
+
+  protected void testOnlyHighway(RestTemplate template, String cseUrlPrefix) {
+
+  }
+
   protected void testOnlyRest(RestTemplate template, String cseUrlPrefix) {
+    // TODO: highway unsupported until JAV-394 completed
     testModelFieldIgnore(template, cseUrlPrefix);
+
+    // only rest transport will set trace id
+    testTraceIdOnNotSetBefore(template, cseUrlPrefix);
+
   }
 
   private void testCodeFirstUserMap(RestTemplate template, String cseUrlPrefix) {
@@ -152,10 +164,6 @@ public class CodeFirstRestTemplate {
     TestMgr.check(new Date(date.getTime() + seconds * 1000), result);
   }
 
-  protected void testExtend(RestTemplate template, String cseUrlPrefix) {
-
-  }
-
   protected void testCodeFirstAddString(RestTemplate template, String cseUrlPrefix) {
     ResponseEntity<String> responseEntity =
         template.exchange(cseUrlPrefix + "addstring?s=a&s=b",
@@ -233,7 +241,7 @@ public class CodeFirstRestTemplate {
   protected void testModelFieldIgnore(RestTemplate template, String cseUrlPrefix) {
     InputModelForTestIgnore input = new InputModelForTestIgnore("input_id_rest", "input_id_content",
         new Person("inputSomeone"), new JsonObject("{\"InputJsonKey\" : \"InputJsonValue\"}"), () -> {
-    });
+        });
     OutputModelForTestIgnore output = template
         .postForObject(cseUrlPrefix + "ignore", input, OutputModelForTestIgnore.class);
 
diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/TemplateResponse.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/EmptyObject.java
similarity index 78%
rename from demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/TemplateResponse.java
rename to demo/demo-schema/src/main/java/org/apache/servicecomb/demo/EmptyObject.java
index cf19bce..2c1baa4 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/TemplateResponse.java
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/EmptyObject.java
@@ -14,18 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.servicecomb.demo;
 
-package org.apache.servicecomb.demo.springmvc.server;
+public class EmptyObject {
 
-public class TemplateResponse<T> {
-  private T value;
-
-  public T getValue() {
-    return value;
-  }
-
-  public void setValue(T value) {
-    this.value = value;
-  }
-  
 }
diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java
index 1449ef5..c72bb36 100644
--- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java
@@ -40,6 +40,10 @@ public class TestMgr {
   }
 
   public static void check(Object expect, Object real) {
+    if (expect == real) {
+      return;
+    }
+
     String strExpect = String.valueOf(expect);
     String strReal = String.valueOf(real);
 
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
index b3c0053..9076f85 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
@@ -35,10 +35,8 @@ import org.apache.servicecomb.demo.CodeFirstRestTemplate;
 import org.apache.servicecomb.demo.TestMgr;
 import org.apache.servicecomb.foundation.common.part.FilePart;
 import org.apache.servicecomb.provider.pojo.Invoker;
-import org.apache.servicecomb.provider.pojo.RpcReference;
 import org.apache.servicecomb.provider.springmvc.reference.CseHttpEntity;
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
-import org.apache.servicecomb.swagger.invocation.Response;
 import org.springframework.core.io.FileSystemResource;
 import org.springframework.core.io.PathResource;
 import org.springframework.core.io.Resource;
@@ -66,8 +64,9 @@ public class CodeFirstRestTemplateSpringmvc extends CodeFirstRestTemplate {
   private UploadStreamAndResource uploadStreamAndResource =
       Invoker.createProxy("springmvc", "codeFirst", UploadStreamAndResource.class);
 
-  @RpcReference(microserviceName = "springmvc", schemaId = "codeFirst")
-  private CodeFirstSprigmvcIntf intf;
+  private TestResponse testResponse = new TestResponse();
+
+  private TestObject testObject = new TestObject();
 
   @Override
   protected void testOnlyRest(RestTemplate template, String cseUrlPrefix) {
@@ -77,17 +76,30 @@ public class CodeFirstRestTemplateSpringmvc extends CodeFirstRestTemplate {
       throw new IllegalStateException(e);
     }
 
+    testResponse.runRest();
+    testObject.runRest();
+
     super.testOnlyRest(template, cseUrlPrefix);
   }
 
   @Override
-  protected void testExtend(RestTemplate template, String cseUrlPrefix) {
-    super.testExtend(template, cseUrlPrefix);
+  protected void testOnlyHighway(RestTemplate template, String cseUrlPrefix) {
+    testResponse.runHighway();
+    testObject.runHighway();
+
+    super.testOnlyHighway(template, cseUrlPrefix);
+  }
+
+  @Override
+  protected void testAllTransport(String microserviceName, RestTemplate template, String cseUrlPrefix) {
+    testResponse.runAllTransport();
+    testObject.runAllTransport();
 
     testResponseEntity("springmvc", template, cseUrlPrefix);
     testCodeFirstTestForm(template, cseUrlPrefix);
-    testIntf();
     testFallback(template, cseUrlPrefix);
+
+    super.testAllTransport(microserviceName, template, cseUrlPrefix);
   }
 
   private void testUpload(RestTemplate template, String cseUrlPrefix) throws IOException {
@@ -167,24 +179,6 @@ public class CodeFirstRestTemplateSpringmvc extends CodeFirstRestTemplate {
     TestMgr.check(result, "mockedreslut");
   }
 
-  private void testIntf() {
-    Date date = new Date();
-
-    String srcName = RegistryUtils.getMicroservice().getServiceName();
-
-    ResponseEntity<Date> responseEntity = intf.responseEntity(date);
-    TestMgr.check(date, responseEntity.getBody());
-    TestMgr.check("h1v " + srcName, responseEntity.getHeaders().getFirst("h1"));
-    TestMgr.check("h2v " + srcName, responseEntity.getHeaders().getFirst("h2"));
-
-    checkStatusCode("springmvc", 202, responseEntity.getStatusCode());
-
-    Response cseResponse = intf.cseResponse();
-    TestMgr.check("User [name=nameA, age=100, index=0]", cseResponse.getResult());
-    TestMgr.check("h1v " + srcName, cseResponse.getHeaders().getFirst("h1"));
-    TestMgr.check("h2v " + srcName, cseResponse.getHeaders().getFirst("h2"));
-  }
-
   private void testResponseEntity(String microserviceName, RestTemplate template, String cseUrlPrefix) {
     Map<String, Object> body = new HashMap<>();
     Date date = new Date();
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstSprigmvcIntf.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstSprigmvcIntf.java
index e173873..12b6b54 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstSprigmvcIntf.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstSprigmvcIntf.java
@@ -17,7 +17,13 @@
 package org.apache.servicecomb.demo.springmvc.client;
 
 import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
+import javax.xml.ws.Holder;
+
+import org.apache.servicecomb.demo.EmptyObject;
+import org.apache.servicecomb.demo.server.User;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.springframework.http.ResponseEntity;
 
@@ -25,4 +31,16 @@ public interface CodeFirstSprigmvcIntf {
   ResponseEntity<Date> responseEntity(Date date);
 
   Response cseResponse();
+
+  Object testObject(Object input);
+
+  EmptyObject testEmpty(EmptyObject input);
+
+  Map<String, Object> testMapObject(Map<String, Object> input);
+
+  List<Object> testListObject(List<Object> input);
+
+  Holder<Object> testHolderObject(Holder<Object> input);
+
+  Holder<User> testGeneric(Holder<User> input);
 }
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestObject.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestObject.java
new file mode 100644
index 0000000..9082005
--- /dev/null
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestObject.java
@@ -0,0 +1,196 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.ws.Holder;
+
+import org.apache.servicecomb.demo.EmptyObject;
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.demo.server.User;
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate;
+import org.springframework.web.client.RestTemplate;
+
+public class TestObject {
+  private CodeFirstSprigmvcIntf intf;
+
+  private RestTemplate restTemplate = new CseRestTemplate();
+
+  private String prefix = "cse://springmvc/codeFirstSpringmvc";
+
+  public TestObject() {
+    intf = Invoker.createProxy("springmvc", "codeFirst", CodeFirstSprigmvcIntf.class);
+  }
+
+  public void runRest() {
+    testEmptyObject_rest();
+    testMapObject_rest();
+  }
+
+  public void runHighway() {
+    testEmptyObject_highway();
+    testMapObject_highway();
+  }
+
+  public void runAllTransport() {
+    testObject();
+    testListObject();
+    testHolderObject();
+    testGeneric();
+  }
+
+  @SuppressWarnings("unchecked")
+  private void testGeneric() {
+    Holder<User> holder = new Holder<>(new User());
+    Holder<User> result = intf.testGeneric(holder);
+    TestMgr.check("{name=nameA, age=100, index=0, names=null}", result.value);
+
+    result = restTemplate.postForObject(prefix + "/generic", holder, Holder.class);
+    TestMgr.check("{name=nameA, age=100, index=0, names=null}", result.value);
+  }
+
+  @SuppressWarnings("unchecked")
+  private void testHolderObject() {
+    Holder<Object> holder = new Holder<>("v");
+    Holder<Object> result = intf.testHolderObject(holder);
+    TestMgr.check("v", result.value);
+
+    result = restTemplate.postForObject(prefix + "/holderObject", holder, Holder.class);
+    TestMgr.check("v", result.value);
+  }
+
+  @SuppressWarnings("unchecked")
+  private void testListObject() {
+    List<Object> list = Collections.singletonList("v");
+    List<Object> result = intf.testListObject(list);
+    TestMgr.check("[v]", result);
+    TestMgr.check(ArrayList.class, result.getClass());
+
+    result = restTemplate.postForObject(prefix + "/listObject", list, List.class);
+    TestMgr.check("[v]", result);
+    TestMgr.check(ArrayList.class, result.getClass());
+  }
+
+  @SuppressWarnings("unchecked")
+  private void testMapObject_rest() {
+    Map<String, Object> map = Collections.singletonMap("k", "v");
+    Map<String, Object> result = intf.testMapObject(map);
+    TestMgr.check("{k=v}", result);
+    TestMgr.check(LinkedHashMap.class, result.getClass());
+
+    result = restTemplate.postForObject(prefix + "/mapObject", map, Map.class);
+    TestMgr.check("{k=v}", result);
+    TestMgr.check(LinkedHashMap.class, result.getClass());
+  }
+
+  @SuppressWarnings("unchecked")
+  private void testMapObject_highway() {
+    Map<String, Object> map = Collections.singletonMap("k", "v");
+    Map<String, Object> result = intf.testMapObject(map);
+    TestMgr.check("{k=v}", result);
+    TestMgr.check(HashMap.class, result.getClass());
+
+    result = restTemplate.postForObject(prefix + "/mapObject", map, Map.class);
+    TestMgr.check("{k=v}", result);
+    TestMgr.check(HashMap.class, result.getClass());
+  }
+
+  private void testEmptyObject_highway() {
+    // protobuf can not express empty/null
+    // everything empty will be null
+    EmptyObject result = intf.testEmpty(new EmptyObject());
+    TestMgr.check(null, result);
+
+    result = restTemplate.postForObject(prefix + "/emptyObject", new EmptyObject(), EmptyObject.class);
+    TestMgr.check(null, result);
+  }
+
+  private void testEmptyObject_rest() {
+    EmptyObject result = intf.testEmpty(new EmptyObject());
+    TestMgr.check(EmptyObject.class, result.getClass());
+
+    result = restTemplate.postForObject(prefix + "/emptyObject", new EmptyObject(), EmptyObject.class);
+    TestMgr.check(EmptyObject.class, result.getClass());
+  }
+
+  @SuppressWarnings("unchecked")
+  private void testObject() {
+    // int
+    Object result = intf.testObject(1);
+    TestMgr.check(1, result);
+    TestMgr.check(Integer.class, result.getClass());
+
+    result = restTemplate.postForObject(prefix + "/object", 1, Integer.class);
+    TestMgr.check(1, result);
+    TestMgr.check(Integer.class, result.getClass());
+
+    // string
+    result = intf.testObject("str");
+    TestMgr.check("str", result);
+    TestMgr.check(String.class, result.getClass());
+
+    result = restTemplate.postForObject(prefix + "/object", "str", String.class);
+    TestMgr.check("str", result);
+    TestMgr.check(String.class, result.getClass());
+
+    // emptyObject
+    result = intf.testObject(new EmptyObject());
+    TestMgr.check("{}", result);
+    TestMgr.check(LinkedHashMap.class, result.getClass());
+
+    result = restTemplate.postForObject(prefix + "/object", new EmptyObject(), EmptyObject.class);
+    TestMgr.check("{}", result);
+    TestMgr.check(LinkedHashMap.class, result.getClass());
+
+    // map
+    Map<String, String> map = Collections.singletonMap("k", "v");
+    result = intf.testObject(map);
+    TestMgr.check("{k=v}", result);
+    TestMgr.check(LinkedHashMap.class, result.getClass());
+
+    result = restTemplate.postForObject(prefix + "/object", map, Map.class);
+    TestMgr.check("{k=v}", result);
+    TestMgr.check(LinkedHashMap.class, result.getClass());
+
+    // list
+    List<String> list = Collections.singletonList("v");
+    result = intf.testObject(list);
+    TestMgr.check("[v]", result);
+    TestMgr.check(ArrayList.class, result.getClass());
+
+    result = restTemplate.postForObject(prefix + "/object", list, List.class);
+    TestMgr.check("[v]", result);
+    TestMgr.check(ArrayList.class, result.getClass());
+
+    // generic
+    Holder<String> holder = new Holder<>("v");
+    result = intf.testObject(holder);
+    TestMgr.check("v", ((Map<String, String>) result).get("value"));
+    TestMgr.check(LinkedHashMap.class, result.getClass());
+
+    result = restTemplate.postForObject(prefix + "/object", holder, Holder.class);
+    TestMgr.check("v", ((Map<String, String>) result).get("value"));
+    TestMgr.check(LinkedHashMap.class, result.getClass());
+  }
+}
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestResponse.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestResponse.java
new file mode 100644
index 0000000..4036bed
--- /dev/null
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestResponse.java
@@ -0,0 +1,65 @@
+/*
+ * 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 java.util.Date;
+
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.springframework.http.ResponseEntity;
+
+public class TestResponse {
+  private CodeFirstSprigmvcIntf intf;
+
+  public TestResponse() {
+    intf = Invoker.createProxy("springmvc", "codeFirst", CodeFirstSprigmvcIntf.class);
+  }
+
+  public void runRest() {
+  }
+
+  public void runHighway() {
+  }
+
+  public void runAllTransport() {
+    testResponseEntity();
+    testCseResponse();
+  }
+
+  private void testCseResponse() {
+    String srcName = RegistryUtils.getMicroservice().getServiceName();
+    Response cseResponse = intf.cseResponse();
+    TestMgr.check("User [name=nameA, age=100, index=0]", cseResponse.getResult());
+    TestMgr.check("h1v " + srcName, cseResponse.getHeaders().getFirst("h1"));
+    TestMgr.check("h2v " + srcName, cseResponse.getHeaders().getFirst("h2"));
+  }
+
+  private void testResponseEntity() {
+    Date date = new Date();
+
+    String srcName = RegistryUtils.getMicroservice().getServiceName();
+
+    ResponseEntity<Date> responseEntity = intf.responseEntity(date);
+    TestMgr.check(date, responseEntity.getBody());
+    TestMgr.check("h1v " + srcName, responseEntity.getHeaders().getFirst("h1"));
+    TestMgr.check("h2v " + srcName, responseEntity.getHeaders().getFirst("h2"));
+
+    TestMgr.check(202, responseEntity.getStatusCode());
+  }
+}
diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
index 7286bf3..aceba90 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
@@ -28,10 +28,12 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.Part;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response.Status;
+import javax.xml.ws.Holder;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
 import org.apache.servicecomb.core.Const;
+import org.apache.servicecomb.demo.EmptyObject;
 import org.apache.servicecomb.demo.compute.Person;
 import org.apache.servicecomb.demo.ignore.InputModelForTestIgnore;
 import org.apache.servicecomb.demo.ignore.OutputModelForTestIgnore;
@@ -161,11 +163,6 @@ public class CodeFirstSpringmvc {
     return userMap;
   }
 
-  @RequestMapping(path = "/testUserMapGeneric", method = RequestMethod.POST)
-  public TemplateResponse<String> testUserMapGeneric(@RequestBody Map<String, User> userMap) {
-    return null;
-  }
-
   @RequestMapping(path = "/textPlain", method = RequestMethod.POST, consumes = MediaType.TEXT_PLAIN_VALUE)
   public String textPlain(@RequestBody String body) {
     return body;
@@ -308,7 +305,7 @@ public class CodeFirstSpringmvc {
     return new OutputModelForTestIgnore("output_id", input.getInputId(), input.getContent(), input.getInputObject(),
         input.getInputJsonObject(), input.getInputIgnoreInterface(),
         new Person("outputSomeone"), new JsonObject("{\"OutputJsonKey\" : \"OutputJsonValue\"}"), () -> {
-    });
+        });
   }
 
   @SuppressWarnings("unchecked")
@@ -364,4 +361,34 @@ public class CodeFirstSpringmvc {
   public String getTraceId() {
     return ContextUtils.getInvocationContext().getContext(Const.TRACE_ID_NAME);
   }
+
+  @PostMapping(path = "/emptyObject")
+  public EmptyObject testEmpty(@RequestBody EmptyObject input) {
+    return input;
+  }
+
+  @PostMapping(path = "/object")
+  public Object testObject(@RequestBody Object input) {
+    return input;
+  }
+
+  @PostMapping(path = "/mapObject")
+  public Map<String, Object> testMapObject(@RequestBody Map<String, Object> input) {
+    return input;
+  }
+
+  @PostMapping(path = "/listObject")
+  public List<Object> testListObject(@RequestBody List<Object> input) {
+    return input;
+  }
+
+  @PostMapping(path = "/holderObject")
+  public Holder<Object> testHolderObject(@RequestBody Holder<Object> input) {
+    return input;
+  }
+
+  @PostMapping(path = "/generic")
+  public Holder<User> testGeneric(@RequestBody Holder<User> input) {
+    return input;
+  }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@servicecomb.apache.org" <co...@servicecomb.apache.org>.