You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2020/01/16 11:39:40 UTC

[servicecomb-java-chassis] 01/02: [SCB-1727]support encode/decode Object(Any) types

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 3dd9fc0115150c39595a4e654fc0d477a080bbae
Author: liubao <bi...@qq.com>
AuthorDate: Thu Jan 16 10:18:09 2020 +0800

    [SCB-1727]support encode/decode Object(Any) types
---
 .../protobuf/definition/OperationProtobuf.java     | 10 +--
 .../definition/RequestRootDeserializer.java        |  7 +-
 .../definition/ResponseRootDeserializer.java       | 24 ++++---
 .../internal/converter/TestSchemaMetaCodec.java    | 81 ++++++++++++++++++++--
 .../converter/TestSchemaMetaCodecRestTemplate.java |  8 ++-
 .../servicecomb/demo/pojo/client/TestWeakPojo.java | 36 ++++++++--
 .../servicecomb/demo/pojo/server/WeakPojo.java     |  4 ++
 .../demo/springmvc/client/TestObject.java          | 19 ++---
 .../foundation/protobuf/internal/ProtoUtils.java   |  4 ++
 .../internal/schema/any/AnyEntrySchema.java        | 47 +++++++++++--
 .../protobuf/internal/schema/any/AnySchema.java    |  4 +-
 .../deserializer/DeserializerSchemaManager.java    |  7 +-
 .../repeated/impl/AnyRepeatedReadSchemas.java      |  2 +-
 .../schema/serializer/SerializerSchemaManager.java |  5 ++
 .../protobuf/internal/schema/TestAnySchema.java    |  3 +-
 .../foundation/test/scaffolding/model/People.java  | 24 ++-----
 .../transport/highway/HighwayCodec.java            |  2 +-
 17 files changed, 218 insertions(+), 69 deletions(-)

diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java
index eb6e22c..e475712 100644
--- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java
+++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java
@@ -29,6 +29,8 @@ import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.foundation.protobuf.ProtoMapper;
 import org.apache.servicecomb.foundation.protobuf.internal.ProtoUtils;
 
+import com.fasterxml.jackson.databind.JavaType;
+
 import io.protostuff.compiler.model.Message;
 
 @SuppressWarnings("rawtypes")
@@ -123,7 +125,7 @@ public class OperationProtobuf {
     ProtoMapper mapper = scopedProtobufSchemaManager.getOrCreateProtoMapper(operationMeta.getSchemaMeta());
     Message responseMessage = mapper.getResponseMessage(operationMeta.getOperationId());
 
-    Type responseType = operationMeta.getResponsesMeta().findResponseType(Status.OK.getStatusCode());
+    JavaType responseType = operationMeta.getResponsesMeta().findResponseType(Status.OK.getStatusCode());
     if (operationMeta.getSwaggerProducerOperation() != null) {
       if (ProtoUtils.isWrapProperty(responseMessage)) {
         responseRootSerializer = new ResponseRootSerializer(
@@ -142,18 +144,18 @@ public class OperationProtobuf {
         responseRootSerializer = new ResponseRootSerializer(
             mapper.createRootSerializer(responseMessage, responseType), true, false);
         responseRootDeserializer = new ResponseRootDeserializer<>(
-            mapper.createRootDeserializer(responseMessage, responseType), true, false);
+            mapper.createRootDeserializer(responseMessage, responseType), false);
       } else {
         if (ProtoUtils.isEmptyMessage(responseMessage)) {
           responseRootSerializer = new ResponseRootSerializer(mapper.createRootSerializer(responseMessage,
               Object.class), false, false);
           responseRootDeserializer = new ResponseRootDeserializer<>(
-              mapper.createRootDeserializer(responseMessage, Object.class), false, true);
+              mapper.createRootDeserializer(responseMessage, Object.class), true);
         } else {
           responseRootSerializer = new ResponseRootSerializer(mapper.createRootSerializer(responseMessage,
               responseType), false, false);
           responseRootDeserializer = new ResponseRootDeserializer<>(
-              mapper.createRootDeserializer(responseMessage, responseType), false, false);
+              mapper.createRootDeserializer(responseMessage, responseType), false);
         }
       }
     }
diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootDeserializer.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootDeserializer.java
index 049c7c0..c8b70f4 100644
--- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootDeserializer.java
+++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootDeserializer.java
@@ -21,6 +21,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.protobuf.RootDeserializer;
+import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyWrapper;
 
 public class RequestRootDeserializer<T> {
   private boolean wrapArgument;
@@ -42,7 +43,11 @@ public class RequestRootDeserializer<T> {
         return null;
       }
       Map<String, Object> result = new HashMap<>(1);
-      result.put(parameterName, rootDeserializer.deserialize(bytes));
+      Object obj = rootDeserializer.deserialize(bytes);
+      if (obj instanceof PropertyWrapper) {
+        obj = ((PropertyWrapper) obj).getValue();
+      }
+      result.put(parameterName, obj);
       return result;
     } else {
       return (Map<String, Object>) rootDeserializer.deserialize(bytes);
diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootDeserializer.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootDeserializer.java
index 467b07c..f32a010 100644
--- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootDeserializer.java
+++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootDeserializer.java
@@ -18,33 +18,37 @@ package org.apache.servicecomb.codec.protobuf.definition;
 
 import java.io.IOException;
 
+import org.apache.servicecomb.foundation.common.utils.JsonUtils;
 import org.apache.servicecomb.foundation.protobuf.RootDeserializer;
 import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyWrapper;
 
-public class ResponseRootDeserializer<T> {
-  private boolean wrapProperty;
+import com.fasterxml.jackson.databind.JavaType;
 
+public class ResponseRootDeserializer<T> {
   private RootDeserializer<T> rootDeserializer;
 
   private boolean empty;
 
-  public ResponseRootDeserializer(RootDeserializer<T> rootDeserializer, boolean wrapProperty, boolean empty) {
+  public ResponseRootDeserializer(RootDeserializer<T> rootDeserializer, boolean empty) {
     this.rootDeserializer = rootDeserializer;
-    this.wrapProperty = wrapProperty;
     this.empty = empty;
   }
 
   @SuppressWarnings("unchecked")
-  public T deserialize(byte[] bytes) throws IOException {
+  public T deserialize(byte[] bytes, JavaType invocationTimeType) throws IOException {
     if (empty) {
-      T a = rootDeserializer.deserialize(bytes); // read buffers if possible.
+      rootDeserializer.deserialize(bytes); // read buffers if possible.
       return null;
     }
 
-    if (wrapProperty) {
-      return ((PropertyWrapper<T>) rootDeserializer.deserialize(bytes)).getValue();
-    } else {
-      return rootDeserializer.deserialize(bytes);
+    Object obj = rootDeserializer.deserialize(bytes);
+    if (obj instanceof PropertyWrapper) {
+      obj = ((PropertyWrapper) obj).getValue();
+    }
+    if (obj != null && !invocationTimeType.isPrimitive() && !invocationTimeType.getRawClass()
+        .isAssignableFrom(obj.getClass())) {
+      obj = JsonUtils.convertValue(obj, invocationTimeType.getRawClass());
     }
+    return (T) obj;
   }
 }
diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java
index 4d74073..01823e9 100644
--- a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java
+++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java
@@ -38,8 +38,10 @@ import org.apache.servicecomb.codec.protobuf.internal.converter.model.ProtoSchem
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.definition.SchemaMeta;
+import org.apache.servicecomb.foundation.protobuf.internal.ProtoConst;
 import org.apache.servicecomb.foundation.test.scaffolding.model.Color;
 import org.apache.servicecomb.foundation.test.scaffolding.model.Empty;
+import org.apache.servicecomb.foundation.test.scaffolding.model.People;
 import org.apache.servicecomb.foundation.test.scaffolding.model.User;
 import org.apache.servicecomb.swagger.engine.SwaggerConsumer;
 import org.apache.servicecomb.swagger.engine.SwaggerConsumerOperation;
@@ -53,6 +55,8 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
 import io.swagger.models.Swagger;
 import mockit.Expectations;
 import mockit.Injectable;
@@ -166,13 +170,15 @@ public class TestSchemaMetaCodec {
     ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200);
     values = responseSerializer.serialize(user);
     ResponseRootDeserializer<Object> responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200);
-    User decodedUser = (User) responseDeserializer.deserialize(values);
+    User decodedUser = (User) responseDeserializer
+        .deserialize(values, TypeFactory.defaultInstance().constructType(User.class));
     Assert.assertEquals(user.name, decodedUser.name);
     Assert.assertEquals(user.friends.get(0).name, decodedUser.friends.get(0).name);
 
     user.friends = new ArrayList<>();
     values = responseSerializer.serialize(user);
-    decodedUser = (User) responseDeserializer.deserialize(values);
+    decodedUser = (User) responseDeserializer
+        .deserialize(values, TypeFactory.defaultInstance().constructType(User.class));
     Assert.assertEquals(user.name, decodedUser.name);
     // proto buffer encode and decode empty list to be null
     Assert.assertEquals(null, decodedUser.friends);
@@ -236,13 +242,13 @@ public class TestSchemaMetaCodec {
     ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200);
     values = responseSerializer.serialize(userMap);
     ResponseRootDeserializer<Object> responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200);
-    Map<String, User> decodedUser = (Map<String, User>) responseDeserializer.deserialize(values);
+    Map<String, User> decodedUser = (Map<String, User>) responseDeserializer.deserialize(values, ProtoConst.MAP_TYPE);
     Assert.assertEquals(user.name, decodedUser.get("test").name);
     Assert.assertEquals(user.friends.get(0).name, decodedUser.get("test").friends.get(0).name);
 
     user.friends = new ArrayList<>();
     values = responseSerializer.serialize(userMap);
-    decodedUser = (Map<String, User>) responseDeserializer.deserialize(values);
+    decodedUser = (Map<String, User>) responseDeserializer.deserialize(values, ProtoConst.MAP_TYPE);
     Assert.assertEquals(user.name, decodedUser.get("test").name);
     // proto buffer encode and decode empty list to be null
     Assert.assertEquals(null, decodedUser.get("test").friends);
@@ -359,7 +365,8 @@ public class TestSchemaMetaCodec {
     ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200);
     values = responseSerializer.serialize(30);
     ResponseRootDeserializer<Object> responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200);
-    Object decodedValue = responseDeserializer.deserialize(values);
+    Object decodedValue = responseDeserializer
+        .deserialize(values, TypeFactory.defaultInstance().constructType(int.class));
     Assert.assertEquals(30, (int) decodedValue);
   }
 
@@ -432,4 +439,68 @@ public class TestSchemaMetaCodec {
       Assert.assertEquals("friend", user.friends.get(0).name);
     }
   }
