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());