+
+  @Test
+  public void testProtoSchemaOperationObjSpringMVC() throws Exception {
+    mockSchemaMeta(new SpringmvcSwaggerGenerator(ProtoSchema.class), new ProtoSchema());
+    testProtoSchemaOperationObjImpl(false);
+  }
+
+  @Test
+  public void testProtoSchemaOperationObjPOJO() throws Exception {
+    mockSchemaMeta(new PojoSwaggerGenerator(ProtoSchemaPojo.class), new ProtoSchemaPojo());
+    testProtoSchemaOperationObjImpl(true);
+  }
+
+  private void testProtoSchemaOperationObjImpl(boolean isPojo) throws IOException {
+    OperationProtobuf providerOperationProtobuf = ProtobufManager
+        .getOrCreateOperation(providerSchemaMeta.getOperations().get("obj"));
+    OperationProtobuf consumerOperationProtobuf = ProtobufManager
+        .getOrCreateOperation(consumerSchemaMeta.getOperations().get("obj"));
+    byte[] values;
+
+    // request message
+    RequestRootSerializer requestSerializer = consumerOperationProtobuf.getRequestRootSerializer();
+    Map<String, Object> args = new HashMap<>();
+    args.put("value", 2);
+
+    values = requestSerializer.serialize(args);
+    RequestRootDeserializer<Object> requestDeserializer = providerOperationProtobuf.getRequestRootDeserializer();
+    Map<String, Object> decodedArgs = requestDeserializer.deserialize(values);
+    int result = (int) decodedArgs.get("value");
+    Assert.assertEquals(2, result);
+
+    User user = new User();
+    user.name = "user";
+    User friend = new User();
+    friend.name = "friend";
+    List<User> friends = new ArrayList<>();
+    friends.add(friend);
+    user.friends = friends;
+    args.put("value", user);
+    values = requestSerializer.serialize(args);
+    decodedArgs = requestDeserializer.deserialize(values);
+    Map<String, Object> userMap = (Map<String, Object>) decodedArgs.get("value");
+    Assert.assertEquals("user", userMap.get("name"));
+    // proto buffer encode and decode empty list to be null
+    friends = (List<User>) userMap.get("friends");
+    Map<String, Object> friendMap = (Map<String, Object>) friends.get(0);
+    Assert.assertEquals("friend", friendMap.get("name"));
+
+    args.clear();
+    People people = new People();
+    people.name = "user";
+    People pFriend = new People();
+    pFriend.name = "friend";
+    List<People> pFriends = new ArrayList<>();
+    pFriends.add(pFriend);
+    people.friends = pFriends;
+    args.put("value", people);
+    values = requestSerializer.serialize(args);
+    decodedArgs = requestDeserializer.deserialize(values);
+    people = (People) decodedArgs.get("value");
+    Assert.assertEquals("user", people.name);
+    // proto buffer encode and decode empty list to be null
+    Assert.assertEquals("friend", people.friends.get(0).name);
+  }
 }
diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java
index 25d4eb4..0472b37 100644
--- a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java
+++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java
@@ -46,6 +46,8 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
 import io.swagger.models.Swagger;
 import mockit.Expectations;
 import mockit.Injectable;
@@ -123,13 +125,13 @@ public class TestSchemaMetaCodecRestTemplate {
     ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200);
     values = responseSerializer.serialize(user);
     ResponseRootDeserializer<Object> responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200);
-    User decodedUser = (User) responseDeserializer.deserialize(values);
+    User decodedUser = (User) responseDeserializer.deserialize(values, TypeFactory.defaultInstance().constructType(User.class));
     Assert.assertEquals(user.name, decodedUser.name);
     Assert.assertEquals(user.friends.get(0).name, decodedUser.friends.get(0).name);
 
     user.friends = new ArrayList<>();
     values = responseSerializer.serialize(user);
-    decodedUser = (User) responseDeserializer.deserialize(values);
+    decodedUser = (User) responseDeserializer.deserialize(values, TypeFactory.defaultInstance().constructType(User.class));
     Assert.assertEquals(user.name, decodedUser.name);
     // proto buffer encode and decode empty list to be null
     Assert.assertEquals(null, decodedUser.friends);
@@ -213,7 +215,7 @@ public class TestSchemaMetaCodecRestTemplate {
     ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200);
     values = responseSerializer.serialize(30);
     ResponseRootDeserializer<Object> responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200);
-    Object decodedValue = responseDeserializer.deserialize(values);
+    Object decodedValue = responseDeserializer.deserialize(values, TypeFactory.defaultInstance().constructType(int.class));
     Assert.assertEquals(30, (int) decodedValue);
   }
 }
diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestWeakPojo.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestWeakPojo.java
index 62bc6a3..a28c71f 100644
--- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestWeakPojo.java
+++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestWeakPojo.java
@@ -87,6 +87,10 @@ interface GenericsModelInf {
   GenericsModel genericParamsModel(int code, GenericsModel model);
 }
 
+interface ObjectInf {
+  GenericsModel obj(GenericsModel obj);
+}
+
 @Component
 public class TestWeakPojo implements CategorizedTestCase {
   @RpcReference(microserviceName = "pojo", schemaId = "WeakPojo")
@@ -101,16 +105,40 @@ public class TestWeakPojo implements CategorizedTestCase {
   @RpcReference(microserviceName = "pojo", schemaId = "WeakPojo")
   private GenericsModelInf genericsModelInf;
 
+  @RpcReference(microserviceName = "pojo", schemaId = "WeakPojo")
+  private ObjectInf objectInf;
+
   @Override
   public void testAllTransport() throws Exception {
-    getDiffName();
+    testDiffName();
 
     testGenerics();
 
-    getGenericsModel();
+    testGenericsModel();
+
+    testObject();
+  }
+
+  private void testObject() throws JsonProcessingException {
+    GenericsModel model = new GenericsModel();
+    model.setName("model");
+    List<List<String>> namesList = new ArrayList<>();
+    List<String> names = new ArrayList<>();
+    names.add("hello");
+    namesList.add(names);
+    model.setNameList(namesList);
+    List<List<List<Object>>> objectLists = new ArrayList<>();
+    List<List<Object>> objectList = new ArrayList<>();
+    List<Object> objects = new ArrayList<>();
+    objects.add("object");
+    objectList.add(objects);
+    objectLists.add(objectList);
+    model.setObjectLists(objectLists);
+    GenericsModel result = objectInf.obj(model);
+    TestMgr.check(JsonUtils.writeValueAsString(model), JsonUtils.writeValueAsString(result));
   }
 
-  private void getGenericsModel() throws JsonProcessingException {
+  private void testGenericsModel() throws JsonProcessingException {
     GenericsModel model = new GenericsModel();
     model.setName("model");
     List<List<String>> namesList = new ArrayList<>();
@@ -140,7 +168,7 @@ public class TestWeakPojo implements CategorizedTestCase {
     TestMgr.check("hello", nameListResult.get(0).get(0));
   }
 
-  private void getDiffName() {
+  private void testDiffName() {
     TestMgr.check(7, diffNames.differentName(2, 3));
     TestMgr.check(8, diffNames2.differentName(2, 3));
     Map<String, Object> args = new HashMap<>();
diff --git a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/WeakPojo.java b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/WeakPojo.java
index e884229..fc82bf1 100644
--- a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/WeakPojo.java
+++ b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/WeakPojo.java
@@ -39,4 +39,8 @@ public class WeakPojo {
   public GenericsModel genericParamsModel(int code, GenericsModel model) {
     return model;
   }
+
+  public Object obj(Object obj) {
+    return obj;
+  }
 }
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
index 5e42db7..fe36b6b 100644
--- 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
@@ -18,7 +18,6 @@ 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;
@@ -27,7 +26,6 @@ import javax.xml.ws.Holder;
 
 import org.apache.servicecomb.demo.EmptyObject;
 import org.apache.servicecomb.demo.TestMgr;
-import org.apache.servicecomb.foundation.test.scaffolding.model.Empty;
 import org.apache.servicecomb.provider.pojo.Invoker;
 import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate;
 import org.springframework.web.client.RestTemplate;
@@ -58,7 +56,7 @@ public class TestObject {
 
   public void runAllTransport() {
     // TODO : WEAK not supported now in HIGHWAY
-//    testObject();
+    testObject();
 //    testListObject();
 //    testHolderObject();
   }
@@ -149,31 +147,34 @@ public class TestObject {
 
     // emptyObject
     result = intf.testObject(new EmptyObject());
-    TestMgr.check("{}", result);
-    TestMgr.check(LinkedHashMap.class, result.getClass());
+    // result may not be an empty map in highway
+    //    TestMgr.check("{}", result);
+    TestMgr.check(true, Map.class.isAssignableFrom(result.getClass()));
 
     result = restTemplate.postForObject(prefix + "/object", new EmptyObject(), EmptyObject.class);
     TestMgr.check(EmptyObject.class, result.getClass());
+    result = restTemplate.postForObject(prefix + "/object", new EmptyObject(), EmptyObject.class);
+    TestMgr.check(EmptyObject.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());
+    TestMgr.check(true, Map.class.isAssignableFrom(result.getClass()));
 
     result = restTemplate.postForObject(prefix + "/object", map, Map.class);
     TestMgr.check("{k=v}", result);
-    TestMgr.check(LinkedHashMap.class, result.getClass());
+    TestMgr.check(true, Map.class.isAssignableFrom(result.getClass()));
 
     // list
     List<String> list = Collections.singletonList("v");
     result = intf.testObject(list);
     TestMgr.check("[v]", result);
-    TestMgr.check(ArrayList.class, result.getClass());
+    TestMgr.check(true, List.class.isAssignableFrom(result.getClass()));
 
     result = restTemplate.postForObject(prefix + "/object", list, List.class);
     TestMgr.check("[v]", result);
-    TestMgr.check(ArrayList.class, result.getClass());
+    TestMgr.check(true, List.class.isAssignableFrom(result.getClass()));
 
     // generic
     Holder<String> holder = new Holder<>("v");
diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoUtils.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoUtils.java
index 55fcd30..2d5c7e0 100644
--- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoUtils.java
+++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoUtils.java
@@ -33,6 +33,10 @@ public final class ProtoUtils {
     return protoField.getCanonicalName().equals(ProtoConst.EMPTY.getCanonicalName());
   }
 
+  public static boolean isAnyMessage(Message protoField) {
+    return protoField.getCanonicalName().equals(ProtoConst.ANY.getCanonicalName());
+  }
+
   public static boolean isAnyField(Field protoField) {
     return protoField.getType().getCanonicalName().equals(ProtoConst.ANY.getCanonicalName());
   }
diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnyEntrySchema.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnyEntrySchema.java
index e371c7c..cd89bf9 100644
--- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnyEntrySchema.java
+++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnyEntrySchema.java
@@ -17,6 +17,7 @@
 package org.apache.servicecomb.foundation.protobuf.internal.schema.any;
 
 import java.io.IOException;
+import java.lang.reflect.Type;
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
@@ -24,8 +25,10 @@ import org.apache.servicecomb.foundation.protobuf.ProtoMapper;
 import org.apache.servicecomb.foundation.protobuf.RootDeserializer;
 import org.apache.servicecomb.foundation.protobuf.RootSerializer;
 import org.apache.servicecomb.foundation.protobuf.internal.ProtoConst;
+import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyWrapper;
 
 import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.type.TypeFactory;
 
 import io.protostuff.InputEx;
 import io.protostuff.OutputEx;
@@ -47,8 +50,11 @@ public class AnyEntrySchema implements SchemaEx<Object> {
 
   private final int valueTag = WireFormat.makeTag(2, WireFormat.WIRETYPE_LENGTH_DELIMITED);
 
-  public AnyEntrySchema(ProtoMapper protoMapper) {
+  private Type anyTargetType;
+
+  public AnyEntrySchema(ProtoMapper protoMapper, Type type) {
     this.protoMapper = protoMapper;
+    this.anyTargetType = type;
   }
 
   @Override
@@ -57,6 +63,11 @@ public class AnyEntrySchema implements SchemaEx<Object> {
   }
 
   @Override
+  public Object newMessage() {
+    return new PropertyWrapper<>();
+  }
+
+  @Override
   public void mergeFrom(InputEx input, Object message) throws IOException {
     input.readFieldNumber();
     String typeUrl = input.readString();
@@ -66,12 +77,19 @@ public class AnyEntrySchema implements SchemaEx<Object> {
 
     input.readFieldNumber();
 
-    AnyEntry anyEntry = (AnyEntry) message;
-    anyEntry.setTypeUrl(typeUrl);
-    anyEntry.setValue(bytes);
+    if (message instanceof PropertyWrapper) {
+      if (typeUrl.startsWith(ProtoConst.PACK_SCHEMA)) {
+        ((PropertyWrapper) message).setValue(standardUnpack(typeUrl, bytes));
+      } else {
+        ((PropertyWrapper) message).setValue(jsonExtendMergeFrom(typeUrl, bytes));
+      }
+    } else if (message instanceof AnyEntry) {
+      ((AnyEntry) message).setTypeUrl(typeUrl);
+      ((AnyEntry) message).setValue(bytes);
+    }
   }
 
-  public Object deseriaze(InputEx input) throws IOException {
+  public Object deserialize(InputEx input) throws IOException {
     AnyEntry anyEntry = new AnyEntry();
     input.mergeObject(anyEntry, this);
 
@@ -101,12 +119,27 @@ public class AnyEntrySchema implements SchemaEx<Object> {
           "can not find proto message to create deserializer, name=" + msgCanonicalName);
     }
 
-    JavaType javaType = protoMapper.getAnyTypes().getOrDefault(msgCanonicalName, ProtoConst.MAP_TYPE);
+    JavaType javaType = protoMapper.getAnyTypes()
+        .getOrDefault(msgCanonicalName, constructRuntimeType(ProtoConst.MAP_TYPE));
     return protoMapper.createRootDeserializer(message, javaType);
   }
 
   protected Object jsonExtendMergeFrom(String typeUrl, byte[] bytes) throws IOException {
-    return protoMapper.getJsonMapper().readValue(bytes, Object.class);
+    try {
+      return protoMapper.getJsonMapper()
+          .readValue(bytes, Class.forName(typeUrl.substring(ProtoConst.JSON_SCHEMA.length())));
+    } catch (ClassNotFoundException e) {
+      return protoMapper.getJsonMapper()
+          .readValue(bytes, constructRuntimeType(ProtoConst.OBJECT_TYPE));
+    }
+  }
+
+  private JavaType constructRuntimeType(JavaType defaultType) {
+    if (this.anyTargetType == null) {
+      return defaultType;
+    } else {
+      return TypeFactory.defaultInstance().constructType(anyTargetType);
+    }
   }
 
   protected String getInputActualTypeName(Object input) {
diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnySchema.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnySchema.java
index 41ba967..87cbba9 100644
--- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnySchema.java
+++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnySchema.java
@@ -38,14 +38,14 @@ public class AnySchema<T> extends FieldSchema<T> {
   public AnySchema(ProtoMapper protoMapper, Field protoField, PropertyDescriptor propertyDescriptor) {
     super(protoField, propertyDescriptor.getJavaType());
 
-    this.anyEntrySchema = new AnyEntrySchema(protoMapper);
+    this.anyEntrySchema = new AnyEntrySchema(protoMapper, null);
     this.getter = propertyDescriptor.getGetter();
     this.setter = propertyDescriptor.getSetter();
   }
 
   @Override
   public final int mergeFrom(InputEx input, T message) throws IOException {
-    Object anyValue = anyEntrySchema.deseriaze(input);
+    Object anyValue = anyEntrySchema.deserialize(input);
     setter.set(message, anyValue);
 
     return input.readFieldNumber();
diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java
index 5757abd..8408c54 100644
--- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java
+++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java
@@ -23,6 +23,7 @@ import java.util.Map;
 
 import org.apache.servicecomb.foundation.protobuf.ProtoMapper;
 import org.apache.servicecomb.foundation.protobuf.RootDeserializer;
+import org.apache.servicecomb.foundation.protobuf.RootSerializer;
 import org.apache.servicecomb.foundation.protobuf.internal.ProtoConst;
 import org.apache.servicecomb.foundation.protobuf.internal.ProtoUtils;
 import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyDescriptor;
@@ -99,6 +100,10 @@ public class DeserializerSchemaManager extends SchemaManager {
   }
 
   public <T> RootDeserializer<T> createRootDeserializer(Message message, Type type) {
+    if (ProtoUtils.isAnyMessage(message)) {
+      SchemaEx<Object> messageSchema = new AnyEntrySchema(protoMapper, type);
+      return new RootDeserializer(messageSchema);
+    }
     JavaType javaType = TypeFactory.defaultInstance().constructType(type);
     SchemaEx<T> messageSchema = getOrCreateMessageSchema(message, javaType);
     return new RootDeserializer<>(messageSchema);
@@ -226,7 +231,7 @@ public class DeserializerSchemaManager extends SchemaManager {
     }
 
     if (ProtoUtils.isAnyField(protoField)) {
-      AnyEntrySchema anyEntrySchema = new AnyEntrySchema(protoMapper);
+      AnyEntrySchema anyEntrySchema = new AnyEntrySchema(protoMapper, null);
       return AnyRepeatedReadSchemas.create(protoField, propertyDescriptor, anyEntrySchema);
     }
 
diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/impl/AnyRepeatedReadSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/impl/AnyRepeatedReadSchemas.java
index 27251ba..cdfba2a 100644
--- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/impl/AnyRepeatedReadSchemas.java
+++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/impl/AnyRepeatedReadSchemas.java
@@ -31,7 +31,7 @@ public class AnyRepeatedReadSchemas {
 
       collectionReader = (input, collection) -> {
         while (true) {
-          Object value = anyEntrySchema.deseriaze(input);
+          Object value = anyEntrySchema.deserialize(input);
           collection.add(value);
 
           int fieldNumber = input.readFieldNumber();
diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java
index b71ddea..15734bf 100644
--- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java
+++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java
@@ -27,6 +27,7 @@ import org.apache.servicecomb.foundation.protobuf.internal.ProtoConst;
 import org.apache.servicecomb.foundation.protobuf.internal.ProtoUtils;
 import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyDescriptor;
 import org.apache.servicecomb.foundation.protobuf.internal.schema.SchemaManager;
+import org.apache.servicecomb.foundation.protobuf.internal.schema.any.AnyEntrySchema;
 import org.apache.servicecomb.foundation.protobuf.internal.schema.any.AnySchema;
 import org.apache.servicecomb.foundation.protobuf.internal.schema.serializer.repeated.impl.AnyRepeatedWriteSchemas;
 import org.apache.servicecomb.foundation.protobuf.internal.schema.serializer.repeated.impl.BytesRepeatedWriteSchemas;
@@ -93,6 +94,10 @@ public class SerializerSchemaManager extends SchemaManager {
   }
 
   public RootSerializer createRootSerializer(Message message, Type type) {
+    if (ProtoUtils.isAnyMessage(message)) {
+      SchemaEx<Object> messageSchema = new AnyEntrySchema(protoMapper, type);
+      return new RootSerializer(messageSchema);
+    }
     JavaType javaType = TypeFactory.defaultInstance().constructType(type);
     SchemaEx<Object> messageSchema = getOrCreateMessageSchema(message, javaType);
     return new RootSerializer(messageSchema);
diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestAnySchema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestAnySchema.java
index ebdc754..441bf2f 100644
--- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestAnySchema.java
+++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestAnySchema.java
@@ -22,6 +22,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.protobuf.RootDeserializer;
+import org.apache.servicecomb.foundation.protobuf.internal.ProtoConst;
 import org.apache.servicecomb.foundation.protobuf.internal.TestSchemaBase;
 import org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot;
 import org.apache.servicecomb.foundation.protobuf.internal.model.Root;
@@ -63,7 +64,7 @@ public class TestAnySchema extends TestSchemaBase {
     check();
 
     Map<String, Object> map = new HashMap<>();
-    map.put("@type", "User");
+    map.put(ProtoConst.JSON_ID_NAME, "User");
     map.put("name", "n1");
     Root root = new Root();
     root.setAny(map);
diff --git a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/WeakPojo.java b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/model/People.java
similarity index 54%
copy from demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/WeakPojo.java
copy to foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/model/People.java
index e884229..e5600ce 100644
--- a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/WeakPojo.java
+++ b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/model/People.java
@@ -15,28 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.demo.pojo.server;
+package org.apache.servicecomb.foundation.test.scaffolding.model;
 
 import java.util.List;
 
-import org.apache.servicecomb.demo.server.GenericsModel;
-import org.apache.servicecomb.provider.pojo.RpcSchema;
+public class People {
+  public String name;
 
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-
-@RpcSchema(schemaId = "WeakPojo")
-public class WeakPojo {
-  @ApiOperation(value = "differentName", nickname = "differentName")
-  public int diffNames(@ApiParam(name = "x") int a, @ApiParam(name = "y") int b) {
-    return a * 2 + b;
-  }
-
-  public List<List<String>> genericParams(int code, List<List<String>> names) {
-    return names;
-  }
-
-  public GenericsModel genericParamsModel(int code, GenericsModel model) {
-    return model;
-  }
+  public List<People> friends;
 }
diff --git a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java
index 6d06e1c..fe6e026 100644
--- a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java
+++ b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java
@@ -115,7 +115,7 @@ public final class HighwayCodec {
     }
 
     ResponseRootDeserializer<Object> bodySchema = operationProtobuf.findResponseRootDeserializer(header.getStatusCode());
-    Object body = bodySchema.deserialize(tcpData.getBodyBuffer().getBytes());
+    Object body = bodySchema.deserialize(tcpData.getBodyBuffer().getBytes(), invocation.findResponseType(header.getStatusCode()));
 
     Response response = Response.create(header.getStatusCode(), header.getReasonPhrase(), body);
     response.setHeaders(header.getHeaders());